R 对data.table记录的子集重新排序

R 对data.table记录的子集重新排序,r,data.table,R,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

假设我有以下数据表:

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
(在本例中,整张表已订购,但这不是必需的)

这就是我通常想象的代码:

dt1 <- dt[,
          {
            # processing here, reorder somehow
            # ???
            # ...
            list(id=id, ltr=ltr, letters=paste0(ltr,collapse="_"))
          },
          by=group]
好的,在这个例子中,
字母
col5diff
的计算是独立的,所以我可以简单地连续进行:

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]
setkey(dt,“group”,“val”)
dt[,字母:=粘贴(ltr,collapse=“”)、由=组]
设置键(dt,“组”、“col5”)

dt我想你只是在寻找
订单

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

除非我遗漏了什么,否则这只需要将
数据的
键设置为
val

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
您可以看到这些值是自动排序的。现在您可以按
进行子集:

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

谢谢@GSee,但正如我在P.S.中所说的,这是唯一一个简化的示例,
{}
中的唯一操作是在单个列上粘贴
。在我的实际数据中,我需要对有序子集的不同列执行许多操作。我将尝试扩展我的示例以使其更清楚。这是否足够一般,或太一般:
dt[,.SD[order(val)],by=group]
?不太可能:)我将更新我的示例(几个小时后-现在无法更新)显示真实情况。如果我不需要在
处理
部分使用多个排序,这将是一个完美的解决方案(即,在我的真实情况下,我需要先按一个字段排序,然后独立地按另一个字段排序)。我将尝试用真实数据更新我的示例(稍晚一点)以进行解释。好吧,我试图调整我的真实案例以在这里显示它,但结果太复杂了,所以我放弃了:/但我更新了我的示例-也许你可以就此提些建议。事实上,你的答案已经给了我一个解决方案,但我发现我的代码在最后4行中非常难看(见注释行-我不知道我是否可以在
{}
块之后使用
:=
),所以我非常感谢你的帮助来改进它。@VasilyA你可以使用
dt[,a:={…}]
dt[,c(“a”,“b”,“c”):=list({…},{…},{…},{…})]
创建新列/变量。并且可以将选项
,by=group
添加到其中任何一个。
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
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