首页 文章

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

提问于
浏览
7

我想通过选择 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 回答

  • 9

    您可以改进几件事:

    • fread 将返回一个data.table,因此无需将其包装在 data.table 中 . 你可以查看 class(DT) .

    • 读入数据时使用 na.strings 参数 . 请参阅下面的示例 .

    • 总结:

    DT[, .(a = a[.N], 
           b = b[.N], 
           c = c[1], 
           d = sum(d), 
           e = sum(e), 
           f = unique(na.omit(f))), 
       by = ID]
    

    然后你会得到:

    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] 进行子集将为您提供组的最后一个值 . 您还可以使用在 data.table 中优化的 last -function,因此速度更快 .

    • Don 't use variable names that are also functions in R (in this case, don' t使用 c 作为变量名称) . 有关 c -function的作用的解释,另请参见 ?c .

    • 为了总结 f -variable,我将 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优化用于所有计算 .


    Used data:

    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='?')
    
  • 3

    我们可以使用 tidyverse . 在按'ID'分组后,我们 summarise 基于 firstlast 观察的列

    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
    

相关问题