将.GRP应用于data.table R中的多个列以将每个列分别分组

时间:2020-08-26 07:08:56

标签: r data.table grouping

我有一个大的data.table(200M行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循环。这是一个简单的操作,但要花费大量时间处理大型数据表。

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解决方案。

1 个答案:

答案 0 :(得分:1)

一种方法是使用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