Видаліть повторювані рядки


152

Я прочитав CSVфайл у рамці R data.frame. Деякі з рядків мають однаковий елемент в одному з стовпців. Я хотів би видалити рядки, що є дублікатами в цьому стовпці. Наприклад:

platform_external_dbus          202           16                     google        1
platform_external_dbus          202           16         space-ghost.verbum        1
platform_external_dbus          202           16                  localhost        1
platform_external_dbus          202           16          users.sourceforge        8
platform_external_dbus          202           16                    hughsie        1

Я хотів би лише одного з цих рядків, оскільки інші мають ті ж дані в першому стовпці.


3
котрий саме ви хочете? тільки перший? Іншими словами: ви хочете зберегти googleабо localhostабо hughsie?
Ентоні Даміко

Для цієї частини мого статистичного аналізу це не має значення. Я лише намагаюся співвідносити назву проекту (перша колонка), кількість помилок (другий стовпчик) та кількість організацій проекту (третя колонка).
користувач1897691

3
круто. викинути непотрібні стовпчики і використовувати? унікальний
Ентоні Даміко

Відповіді:


186

просто ізолюйте ваш кадр даних до потрібних вам стовпців, а потім використовуйте унікальну функцію: D

# in the above example, you only need the first three columns
deduped.data <- unique( yourdata[ , 1:3 ] )
# the fourth column no longer 'distinguishes' them, 
# so they're duplicates and thrown out.

1
Схоже, це буде справно працювати. Чи можете ви поясніть мені, що відбувається з [,1:3]частиною цього коду? Я новачок у R, тому я запитую те, що я можу тільки припустити, це очевидне питання.
користувач1897691

6
@ user1897691 позначте це як правильне, то;) дивіться це, і якщо вам це подобається, перевірте twotorials.com
Ентоні Даміко

3
Зверніть увагу, що це видалить усі стовпці, крім трьох перших.
GuillaumeL

186

Для людей, які завітали сюди, щоб шукати загальну відповідь на видалення дублікатів рядків, використовуйте !duplicated():

a <- c(rep("A", 3), rep("B", 3), rep("C",2))
b <- c(1,1,2,4,1,1,2,2)
df <-data.frame(a,b)

duplicated(df)
[1] FALSE  TRUE FALSE FALSE FALSE  TRUE FALSE  TRUE

> df[duplicated(df), ]
  a b
2 A 1
6 B 1
8 C 2

> df[!duplicated(df), ]
  a b
1 A 1
3 A 2
4 B 4
5 B 1
7 C 2

Відповідь від: Видалення дублюваних рядків з R фрейму даних


Я хочу створити нову змінну, яка позначається, якщо у певній змінній є дублікат, майже як df $ дублікати <- ifelse (це значення рядків у стовпці a == попереднє значення рядка у колонці a, 1, 0)
jacob

@jacob побачити це питання stackoverflow.com/questions/12495345 / ...
dpel

2
Це зберігає перше з'явилося значення і видаляє решта дублікатів, правда? Або він видаляє значення випадковим чином?
News_is_Selection_Bias

@alphabetagamma так, він зберігає перше значення, яке з'явилося
Мехді Неллен

2
Якщо вас цікавлять лише дублікати у певних стовпцях, скажімо, кол 1 та 2, ми можемо використовуватиdf[!duplicated(df[, 1:2])]
qwr

82

Функція distinct()в dplyrпакеті виконує довільне видалення дублікатів або з певних стовпців / змінних (як у цьому питанні), або з урахуванням усіх стовпців / змінних. dplyrє частиною tidyverse.

Дані та пакет

library(dplyr)
dat <- data.frame(a = rep(c(1,2),4), b = rep(LETTERS[1:4],2))

Видаліть рядки, дубльовані у певному стовпці (наприклад, стовпець a)

Зауважте, що .keep_all = TRUEзберігаються всі стовпці, інакше збережеться лише стовпець a.

distinct(dat, a, .keep_all = TRUE)

  a b
1 1 A
2 2 B

Видаліть рядки, які є повними копіями інших рядків:

distinct(dat)

  a b
1 1 A
2 2 B
3 1 C
4 2 D

Великий відповідь, до речі, .keep_allдля того , щоб зберегти всі стовпці, не слід змішувати з keepв pandas.
Гол Джейсона

28

data.tableПакет також uniqueі duplicatedметоди його власний з деякими додатковими функціями.

І методи, unique.data.tableі duplicated.data.tableметоди мають додатковий byаргумент, який дозволяє передавати characterабо integerвектор імен стовпців або їх розташування відповідно

library(data.table)
DT <- data.table(id = c(1,1,1,2,2,2),
                 val = c(10,20,30,10,20,30))

unique(DT, by = "id")
#    id val
# 1:  1  10
# 2:  2  10

duplicated(DT, by = "id")
# [1] FALSE  TRUE  TRUE FALSE  TRUE  TRUE

Ще одна важлива особливість цих методів - це величезне збільшення продуктивності для великих наборів даних

library(microbenchmark)
library(data.table)
set.seed(123)
DF <- as.data.frame(matrix(sample(1e8, 1e5, replace = TRUE), ncol = 10))
DT <- copy(DF)
setDT(DT)

microbenchmark(unique(DF), unique(DT))
# Unit: microseconds
#       expr       min         lq      mean    median        uq       max neval cld
# unique(DF) 44708.230 48981.8445 53062.536 51573.276 52844.591 107032.18   100   b
# unique(DT)   746.855   776.6145  2201.657   864.932   919.489  55986.88   100  a 


microbenchmark(duplicated(DF), duplicated(DT))
# Unit: microseconds
#           expr       min         lq       mean     median        uq        max neval cld
# duplicated(DF) 43786.662 44418.8005 46684.0602 44925.0230 46802.398 109550.170   100   b
# duplicated(DT)   551.982   558.2215   851.0246   639.9795   663.658   5805.243   100  a 

7

Ви також можете використовувати функцію dplyr's distinct()! Це, як правило, більш ефективно, ніж альтернативні варіанти, особливо якщо у вас є багато спостережень.

distinct_data <- dplyr::distinct(yourdata)

1
Це та сама відповідь, що і відповідь Сема Фірка, але з меншою деталізацією.
qwr

6

загальна відповідь може бути, наприклад:

df <-  data.frame(rbind(c(2,9,6),c(4,6,7),c(4,6,7),c(4,6,7),c(2,9,6))))



new_df <- df[-which(duplicated(df)), ]

вихід:

      X1 X2 X3
    1  2  9  6
    2  4  6  7

1
Будьте обережні при використанні -which, це призведе до помилок, якщо немає дублікатів, використання df[!(duplicated(df)), ]може бути безпечнішим.
Гол Джейсона

5

З sqldf:

# Example by Mehdi Nellen
a <- c(rep("A", 3), rep("B", 3), rep("C",2))
b <- c(1,1,2,4,1,1,2,2)
df <-data.frame(a,b)

Рішення:

 library(sqldf)
    sqldf('SELECT DISTINCT * FROM df')

Вихід:

  a b
1 A 1
2 A 2
3 B 4
4 B 1
5 C 2

Це має накладні витрати зі створення всієї бази даних SQL. cran.r-project.org/web/packages/sqldf/index.html
qwr

Що ви маєте на увазі під налаштуванням цілої бази даних SQL? Це одна з головних переваг: 'з sqldf користувач звільняється від необхідності виконувати наступні дії, які автоматично виконуються: налаштування бази даних, написання оператора створення таблиці, який визначає кожну таблицю, імпорт та експорт до бази даних та з неї '. Це не оптимальне рішення, але зручне для тих, хто знайомий з SQL.
mpalanco

3

Або ви можете вкладати дані в колодки 4 і 5 в один ряд із tidyr:

library(tidyr)
df %>% nest(V4:V5)

# A tibble: 1 × 4
#                      V1    V2    V3             data
#                  <fctr> <int> <int>           <list>
#1 platform_external_dbus   202    16 <tibble [5 × 2]>

Копії 2 та 3 тепер видаляються для статистичного аналізу, але ви зберегли дані колонки 4 та 5 табл. Ви можете повернутися до початкового кадру даних у будь-якій точці unnest().


1

Видаліть повторювані рядки фрейму даних

library(dplyr)
mydata <- mtcars

# Remove duplicate rows of the dataframe
distinct(mydata)

У цьому наборі даних немає жодного повторюваного рядка, тому він повертав таку ж кількість рядків, як у моїх даних.



Видаліть повторювані рядки на основі однієї змінної

library(dplyr)
mydata <- mtcars

# Remove duplicate rows of the dataframe using carb variable
distinct(mydata,carb, .keep_all= TRUE)

Функція .keep_all використовується для збереження всіх інших змінних у кадрі вихідних даних.



Видаліть повторювані рядки на основі декількох змінних

library(dplyr)
mydata <- mtcars

# Remove duplicate rows of the dataframe using cyl and vs variables
distinct(mydata, cyl,vs, .keep_all= TRUE)

Функція .keep_all використовується для збереження всіх інших змінних у кадрі вихідних даних.

(від: http://www.datasciencemadesimple.com/remove-duplicate-rows-r-using-dplyr-distinct-function/ )


0

Цю проблему можна також вирішити, вибравши перший рядок із кожної групи, де група - це стовпці, на основі яких ми хочемо вибрати унікальні значення (у прикладі, що ділиться, це лише перший стовпець).

Використання бази R:

subset(df, ave(V2, V1, FUN = seq_along) == 1)

#                      V1  V2 V3     V4 V5
#1 platform_external_dbus 202 16 google  1

В dplyr

library(dplyr)
df %>% group_by(V1) %>% slice(1L)

Або за допомогою data.table

library(data.table)
setDT(df)[, .SD[1L], by = V1]

Якщо нам потрібно знайти унікальні рядки на основі декількох стовпців, просто додайте ці назви стовпців у групувальну частину для кожної з вищевказаних відповідей.

дані

df <- structure(list(V1 = structure(c(1L, 1L, 1L, 1L, 1L), 
.Label = "platform_external_dbus", class = "factor"), 
V2 = c(202L, 202L, 202L, 202L, 202L), V3 = c(16L, 16L, 16L, 
16L, 16L), V4 = structure(c(1L, 4L, 3L, 5L, 2L), .Label = c("google", 
"hughsie", "localhost", "space-ghost.verbum", "users.sourceforge"
), class = "factor"), V5 = c(1L, 1L, 1L, 8L, 1L)), class = "data.frame", 
row.names = c(NA, -5L))

0

Ось дуже просте, швидке dplyr/ tidyрішення:

Видаліть цілком однакові рядки:

library(dplyr)
iris %>% 
  distinct(.keep_all = TRUE)

Видаліть рядки, однакові лише в певних стовпцях:

iris %>% 
  distinct(Sepal.Length, Sepal.Width, .keep_all = TRUE)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.