2017-09-05 102 views
1

試圖基於匹配的另一個數據幀DF2,其中DF1比DF2更大的創造數據幀DF1列:匹配數據幀列:一個int和另一個是列表

df1$val2 <- df2$val2[match(df1$id, df2$IDs)] 

這完全不是那麼回事因爲DF2 $標識列的列表:

> df2 
      IDs val2 
1    0 1 
2   1, 2 2 
3   3, 4 3 
4   5, 6 4 
5   7, 8 5 
6   9, 10 6 
7 11, 12, 13, 14 7 

它僅適用於在列表中有1元的部分(第1行:.. $:以上INT 0)。對於所有其他行,'匹配(df1 $ id,df2 $ IDs)'返回NA。

匹配一些個體數量的測試工作得很好用雙括號:

2 %in% df2[[2,'IDs']] 

所以,我要麼需要修改列DF2 $ ID或需要以不同的方式進行匹配操作。 df1有許多其他列,df2也是如此,但df2在行中要短得多。

的情況下,可以用下面的被複制:

IDs <- c("[0]", "[1, 2]", "[3, 4]", "[5, 6]", "[7, 8]", "[9, 10]", "[11, 12, 13, 14]") 
val2 <- c(1,2,3,4,5,6,7) 
df2 <- data.frame(IDs, val2) 
df2$IDs <- lapply(strsplit(as.character(df2$IDs), ','), function (x) as.integer(gsub("\\s|\\[|\\]", "", x))) 
id <- floor(runif(100, min=0, max=15)) 
df1 <- data.frame(id) 
str(df1) 
str(df2) 
df1$val2 <- df2$val2[match(df1$id, df2$IDs)] 
+1

一可重複的例子可以來得心應手...你有沒有嘗試unlist(df2 $ ID)? – Cris

+0

@Cris。謝謝。這將產生一個平面列表,但我們需要保持每行適當的列表。例如,在第2行中,我們列出了:int 1 2.這告訴我們所有具有值1和2的ID映射到該行。 – Dimon

+0

您正在討論一個示例,但這不同於構建和提供*可重現*示例。請參閱https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example/28481250#28481250 – Frank

回答

2

名單列笨拙的工作。如果轉換df2一個更香草格式,它的工作原理:

DF2 = with(df2, data.frame(ID = unlist(IDs), val2 = rep(val2, lengths(IDs)))) 
df1$m = DF2$val2[ match(df1$id, DF2$ID) ] 

如果你想只爲瀏覽列表列,它是快速做......

aggregate(ID ~ ., DF2, list) 

    val2    ID 
1 1    0 
2 2   1, 2 
3 3   3, 4 
4 4   5, 6 
5 5   7, 8 
6 6   9, 10 
7 7 11, 12, 13, 14 


據透露,該match做法自然不會擴展到加入更多的列,因此您可能希望最終學會data.table和它的「更新加入」語法這種情況:

library(data.table) 
setDT(df1); setDT(df2) 

DT2 = df2[, .(ID = unlist(IDs)), by=setdiff(names(df2), "IDs")] 
df1[DT2, on=.(id = ID), v := i.val2 ] 
+1

謝謝。這工作。我想的另一種方法是通過字符串匹配(即保持原始ID爲字符串)。我沒有得到它的工作。此外,它可能比你的版本慢,但是,更通用的版本。 – Dimon

相關問題