如何在R中自动比较两个数据框对应列的数值交集数量
批量计算两个数据框对应列的交集长度问题解决方法
问题背景
有两个数据框position_sc(示例中为df.sc)和position_hit(示例中为df.hit),每列对应一位受试者(命名格式为PD..),行代表句子编号。需要统计每位受试者在sc条件下答对的句子数量,即计算两个数据框对应列的交集长度。
单列计算可正常得到结果:
# 单列统计示例 matches.hit_sc_PD02 = length(intersect(df.sc$PD02, df.hit$PD02)) matches.hit_sc_PD02 # 输出: [1] 3
但尝试批量处理时返回NULL:
df.hit_sc = list(df.hit, df.sc) names(df.hit_sc) = c("hit", "sc") matches.hit_sc_all = sapply(df.hit_sc, function(x) intersect(df.sc$x, df.hit$x)) matches.hit_sc_all # 输出: # $hit # NULL # # $sc # NULL
错误原因
你的批量处理逻辑存在三个关键问题:
sapply(df.hit_sc, ...)是遍历整个数据框列表(先处理df.hit,再处理df.sc),而非遍历列名,不符合“对应列计算”的需求- 在函数中使用
df.sc$x无法正确引用列名,R中通过字符串索引列应该用df.sc[[x]]的形式 - 代码逻辑没有实现“两个数据框对应列取交集”,而是错误地尝试在单个数据框内部操作
解决方法
方法1:使用mapply(基础R)
mapply可以同时对两个数据框的对应列执行操作,完美匹配需求:
# 直接计算所有对应列的交集长度 result_mapply = mapply(function(col_sc, col_hit) { length(intersect(col_sc, col_hit)) }, df.sc, df.hit) # 整理为易读的数据框格式 result_mapply_df = data.frame( 受试者 = names(result_mapply), 答对数量 = as.vector(result_mapply) ) print(result_mapply_df)
运行结果:
受试者 答对数量 1 PD02 3 2 PD03 3 3 PD04 3 4 PD05 3
方法2:使用purrr::map2(tidyverse风格)
如果你习惯tidyverse语法,map2可以更简洁地实现:
library(purrr) result_map2 = map2(df.sc, df.hit, ~length(intersect(.x, .y))) %>% unlist() %>% data.frame(受试者 = names(.), 答对数量 = .) print(result_map2)
运行结果与方法1完全一致。
方法3:遍历列名(基础R)
通过遍历列名,逐个取对应列计算:
subject_names = names(df.sc) result_colnames = sapply(subject_names, function(name) { length(intersect(df.sc[[name]], df.hit[[name]])) }) result_colnames_df = data.frame( 受试者 = subject_names, 答对数量 = as.vector(result_colnames) ) print(result_colnames_df)
同样得到正确的批量统计结果。
验证可复现代码
先运行你提供的代码生成数据框:
# CREATE 2 DATAFRAMES # Dataframe 1 df.sc = data.frame( PD02 = c(1,3,7,9,12), PD03 = c(8,9,10,11,13), PD04 = c(1,2,3,24,36), PD05 = c(1,9,20,23,26) ) # Dataframe 2 list.hit = list( PD02 = c(1,3,7,8,11,13,14,15,16,17), PD03 = c(2,4,6,10,11,13,18,19,21), PD04 = c(1,2,3,4,6), PD05 = c(18,19,20,23,25,26) ) # 转换为数据框 library(stringi) df.hit = as.data.frame(t(stri_list2matrix(list.hit))) df.hit = data.frame(t(df.hit)) names(df.hit)[1:4] = names(df.sc)[1:4] df.hit = sapply(df.hit, as.integer) df.hit = data.frame(t(df.hit)) df.hit = data.frame(t(df.hit))
再运行上述解决方法的代码,即可得到正确的批量统计结果。
内容的提问来源于stack exchange,提问作者Tena
相关产品推荐
相关产品推荐

