将 .GRP 应用于 data.table R 中的多列以分别对每一列进行分组

apply .GRP to multiple columns in data.table R to group each column separately

我有一个很大的 data.table(2 亿行 x 300 列)DT,有多个(超过 50 个)标识符列。 标识符都是不同的格式,其中一些相当复杂和长,我想将它们(selected_cols)全部转换为简单的数字标识符。

我一次可以为一列使用 .GRP,而且速度非常快(好吧,相对而言,在上下文中!)

DT[, new_col_1 := .GRP , by = .(col_1)]  #this works for one column at a time

有没有办法使用 .GRP 业务对多个列执行此操作? 如果我使用 lapply 定义自己的函数,我知道该怎么做,但我不能在函数中使用 .GRP。可能是一厢情愿。我也可以用 for 循环来完成,但我讨厌 for 循环,它们让我毛骨悚然,因为它们不会按比例放大。 只是希望避免创建我自己的函数或出于速度原因使用 for 循环。这是一个简单的操作,但需要很长时间才能处理大 data.table.

DT[ , (paste0('new_', selected_cols)) := lapply(.SD, some_function_with_.GRP), .SDcols = selected_cols)] 

这里有一个 data.table 示例,如果您需要的话:

require(data.table)
DT = data.table(col1 = c('A','B','B','D','B','A','A','B','R','T','E','E','H','T','Y','F','F','F')
               ,col2 = c('DD','GG','RR','HH','SS','AA','CC','RR','EE','DD','HH','BB','CC','AA','QQ','EE','YY','MM')
               , col3 = c('FFF1', 'HHH1', 'CCC1', 'AAA1', 'FFF1', 'RRR1', 'GGG1', 'DDD1', 'FFF1', 'JJJ1', 'VVV1', 'CCC1', 'AAA1', 'XXX1', 'GGG1', 'HHH1', 'AAA1', 'RRR1'))

这是我想要的输出:

> DT
    col1 col2 col3 new_col1 new_col2 new_col3
 1:    A   DD FFF1        1        1        1
 2:    B   GG HHH1        2        2        2
 3:    B   RR CCC1        2        3        3
 4:    D   HH AAA1        3        4        4
 5:    B   SS FFF1        2        5        1
 6:    A   AA RRR1        1        6        5
 7:    A   CC GGG1        1        7        6
 8:    B   RR DDD1        2        3        7
 9:    R   EE FFF1        4        8        1
10:    T   DD JJJ1        5        1        8
11:    E   HH VVV1        6        4        9
12:    E   BB CCC1        6        9        3
13:    H   CC AAA1        7        7        4
14:    T   AA XXX1        5        6       10
15:    Y   QQ GGG1        8       10        6
16:    F   EE HHH1        9        8        2
17:    F   YY AAA1        9       11        4
18:    F   MM RRR1        9       12        5

我正在寻找本机 data.table 解决方案。

一种方法是使用 matchunique :

library(data.table)
cols <- paste0('col', 1:3)

DT[, paste0('new_', cols) := lapply(.SD, function(x) 
            match(x, unique(x))), .SDcols = cols]
DT

#    col1 col2 col3 new_col1 new_col2 new_col3
# 1:    A   DD FFF1        1        1        1
# 2:    B   GG HHH1        2        2        2
# 3:    B   RR CCC1        2        3        3
# 4:    D   HH AAA1        3        4        4
# 5:    B   SS FFF1        2        5        1
# 6:    A   AA RRR1        1        6        5
# 7:    A   CC GGG1        1        7        6
# 8:    B   RR DDD1        2        3        7
# 9:    R   EE FFF1        4        8        1
#10:    T   DD JJJ1        5        1        8
#11:    E   HH VVV1        6        4        9
#12:    E   BB CCC1        6        9        3
#13:    H   CC AAA1        7        7        4
#14:    T   AA XXX1        5        6       10
#15:    Y   QQ GGG1        8       10        6
#16:    F   EE HHH1        9        8        2
#17:    F   YY AAA1        9       11        4
#18:    F   MM RRR1        9       12        5