2015-11-26 10 views
1

Я искал эффективный способ подсчета и удаления повторяющихся строк в кадре данных, сохраняя индекс своих первых вхождений. Например, если у меня есть кадр данных:R - подсчитывать повторяющиеся строки, сохраняющие индекс их первых вхождений

df<-data.frame(x=c(9.3,5.1,0.6,0.6,8.5,1.3,1.3,10.8),y=c(2.4,7.1,4.2,4.2,3.2,8.1,8.1,5.9)) 
ddply(df,names(df),nrow) 

дает мне

x y V1 
1 0.6 4.2 2 
2 1.3 8.1 2 
3 5.1 7.1 1 
4 8.5 3.2 1 
5 9.3 2.4 1 
6 10.8 5.9 1 

Но я хочу, чтобы сохранить исходные показатели (наряду с именами строк) дублированных строк. как:

x y V1 
1 9.3 2.4 1 
2 5.1 7.1 1 
3 0.6 4.2 2 
5 8.5 3.2 1 
6 1.3 8.1 2 
8 10.8 5.9 1 

"дублироваться" возвращает исходные rownames (здесь {1 2 3 5 6 8}), но оленья кожа подсчитать количество вхождений. Я пробовал писать функции самостоятельно, но ни один из них не является достаточно эффективным для обработки больших данных. В моем кадре данных может быть до нескольких миллионов строк (хотя столбцы обычно от 5 до 10).

+0

Я бы предположил, что вы приняли решение из дублированного сообщения. Интересно, почему бы вам не взглянуть дальше на остальные решения. –

+0

Я просмотрел множество решений, но не смог найти «сохранение первых экземпляров дубликатов» где угодно. Поскольку у меня нет привилегии добавлять комментарии в более старые сообщения, а вопрос «вопрос» в поле «ответ» был бы неправильным, мне пришлось создать новый пост. Я задал этот вопрос после борьбы с ним в течение 6 дней. – Ira

+0

О, я вижу. Я не заметил, что вам тоже нужны имена строк. –

ответ

2

Если вы хотите сохранить индекс:

library(data.table) 
setDT(df)[,.(.I, .N), by = names(df)][!duplicated(df)] 
#  x y I N 
#1: 9.3 2.4 1 1 
#2: 5.1 7.1 2 1 
#3: 0.6 4.2 3 2 
#4: 8.5 3.2 5 1 
#5: 1.3 8.1 6 2 
#6: 10.8 5.9 8 1 

или с помощью data.table сек unique метод

unique(setDT(df)[,.(.I, .N), by = names(df)], by = names(df)) 
+0

Отлично! Это то, чего я хотел. Благодарю. Я расскажу об эффективности, с которой сталкивался, другими методами, сравнивая их с этим. – Ira

2

Мы можем попробовать с data.table. Мы преобразуем 'data.frame' в 'data.table' (setDT(df)), сгруппированные по столбцу 'x', 'y', получим nrow (.N).

library(data.table) 
setDT(df)[, list(V1=.N), by = .(x,y)] 
#  x y V1 
#1: 9.3 2.4 1 
#2: 5.1 7.1 1 
#3: 0.6 4.2 2 
#4: 8.5 3.2 1 
#5: 1.3 8.1 2 
#6: 10.8 5.9 1 

Если нам нужны строки идентификаторы,

setDT(df)[, list(V1= .N, rn=.I[1L]), by = .(x,y)] 
#  x y V1 rn 
#1: 9.3 2.4 1 1 
#2: 5.1 7.1 1 2 
#3: 0.6 4.2 2 3 
#4: 8.5 3.2 1 5 
#5: 1.3 8.1 2 6 
#6: 10.8 5.9 1 8 

Или

setDT(df, keep.rownames=TRUE)[, list(V1=.N, rn[1L]), .(x,y)] 
+1

Я думаю, что добавление 'by' упрощает чтение. –

+0

Спасибо. Но он не возвращает имена строк. Я хотел бы, чтобы имена розеров были {1 2 3 5 6 8}. – Ira

+1

@Ira Обновлено сообщение – akrun