Base R中如何获取DataFrame匹配的所有结果(替代match函数)
需求说明
现有两个R数据框:
df1 <- data.frame(c('j','g','e'), c(5,8,3)) colnames(df1) <- c('person', 'number') df2 <- data.frame(c('p','j','w','e','j','e','j'), c('a','b','c','f','l','m','n')) colnames(df2)<-c('person','other')
需要基于df1$person与df2$person的匹配关系,提取df2$other的所有对应值。match()函数仅能返回首个匹配结果,现提供Base R中适用于大数据框的高效实现方法,示例需获取'j'对应的3个值('b','l','n')与'e'对应的2个值('f','m')。
方法1:先筛选再分组(高效首选)
先通过向量化的%in%筛选出df2中person存在于df1的行,再用split()按person分组提取目标值,避免全表遍历,适合大数据场景:
# 筛选匹配行 matched_df <- df2[df2$person %in% df1$person, ] # 按person分组提取other值 result <- split(matched_df$other, matched_df$person) # 输出结果 result # $e # [1] "f" "m" # # $j # [1] "b" "l" "n"
如果需要严格保留df1中person的顺序,可再做一次交集筛选:
result <- result[intersect(df1$person, names(result))]
方法2:用tapply直接分组筛选
tapply可直接对df2的other列按person分组,同时过滤掉df1中不存在的个体:
result <- tapply(df2$other, df2$person, identity)[df1$person] # 移除df1中存在但df2无匹配的个体(示例中的'g') result <- result[!sapply(result, is.null)] result # $j # [1] "b" "l" "n" # # $e # [1] "f" "m"
方法3:用by函数分组
by函数返回分组对象,可转换为普通列表:
grouped_result <- by(df2$other, df2$person, identity) # 筛选df1中存在的person并转为列表 result <- as.list(grouped_result[intersect(df1$person, names(grouped_result))])
性能提示
大数据框场景下优先选方法1:%in%是高效的向量化操作,先筛选再分组的逻辑能大幅减少后续处理的数据量,远快于循环遍历的实现方式。
内容的提问来源于stack exchange,提问作者Carpa
相关产品推荐
相关产品推荐

