尝试根据另一个数据帧df2中的匹配在数据帧df1中创建一个列,其中df1远大于df2:
df1$val2 <- df2$val2[match(df1$id, df2$IDs)]
这不太有用,因为df2 $ IDs列是一个列表:
> 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)。对于所有其他行,'match(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)]
答案 0 :(得分: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
Fyi,match
方法不会自然地扩展到加入更多列,因此您可能希望最终学习data.table及其更新连接&#34;这种情况的语法:
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 ]