2015-08-25 22 views
10

Sorunum, farklı bir kod kullanarak, bir faktör düzeyine göre seçmek istediğiniz satırları zaten belirlediğim gerçeğinden kaynaklanıyor. Temelde ne var şudur: değil bütün dataframe df2 yılında, sıranın endeksine ama kimliği bir tek seviyesine içinde tekabülSatırı bir faktör düzeyine göre seçin

df<-data.frame(ID=c("A","B","C"), pos=c(1,3,2)) 
df2<-data.frame(ID=c(rep("A",5),rep("B",5),rep("C",5)),obs=c(1:15)) 

df, pos yılında. Bu yüzden, her bir ID için doğru indekse göre satırları seçmenin bir yolunu arıyorum (bu nedenle satır sayısı, df2'un her faktörü seviyesinde).

Bu daha sonra beni verecek:

df3<-data.frame(ID=c("A","B","C"), obs=c(1,8,12)) 

cevap

9

İşte baz R çözüm: df2ID göre sıralanır

df2$pos <- ave(df2$obs, df2$ID, FUN=seq_along) 
merge(df, df2) 
    ID pos obs 
1 A 1 1 
2 B 3 8 
3 C 2 12 

, sadece ilk satırı için df2$pos <- sequence(table(df2$ID)) yapabilirsiniz.

ID kolonu üzerinde birleştirir
setDT(df2)[df, .SD[pos], by = .EACHI, on = 'ID'] 

, daha sonra df sıralarının her biri için pos satırı seçer:

+0

Mükemmel çalışıyor, teşekkürler! –

+0

İyi fikir. Yine de bir ara veri seti yapmak yerine, 'df2 $ pos <- dizisini (uzunlukları (bölünmüş (df2 $ ID, df2 $ ID))) yapabilirdiniz ve sonra sadece birleştirme yapabilir (df, df2). Bu şekilde dplyr daha çirkin değildir. – Frank

+0

Bu düzenleme ile daha da iyi (ve daha hızlı). –

11

dplyr

library(dplyr) 

merge(df,df2) %>% 
    group_by(ID) %>% 
    filter(row_number() == pos) %>% 
    select(-pos) 

# ID obs 
# 1 A 1 
# 2 B 8 
# 3 C 12 

temel R

df2m <- merge(df,df2) 
do.call(rbind, 
    by(df2m, df2m$ID, function(SD) SD[SD$pos[1], setdiff(names(SD),"pos")]) 
) 

by birleştirilmiş veri çerçevesini böler df2m tarafından df2m$ID ve her parça üzerinde çalışır; sonuçların bir listede döndüğünü, bu nedenle sonunda birlikte rbind ed olmalıdır. Verilerin her bir alt kümesi (ID'un her bir değeriyle ilişkilendirilir) pos tarafından filtrelenir ve normal data.frame sözdizimini kullanarak "pos" sütununun seçimini kaldırır. setkey(setDT(df2),"ID")[df] - - birleştirme olduğunu

data.table

bir yorumun

library(data.table) 

setkey(setDT(df2),"ID")[df][, 
    .SD[pos[1L], !"pos", with=FALSE] 
, by = ID] 

yılında @DavidArenburg tarafından ilk bölümü önerdi. Bundan sonra, sonuç tablo by = ID bölünür ve her bir Veri Alt kümesi, .SD üzerinde çalışır. pos[1L], normal şekilde alt dizindir, !"pos", with=FALSE ise pos sütununa karşılık gelir.

Daha iyi bir data.table yaklaşımı için @ eddi'nin yanıtına bakın.

+4

Ayrıca belki kütüphane (data.table); setkey (setDT (df2), "ID") [df] [, .SD [pos [1L]], = ID ile =] veya benzer bir şey. –

+0

Çözümünüz en zarif görünüyor ... Ama ben dplyr kuramıyorum. Endişelerinizin hiçbirinin olmadığını biliyorum ama yine de burada söylemek istedim, bu yüzden üst yazıyı görmezden geldiğimi düşünmüyorsun. –

+0

@ user2092517 Sorun değil, açıklama için teşekkürler. – Frank

7

data.table sürüm 1.9.5+ kullanılması.

+3

Ya da sadece setkey (setDT (df2), "ID") [df, .SD [pos], by = .EACHI] ' devel versiyonu –