Удалить дублирующиеся строки

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

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

user1897691
источник
3
какой вы хотите? только первый? другими словами: вы хотите сохранить googleили localhostили hughsie?
Энтони Дамико
Это не имеет значения для этой части моего статистического анализа. Я только пытаюсь связать название проекта (первый столбец), количество ошибок (второй столбец) и количество организаций в проекте (третий столбец).
user1897691 20.12.12
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, поэтому я спрашиваю, что я могу только предположить, это очевидный вопрос.
user1897691 20.12.12
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 $ duplicates <- 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
mpalanco
источник
Это накладные расходы на настройку всей базы данных SQL. cran.r-project.org/web/packages/sqldf/index.html
qwr
Что вы подразумеваете под настройкой всей базы данных SQL? Это одно из основных преимуществ: «с sqldf пользователь освобождается от необходимости делать следующее, все это автоматически выполняется: настройка базы данных, написание оператора create table, который определяет каждую таблицу, импорт и экспорт в базу данных и из нее. ». Это не оптимальное решение, но удобное для тех, кто знаком с 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]>

Дубликаты col 2 и 3 теперь удаляются для статистического анализа, но вы сохранили данные col 4 и 5 в виде таблицы и можете вернуться к исходному фрейму данных в любой точке с помощью unnest().

Джо
источник
1

Удалить дубликаты строк информационного кадра

library(dplyr)
mydata <- mtcars

# Remove duplicate rows of the dataframe
distinct(mydata)

В этом наборе данных нет ни одной повторяющейся строки, поэтому он возвратил то же количество строк, что и в 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/ )

vasili111
источник
0

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

Используя базу 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)
stevec
источник