R veri çerçevesinde belirli bir yinelenen kaydı hariç tümünü nasıl silebilirim? [kapalı]


16

Bazı yinelenen kimlikleri içeren bir veri çerçevesi var. Yalnızca maksimum değeri olan satırı tutarak yinelenen kimlikleri olan kayıtları kaldırmak istiyorum.

Bu şekilde yapılandırılmış için (diğer değişkenler gösterilmemiştir):

id var_1
1 2
1 4
2 1
2 3
3 5
4 2

Bunu oluşturmak istiyorum:

id var_1
1 4
2 3
3 5
4 2

Unique () ve duplicated () hakkında biliyorum, ancak maksimize etme kuralını nasıl dahil edeceğimi anlayamıyorum ...


Tamamen programlama ile ilgili bir görev olduğu ve istatistiklerle ilgisi olmadığı
Enthusiast

Yanıtlar:


24

Bunun bir yolu, verileri ters sıralamak ve duplicatedtüm kopyaları bırakmak için kullanmaktır . Benim için, bu yöntem kavramsal olarak kullanılanlardan daha basittir. Bence de çok hızlı olmalı.

# Some data to start with:
z <- data.frame(id=c(1,1,2,2,3,4),var=c(2,4,1,3,5,2))
# id var
#  1   2
#  1   4
#  2   1
#  2   3
#  3   5
#  4   2

# Reverse sort
z <- z[order(z$id, z$var, decreasing=TRUE),]
# id var
#  4   2
#  3   5
#  2   3
#  2   1
#  1   4
#  1   2

# Keep only the first row for each duplicate of z$id; this row will have the
# largest value for z$var
z <- z[!duplicated(z$id),]

# Sort so it looks nice
z <- z[order(z$id, z$var),]
# id var
#  1   4
#  2   3
#  3   5
#  4   2

Düzenleme: Sadece yukarıdaki ters sıralama bile hiç sıralamak gerektiğini fark ettim id. Bunun z[order(z$var, decreasing=TRUE),]yerine sadece kullanabilirsiniz ve aynı zamanda işe yarayacaktır.

Bir düşünce daha ... varSütun sayısal ise id, artan, ancak varazalan şekilde sıralamanın basit bir yolu vardır . Bu, sondaki sıralama ihtiyacını ortadan kaldırır (sıralanmasını istediğinizi varsayarsak).

z <- data.frame(id=c(1,1,2,2,3,4),var=c(2,4,1,3,5,2))

# Sort: id ascending, var descending
z <- z[order(z$id, -z$var),]

# Remove duplicates
z <- z[!duplicated(z$id),]
# id var
#  1   4
#  2   3
#  3   5
#  4   2

1
Bu yaklaşım "split-compute-rbind" den önemli ölçüde daha hızlıdır. Ayrıca birden fazla faktör üzerinde gruplandırmaya izin verir. Bir c. 650.000 satır (8, dar, sütunlar) "sipariş çoğaltılmış" yaklaşım 55 saniye sürdü, split-compute-rbind ... 1sa15dakika. Tabii ki toplam hesaplama, kopyaları seçmek veya filtrelemekten başka bir şey olduğunda, ikinci yaklaşım veya benzer plyr tabanlı yaklaşımlar gereklidir.
mjv

7

Aslında aynı kimliğe sahip öğelerden maksimum öğeyi seçmek istiyorsunuz. Bunun için plyrddply paketinden kullanabilirsiniz :

> dt<-data.frame(id=c(1,1,2,2,3,4),var=c(2,4,1,3,4,2))
> ddply(dt,.(id),summarise,var_1=max(var))
   id var_1
1  1   4
2  2   3
3  3   4
4  4   2

uniqueve duplicatedyinelenen kayıtları kaldırmak içindir, sizin durumunuzda yalnızca yinelenen kimlikleriniz vardır, kayıtları değil.

Güncelleme: Ek değişkenler olduğunda kod:

> dt<-data.frame(id=c(1,1,2,2,3,4),var=c(2,4,1,3,4,2),bu=rnorm(6))
> ddply(dt,~id,function(d)d[which.max(d$var),])

Ya başka değişkenler olsaydı: onları nasıl taşırsınız?
Aniko

Bu tür soruları hareket ettirmiyoruz - çok az kazanç için çok fazla acele.

6

Baz-R çözeltisi aşağıdakileri içerecektir split:

z<-data.frame(id=c(1,1,2,2,3,4),var=c(2,4,1,3,4,2))
do.call(rbind,lapply(split(z,z$id),function(chunk) chunk[which.max(chunk$var),]))

splitveri çerçevesini, maksimum değere sahip tek satıra kesme yaptığımız parçalar listesine böler ve ardından do.call(rbind,...)tek satır listesini tekrar veri çerçevesine indirir.


1
Ve her zamanki gibi bu, plyr versiyonundan yaklaşık 2 kat daha hızlı.

1
@mbq, evet, doğal olarak, ancak hata ayıklama maliyetlerini dahil ederseniz, olağan veri setleri için ortaya çıkan hız aynıdır :) plyr hız için değil, netlik ve rahatlık için ayrılmıştır.
mpiktas

ve ave kullanmak zaten iki kat daha hızlı :)
Eduardo Leoni

2
@Eduardo + ' avenın bir paketleyicisidir , kodu kontrol edin (-;lapplysplit

1
@Eduardo Evet, ama hepsi sadece faktörler içinde vektörize sıralama ilginç bir olasılık nedeniyle çalışır order; daha genel sorunlar splitiçin kaçınılmazdır.

5

Kullanmayı tercih ederim ave

dt<-data.frame(id=c(1,1,2,2,3,4),var=c(2,4,3,3,4,2))
## use unique if you want to exclude duplicate maxima
unique(subset(dt, var==ave(var, id, FUN=max)))

+1, ave hakkında bilmiyordum. Ne zaman R'de ortaya çıktı?
mpiktas

1

Bunu temel ile yapmanın başka bir yolu:

dt<-data.frame(id=c(1,1,2,2,3,4),var=c(2,4,1,3,4,2))

data.frame(id=sort(unique(dt$var)),max=tapply(dt$var,dt$id,max))
  id max
1  1   4
2  2   3
3  3   4
4  4   2

Yine de mpiktas'ın plyr çözümünü tercih ederim.


1

Örnekte olduğu gibi, sütun var zaten artan sıradaysa, veri çerçevesini sıralamamız gerekmez. Biz sadece duplicatedargümanı geçen fonksiyonu kullanırız fromLast = TRUE, bu nedenle çoğaltma arka taraftan düşünülür ve son unsurlar korunur:

z <- data.frame(id=c(1,1,2,2,3,4),var=c(2,4,1,3,5,2))
z[!duplicated(z$id, fromLast = TRUE), ]

  id var
2  1   4
4  2   3
5  3   5
6  4   2

Aksi takdirde, önce veri çerçevesini artan sırada sıralarız:

z <- z[order(z$id, z$var), ]
z[!duplicated(z$id, fromLast = TRUE), ]

dplyrPaketi kullanma :

library(dplyr)
z %>%
  group_by(id) %>%
  summarise(var = max(var))

Source: local data frame [4 x 2]    
  id var
1  1   4
2  2   3
3  3   5
4  4   2
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.