我有一个data.table,其中包含Age,食物类别和消耗的kcal列。我试图获得每个类别的平均kcal,但是对于某些类别,该类别中没有消费。所以我不能采用简单的平均值,因为data.table中没有零。
所以对于示例数据:
dtp2 <- data.table(age = c(4,4,4,5,6,18), category = c("chips","vegetables","pizza","chips","pizza","beer"), kcal = c(100,5,100,120,100,150))
只是做dtp2[,mean(kcal),by=category]
给出了错误的答案,因为只有18岁的人正在喝啤酒,4-17岁的人不会。
实际数据集是4:18岁,有很多很多类别。我已经尝试使用嵌套的for循环用零填充数据表用于省略的年龄,这非常慢,然后采用上述方法。
是否有一种合理的R方法取平均值kcal,其中假设缺失值为零,而没有嵌套的循环放入零?
答案 0 :(得分:1)
我认为你想在计算中包含缺失值或0 kcal值。您可以按类别求和,而不是取平均值,除以每个类别的总n。
答案 1 :(得分:0)
Make BufferedReader start from the middle of a .txt file rather than the beginning?相当通用,不会显示任何代码。提到这一点,OP的代码需要修改如下:
library(data.table)
dtp2[, sum(kcal) / uniqueN(dtp2$category), by = category]
返回
category V1 1: chips 55.00 2: vegetables 1.25 3: pizza 50.00 4: beer 37.50
请注意uniqueN(dtp2$category)
不仅仅使用uniqueN(category)
,因为按1
分组时始终为category
。
然而,有些情况假设缺失值为零,没有嵌套for循环放入零,就像OP要求的那样。
当数据从长格式转换为宽格式以呈现数据时,可能会出现一种情况:
reshape2::dcast(dtp2, age ~ category, fun = mean, value.var = "kcal", margins = TRUE)
age beer chips pizza vegetables (all) 1 4 NaN 100 100 5 68.33333 2 5 NaN 120 NaN NaN 120.00000 3 6 NaN NaN 100 NaN 100.00000 4 18 150 NaN NaN NaN 150.00000 5 (all) 150 110 100 5 95.83333
这里,保证金平均值仅根据OP要求的可用数据计算。 (请注意,参数fill = 0
对边距的计算没有影响。)
因此,在重塑之前,需要填充缺失值。在基数R中,expand.grid()
可用于此目的,在data.table
它是交叉连接函数CJ()
:
expanded <- dtp2[CJ(age, category, unique = TRUE), on = .(age = V1, category = V2)
][is.na(kcal), kcal := 0][]
expanded
age category kcal 1: 4 beer 0 2: 4 chips 100 3: 4 pizza 100 4: 4 vegetables 5 5: 5 beer 0 6: 5 chips 120 7: 5 pizza 0 8: 5 vegetables 0 9: 6 beer 0 10: 6 chips 0 11: 6 pizza 100 12: 6 vegetables 0 13: 18 beer 150 14: 18 chips 0 15: 18 pizza 0 16: 18 vegetables 0
现在,从长到宽的重塑将返回预期的结果:
reshape2::dcast(expanded, age ~ category, fun = mean, value.var = "kcal", margins = TRUE)
age beer chips pizza vegetables (all) 1 4 0.0 100 100 5.00 51.2500 2 5 0.0 120 0 0.00 30.0000 3 6 0.0 0 100 0.00 25.0000 4 18 150.0 0 0 0.00 37.5000 5 (all) 37.5 55 50 1.25 35.9375