1

假设我有以下data.table:

set.seed(123)
dt <- data.table (id=1:10,
                  group=sample(LETTERS[1:3], 10, replace=TRUE),
                  val=sample(1:100, 10, replace=TRUE),
                  ltr=sample(letters, 10),
                  col5=sample(100:200, 10)
                  )
setkey(dt, id)
(dt)
#     id group  val  ltr col5
#  1:  1     A   96    x  197
#  2:  2     C   46    r  190
#  3:  3     B   68    p  168
#  4:  4     C   58    w  177
#  5:  5     C   11    o  102
#  6:  6     A   90    v  145
#  7:  7     B   25    k  172
#  8:  8     C    5    l  120
#  9:  9     B   33    f  129
# 10: 10     B   96    c  121

现在我想通过分组来处理它group,并且在每个组中,我需要按val列对记录进行排序,然后在每个有序组中进行一些操作(例如,添加一个具有ltr按顺序合并的值的列):

#     id group val ltr letters
#  1   6     A  90   v     v_x
#  2   1     A  96   x     v_x
#  3   7     B  25   k k_f_p_c
#  4   9     B  33   f k_f_p_c
#  5   3     B  68   p k_f_p_c
#  6  10     B  96   c k_f_p_c
#  7   8     C   5   l l_o_r_w
#  8   5     C  11   o l_o_r_w
#  9   2     C  46   r l_o_r_w
#  10  4     C  58   w l_o_r_w

(在这个例子中,整个表是有序的,但这不是必需的)

这就是我想象的一般代码的方式:

dt1 <- dt[,
          {
            # processing here, reorder somehow
            # ???
            # ...
            list(id=id, ltr=ltr, letters=paste0(ltr,collapse="_"))
          },
          by=group]

提前感谢您的任何想法!

UPD。如答案中所述,对于我的示例,我可以简单地订购 bygroup然后 by val。如果我需要做几个不同的订购?例如,我想排序col5并添加col5diff将显示col5值差异的列:

#    id group val ltr col5 letters col5diff
# 1:  6     A  90   v  145     v_x        
# 2:  1     A  96   x  197     v_x       52
# 3: 10     B  96   c  121 k_f_p_c        
# 4:  9     B  33   f  129 k_f_p_c        8
# 5:  3     B  68   p  168 k_f_p_c       47
# 6:  7     B  25   k  172 k_f_p_c       51
# 7:  5     C  11   o  102 l_o_r_w        
# 8:  8     C   5   l  120 l_o_r_w       18
# 9:  4     C  58   w  177 l_o_r_w       75
#10:  2     C  46   r  190 l_o_r_w       88

好的,对于这个例子,计算letterscol5diff是独立的,所以我可以简单地连续进行:

setkey(dt, "group", "val")
dt[, letters := paste(ltr, collapse="_"), by = group]

setkey(dt, "group", "col5")
dt<-dt[, col5diff:={
  diff <- NA;
  for (i in 2:length(col5)) {diff <- c(diff, col5[i]-col5[1]);}
  diff; # updated to use := instead of list - thanks to comment of @Frank
}, by = group]

但如果我需要同时使用这两种顺序(单{}块),我也很高兴知道该怎么做。

4

2 回答 2

2

我想你只是在寻找order

dt[, letters:=paste(ltr[order(val)], collapse="_"), by=group]
dt[order(group, val)]
#    id group val ltr col5 letters
# 1:  6     A  90   v  145     v_x
# 2:  1     A  96   x  197     v_x
# 3:  7     B  25   k  172 k_f_p_c
# 4:  9     B  33   f  129 k_f_p_c
# 5:  3     B  68   p  168 k_f_p_c
# 6: 10     B  96   c  121 k_f_p_c
# 7:  8     C   5   l  120 l_o_r_w
# 8:  5     C  11   o  102 l_o_r_w
# 9:  2     C  46   r  190 l_o_r_w
#10:  4     C  58   w  177 l_o_r_w

或者,如果您不想通过引用添加列:

dt[, list(id, val, ltr, letters=paste(ltr[order(val)], collapse="_")), 
     by=group][order(group, val)]
#    group id val ltr letters
# 1:     A  6  90   v     v_x
# 2:     A  1  96   x     v_x
# 3:     B  7  25   k k_f_p_c
# 4:     B  9  33   f k_f_p_c
# 5:     B  3  68   p k_f_p_c
# 6:     B 10  96   c k_f_p_c
# 7:     C  8   5   l l_o_r_w
# 8:     C  5  11   o l_o_r_w
# 9:     C  2  46   r l_o_r_w
#10:     C  4  58   w l_o_r_w
于 2013-05-11T21:10:43.763 回答
1

除非我遗漏了什么,否则这只需要设置key你的data.tabletogroupval

setkey(dt, "group", "val")
#     id group val ltr col5
#  1:  6     A  90   v  145
#  2:  1     A  96   x  197
#  3:  7     B  25   k  172
#  4:  9     B  33   f  129
#  5:  3     B  68   p  168
#  6: 10     B  96   c  121
#  7:  8     C   5   l  120
#  8:  5     C  11   o  102
#  9:  2     C  46   r  190
# 10:  4     C  58   w  177

您会看到这些值是自动排序的。现在您可以通过以下方式进行子集化group

dt[, letters := paste(ltr, collapse="_"), by = group]
#     id group val ltr col5 letters
#  1:  6     A  90   v  145     v_x
#  2:  1     A  96   x  197     v_x
#  3:  7     B  25   k  172 k_f_p_c
#  4:  9     B  33   f  129 k_f_p_c
#  5:  3     B  68   p  168 k_f_p_c
#  6: 10     B  96   c  121 k_f_p_c
#  7:  8     C   5   l  120 l_o_r_w
#  8:  5     C  11   o  102 l_o_r_w
#  9:  2     C  46   r  190 l_o_r_w
# 10:  4     C  58   w  177 l_o_r_w
于 2013-05-11T21:56:48.837 回答