使用data.table在R中计算中位数时出现错误

14

我有以下数据集

> head(DT)
    V1 V2 V3   V4   V5     V6 V7
1:  2  1  2 0.91 0.02 880.00  1
2:  3  2  1 0.02 0.00   2.24  2
3:  1  1  1 0.15 0.01   3.41  3
4:  1  2  1 3.92 0.05 268.67  2
5:  1  1  2 0.10 0.01   1.59  3
6:  0  1  1 1.20 0.04   1.43  3

> sapply(DT, class)
       V1        V2        V3        V4        V5        V6        V7 
"integer" "integer" "integer" "numeric" "numeric" "numeric"  "factor" 

有一个扩展成数千行的数据集。我试图在由因子变量V7定义的8个组内计算V1-V6的中位数值。

> levels(DT$V7)
[1] "1" "2" "3" "4" "5" "6" "7" "8"

目前我使用以下命令,但返回一个错误:

> DT[, lapply(.SD, median), by = V7]
 Error in `[.data.table`(DF, , lapply(.SD, median), by = V7) : 
 Column 1 of result for group 4 is type 'integer' but expecting type 'double'. Column types must be consistent for each group.

我在某个地方读到过一个解决方法,那就是使用as.double(median(X))。但这只适用于单个列:DT[, as.double(median(X)), by = V7],而考虑所有列时不起作用:DT[, lapply(.SD, as.double(median)), by = V7](如预期的一样,因为你必须传递一个输入给median)。

我可以通过使用aggregate来避免这个问题。

> aggregate(DT[,c(1:6), with = FALSE], by = list(DF$V7), FUN = median)
  Group.1 V1 V2 V3     V4   V5      V6
   1       1  0  1  1  1.285 0.04 401.500
   2       2  1  2  1  3.565 0.06   6.400
   3       3  0  1  1  0.360 0.03  11.200
   4       4  1  1  1 74.290 0.26 325.960
   5       5  2  1  0  1.145 0.04   1.415
   6       6  0  1  1 10.100 0.18  93.000
   7       7  1  1  0  0.740 0.04   1.080
   8       8  1  1  0  7.970 0.40   0.050

但我想知道是否有办法解决上述错误并使用data.table进行这种计算。


使用通常的lapply语法:lapply(.SD, function(x) as.numeric(median(x)))lapply的第二个参数必须是一个函数。 - Roland
value为整数时,此问题也可能在dcast()中显现。Roland的解答是在dcast之前将该字段转换为数字,例如df[,value := as.numeric(value)]。这对我很有效。 - kakarot
1个回答

18

median是不寻常的,因为它可以针对相同的输入类型返回不同类型的返回值:

默认方法返回与x相同类型的长度为一的对象, 但当x是偶数长度的整数时,结果将为double。

然而,data.table需要一个一致的返回值类型。您有两种可能性:

将所有列转换为数字:

DT[, paste0("V", 1:6) := lapply(.SD, as.numeric), by = V7]

或将median的返回值转换:

DT[, lapply(.SD, function(x) as.numeric(median(x))), by = V7]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接