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