2015-02-10 28 views
5

satır sayma aşağıdaki gibi görünen bir veri çerçevesi vardır:gruplama, karşılaştırma ve r

 system Id initial final 
665  9 16001 6070 6071 
683  10 16001 6100 6101 
696  11 16001 6101 6113 
712  10 16971 6150 6151 
715  11 16971 6151 6163 
4966  7 4118 10238 10242 
5031  9 4118 10260 10278 
5088  10 4118 10279 10304 
5115  11 4118 10305 10317 


structure(list(system = c(9L, 10L, 11L, 10L, 11L, 7L, 9L, 10L, 
11L), Id = c(16001L, 16001L, 16001L, 16971L, 16971L, 4118L, 4118L, 
4118L, 4118L), initial = c(6070, 6100, 6101, 6150, 6151, 10238, 
10260, 10279, 10305), final = c(6071, 6101, 6113, 6151, 6163, 
10242, 10278, 10304, 10317)), .Names = c("system", "Id", "initial", 
"final"), row.names = c(665L, 683L, 696L, 712L, 715L, 4966L, 
5031L, 5088L, 5115L), class = "data.frame") 

sonraki yapı

 Id system length initial final 
1 16001 9,10,11  3 6070 6113 
2 16971 10,11  2 6150 6163 
3 4118  7  1 10238 10242 
4 4118 9,10,11  3 10260 10317 


structure(list(Id = c(16001L, 16971L, 4118L, 4118L), system =  structure(c(3L, 
1L, 2L, 3L), .Label = c("10,11", "7", "9,10,11"), class =  "factor"), 
    length = c(3L, 2L, 1L, 3L), initial = c(6070L, 6150L, 10238L, 
    10260L), final = c(6113, 6163, 10242, 10317)), .Names = c("Id", 
"system", "length", "initial", "final"), class = "data.frame",  row.names = c(NA, 
-4L)) 

ile yeni bir veri çerçevesi istiyorum Gruplama, Kimlik ve "sistem" alanındaki farklılık (satırlar arası) ile bire eşittir. Ayrıca farklı "sistemi" ve gruplaşmaya dahil olanların sayısını öğrenmek istiyorum. Sonunda ilk "ilk" ve son "final" ile bir sütun da dahil.

Bunu r? Teşekkürler.

cevap

3

data.table'u kullanabilirsiniz. "Data.frame" öğesini "data.table" e dönüştürün (setDT), "system" (diff(system)), cumsum'un bitişik elemanlarının farkını alarak "indx" bir gruplama değişkenini oluşturun, "Id" ve "indx" i kullanın "istatistikleri almak için gruplandırma değişkeni olarak. data.table olmadan dplyr den first/last fonksiyonlarını kullanma konusunda @ jazzurro yorumuna dayalı

library(data.table) 
setDT(df)[,list(system=toString(system), length=.N, initial=initial[1L], 
    final=final[.N]), by=list(Id,indx=cumsum(c(TRUE, diff(system)!=1)))][, 
    indx:=NULL][] 

#  Id system length initial final 
#1: 16001 9, 10, 11  3 6070 6113 
#2: 16971 10, 11  2 6150 6163 
#3: 4118   7  1 10238 10242 
#4: 4118 9, 10, 11  3 10260 10317 

Ya

,

library(dplyr) 
df %>% 
    group_by(indx=cumsum(c(TRUE, diff(system)!=1)), Id) %>% 
    summarise(system=toString(system), length=n(), 
    initial=first(initial), final=last(final)) 
+1

'kullanarak Can' ilk() 've son() 'burada başka bir seçenek olabilir mi? 'first()' dplyr olsa da. – jazzurro

+0

@jazzurro Bence işe yarıyor. Bunu bir dplyr çözümü olarak gönderebilirsiniz. – akrun

+0

Hala "data.table" içindeki dplyr işlevinden bazı işlevleri kullanmanın iyi bir şey olup olmadığını merak ediyorum. 'Dplyr' çözümü sadece kodunuzun çevirisi olacaktır. Bir tane yazmaktan memnunsanız, lütfen devam edin. Onu sana bırakacağım. :) – jazzurro

1

bir çözüm, ancak plyr:

library(plyr) 

func = function(subdf) 
{ 
    bool = c(diff(subdf$system),1)==1 
    ldply(split(subdf, bool), function(u){ 
     data.frame(system = paste(u$system, collapse=','), 
        Id  = unique(u$Id), 
        length = nrow(u), 
        initial= head(u,1)$initial, 
        final = tail(u,1)$final) 
    }) 
} 


ldply(split(df, df$Id), func) 

# .id system length Id initial final 
#1 FALSE  7  1 4118 10238 10242 
#2 TRUE 9,10,11  3 4118 10260 10317 
#3 TRUE 9,10,11  3 16001 6070 6113 
#4 TRUE 10,11  2 16971 6150 6163