选择第n个观察值并使用data.table按组进行求和

时间:2017-04-08 12:09:32

标签: r data.table

我想通过选择ab组的最后一次观察,将第一个表格转换为第二个表格,c的第一个观察结果,对每个观察值求和de的分组以及f的分组,检查是否存在有效日期并使用该日期。

表1:

ID   a    b    c        d        e          f
1   10  100 1000    10000   100000  ?
1   10  100 1001    10010   100100  5/07/1977
1   11  111 1002    10020   100200  5/07/1977
2   22  222 2000    20000   200000  6/02/1980
3   33  333 3000    30000   300000  20/12/1978
3   33  333 3001    30010   300100  ?
4   40  400 4000    40000   400000  ?
4   40  400 4001    40010   400100  ?
4   40  400 4002    40020   400200  7/06/1944
4   44  444 4003    40030   400300  ?
4   44  444 4004    40040   400400  ?
4   44  444 4005    40050   400500  ?
5   55  555 5000    50000   500000  31/05/1976
5   55  555 5001    50010   500100  31/05/1976

表2:

ID   a    b    c         d        e          f
1   11  111 1000     30030   300300  5/07/1977
2   22  222 2000     20000   200000  6/02/1980
3   33  333 3000     60010   600100 20/12/1978
4   44  444 4000    240150  2401500  7/06/1944
5   55  555 5000    100010  1000100 31/05/1976

我查了StackOverflow问题,我只看到了这个元素。我可以通过以下步骤进行操作。

library(data.table)

setwd('D:/Work/BRB/StackOverflow')

DT = data.table(fread('datatable.csv', header=TRUE))

AB = DT[ , .SD[.N], ID ]
AB = AB[ , c('a', 'b') ]

C = DT[ , .SD[1], ID ]
C = C[ , 'c' ]
DE = DT[ , .(d = sum(d), e = sum(e)) , by = ID ]

Final = cbind(AB, C, DE)
Final

我的问题是,我是否可以在一个转换中对变量abcde执行操作,而无需拆分它变成3?

另外,我不知道如何做f。有什么建议吗?

最后,我是R.的新手。我还可以改进其他代码吗?

2 个答案:

答案 0 :(得分:10)

您可以改进几件事:

  1. fread将返回 data.table ,因此无需将其包含在data.table中。您可以查看class(DT)
  2. 读取数据时使用na.strings参数。请参阅下面的示例。
  3. 总结:

    DT[, .(a = a[.N], 
           b = b[.N], 
           c = c[1], 
           d = sum(d), 
           e = sum(e), 
           f = unique(na.omit(f)))
       , by = ID]
    
  4. 然后你会得到:

       ID  a   b    c      d       e          f
    1:  1 11 111 1000  30030  300300  5/07/1977
    2:  2 22 222 2000  20000  200000  6/02/1980
    3:  3 33 333 3000  60010  600100 20/12/1978
    4:  4 44 444 4000 240150 2401500  7/06/1944
    5:  5 55 555 5000 100010 1000100 31/05/1976
    

    一些解释&其他说明:

    • 使用[1]进行子集将为您提供组的第一个值。您还可以使用first - 在 data.table 中优化的功能,从而加快速度。
    • 使用[.N]进行子设置将为您提供组的最后一个值。您还可以使用last - 在 data.table 中优化的功能,从而加快速度。
    • 不要使用也是R中的函数的变量名(在这种情况下,不要使用c作为变量名)。另请参阅?c,了解c - 函数的作用。
    • 为了总结f - 变量,我将uniquena.omit结合使用。如果ID有多个唯一日期,您也可以使用na.omit(f)[1]

    如果速度是一个问题,你可以优化上面的(thx到@Frank):

    DT[order(f)
       , .(a = last(a), 
           b = last(b), 
           c = first(c), 
           d = sum(d), 
           e = sum(e), 
           f = first(f))
       , by = ID]
    

    f排序会将NA - 值设为最后。因此,现在内部GForce优化用于所有计算。

    使用过的数据:

    DT <- fread("ID   a    b    c        d        e          f
                 1   10  100 1000    10000   100000  ?
                 1   10  100 1001    10010   100100  5/07/1977
                 1   11  111 1002    10020   100200  5/07/1977
                 2   22  222 2000    20000   200000  6/02/1980
                 3   33  333 3000    30000   300000  20/12/1978
                 3   33  333 3001    30010   300100  ?
                 4   40  400 4000    40000   400000  ?
                 4   40  400 4001    40010   400100  ?
                 4   40  400 4002    40020   400200  7/06/1944
                 4   44  444 4003    40030   400300  ?
                 4   44  444 4004    40040   400400  ?
                 4   44  444 4005    40050   400500  ?
                 5   55  555 5000    50000   500000  31/05/1976
                 5   55  555 5001    50010   500100  31/05/1976", na.strings='?')
    

答案 1 :(得分:3)

我们可以使用tidyverse。按照&#39; ID&#39;进行分组后,我们会根据summarisefirst观察结果last

library(dplyr) 
DT %>% 
   group_by(ID) %>% 
   summarise(a = last(a),
             b = last(b), 
             c = first(c), 
             d = sum(d), 
             e = sum(e), 
             f = f[f!="?"][1])
# A tibble: 5 × 7
#     ID     a     b     c      d       e          f
#  <int> <int> <int> <int>  <int>   <int>      <chr>
#1     1    11   111  1000  30030  300300  5/07/1977
#2     2    22   222  2000  20000  200000  6/02/1980
#3     3    33   333  3000  60010  600100 20/12/1978
#4     4    44   444  4000 240150 2401500  7/06/1944
#5     5    55   555  5000 100010 1000100 31/05/1976