data.table与max和min函数

瞿伟斌

2024/11/13

工作中遇到了一个R语言的bug,暂且记录一下。 在日常工作中,我时常使用R语言中的data.table包来处理数据,其对于大数据良好的速度和简洁的使用方法令赞不绝口,但是在简洁的同时,其与其他语言不同的语法也常常使我哭笑不得。

在正常使用data.table中,加入一行可以使用:=的方法来实现, 如

library(data.table)
a= data.table(a=1:5,
           c=c(1,1,0,1,0),
           d=c(1,0,1,0,0))
a[,b:=1]
a[,e:=c+d]
print(a)
##        a     c     d     b     e
##    <int> <num> <num> <num> <num>
## 1:     1     1     1     1     2
## 2:     2     1     0     1     1
## 3:     3     0     1     1     1
## 4:     4     1     0     1     1
## 5:     5     0     0     1     0

但或许是因为这样的插入实在太过方便,以至于我忽略了其中集体实现的方法,而默认可以直接通过这样的方式来增加一列。 结果就在max和min函数中栽了跟头。

a= data.table(a=1:5,
           b=1,
           c=c(1,1,0,1,0),
           d=c(1,0,1,0,0))
a[,.(a,min(d,c),max(d,c),min(d,c))]
##        a    V2    V3    V4
##    <int> <num> <num> <num>
## 1:     1     0     1     0
## 2:     2     0     1     0
## 3:     3     0     1     0
## 4:     4     0     1     0
## 5:     5     0     1     0

可以看到,这个函数的结果和我们预想的是不太一样的,我们本来是想计算这一行的最小值和最大值,但却得到了整个表格所属列的最小值和最大值。 那么该怎么得到我们想要的值呢? 根据data.table的使用方法,我们可以通过设置by来实现.这项功能,具体代码如下:

a[,.(a,min(d,c),max(d,c)),a]
##        a     a    V2    V3
##    <int> <int> <num> <num>
## 1:     1     1     1     1
## 2:     2     2     0     1
## 3:     3     3     0     1
## 4:     4     4     0     1
## 5:     5     5     0     0

这样就能得到我们想要的结果了.实际在使用中,我常常是能看到R给的关于:=的警告信息的,但因为一般不影响计算,所以我也并没有非常在意。 但是这次这个bug让我的结果险些出现重大失误,花费了大量时间来排查问题.究其原因还是data.table的理解不够深入的同时又过于想当然。 看来日后还是要仔细看文档,好好研读,不能想当然。记此错误以警示自己。