基于name列计算type列值的出现次数差值(data.table场景)
解决data.table分组计算apple与pear次数差的问题
首先给出原始数据:
test <- data.table(name = c(rep(1,20), rep(2,20), rep(3,20)), type = c(rep("apple",10), rep("pear",10), rep("apple",15), rep("pear",5), rep("pear",20)))
需求是按name分组,计算每组中apple的出现次数减去pear的出现次数,期望结果如下:
name diff <num> <num> 1: 1 0 2: 2 10 3: 3 -20
你之前用table(type)[1] - table(type)[2]的写法会在分组仅含一种类型时返回NA,原因是table()只会生成存在的类型的计数,缺失的类型没有对应索引,取不存在的索引就会得到NA。下面是三种可靠的实现方法:
方法1:直接统计两类数量差值
这种方式最直观,直接分别统计apple和pear的数量再做减法,不管分组里有没有其中一类,sum(type == "xxx")都会返回0(如果没有该类):
results <- test[, .(diff = sum(type == "apple") - sum(type == "pear")), by = name]
方法2:转宽表后计算差值
先用dcast将长表转为宽表,设置fill=0确保缺失的类型计数为0,再计算apple与pear的差值:
# 转宽表,每个name下的apple和pear计数 wide_dt <- dcast(test, name ~ type, fun.aggregate = length, fill = 0) # 计算差值并保留需要的列 results <- wide_dt[, .(name, diff = apple - pear)]
方法3:赋值求和法
给apple记+1,pear记-1,其他类型(如果存在)记0,直接求和得到差值:
results <- test[, .(diff = sum(fcase(type == "apple", 1, type == "pear", -1, default = 0))), by = name]
以上三种方法都能正确处理分组仅含单一类型的情况,得到你需要的结果。
内容的提问来源于stack exchange,提问作者Paul Endymion
相关产品推荐
相关产品推荐

