R data.table如何逐行计算两个列表列的公共值与差集
问题场景
现有名为test的data.table数据集,包含id、array1、array2三列,共2行数据:
- id=1:
array1为c(1,2,3,4,5),array2为c(3,4,5) - id=2:
array1为c(6,7,8,9,10),array2为c(6,7,0)
通过str()查看数据集结构可见array1、array2均为列表列:
> str(test) Classes ‘data.table’ and 'data.frame': 2 obs. of 3 variables: $ id : num 1 2 $ array1:List of 2 ..$ : num 1 2 3 4 5 ..$ : num 6 7 8 9 10 $ array2:List of 2 ..$ : num 3 4 5 ..$ : num 6 7 0 - attr(*, ".internal.selfref")=<externalptr>
需要逐行计算两个数组列的两个指标:
- 两列的公共值(交集)
- 存在于
array1但不存在于array2的值(差集)
最初编写的实现代码运行结果不符合预期:
test[, `:=` (diff = setdiff(array1, array2), common = intersect(array1, array2))]
实际返回结果:
- id=1:
diff为c(1,2,3,4,5),common为NULL - id=2:
diff为c(6,7,8,9,10),common为NULL
预期正确结果:
- id=1:
diff为c(1,2),common为c(3,4,5) - id=2:
diff为c(8,9,10),common为c(6,7)
问题原因
array1和array2是列表类型列,直接在data.table的j表达式中调用setdiff()、intersect()时,传入函数的是整列的完整列表对象,而非逐行传入列表内存储的原子向量,函数实际是对两个长度为2的列表整体做集合运算,无法得到逐行匹配的计算结果。
修复方案
使用Map()将两个列表列的对应行元素逐对传入集合运算函数即可,代码如下:
test[, c("diff", "common") := list( Map(setdiff, array1, array2), Map(intersect, array1, array2) )]
运行后输出结果完全符合预期,两列新生成的列表列中,每行存储对应行的差集、交集计算结果。
如果需要将结果转换为向量、拼接为字符串等其他格式,只需在Map中自定义运算逻辑即可。
内容的提问来源于stack exchange,提问作者Hilary
相关产品推荐
相关产品推荐

