我对data.table相当新,并且有一个基本问题。我正在尝试根据两列重新排序以下数据表。
library(data.table)
DT <- data.table(letter=c('a','a','a','a','b','b','c','d','d','d','d'),
value =c(1,2,4,8,2,5,1,1,2,3,9))
letter value
1: a 1
2: a 2
3: a 4
4: a 8
5: b 2
6: b 5
7: c 1
8: d 1
9: d 2
10: d 3
11: d 9
我希望根据最低相关值对字母进行排序,如果它们相等则应比较下一个值(如果可用),依此类推。
这应该产生以下结果:
letter value
1: c 1
2: d 1
3: d 2
4: d 3
5: d 9
6: a 1
7: a 2
8: a 4
9: a 8
10: b 2
11: b 5
我已尝试DT[order(value), .SD, letter]
对值进行排序,但在最低关联值的情况下不考虑后续值。我觉得应该有一个简单的方法来做到这一点,但我找不到答案。感谢。
答案 0 :(得分:1)
我想根据最低的相关值对字母进行排序,如果它们相等则应该比较下一个值(如果可用),等等。
这不是那么简单。首先,我们需要填充数据,以便c
的“第二”值再次为1
;第三;第四个:
n = max(DT[, .N, by=letter]$N)
oDT = DT[, .(rid = 1:n, v = c(value, rep(value[.N], n-.N))), by=letter]
然后,我认为我们需要一个递归函数来检查关系:
chk_ties = function(L, r, maxr = n){
if (r == maxr)
L
else
oDT[letter %in% L & rid == r, {
if (.N > 1L)
chk_ties(letter, r + 1L)
else
letter
}, keyby=v]$V1
}
chk_ties(unique(DT$letter), 1L)
# [1] "c" "d" "a" "b"
或者,我没有使用递归函数,而是意识到我们可以制作这个hack:
setorderv(dcast(oDT, letter ~ rid), as.character(1:n))$letter
# [1] "c" "d" "a" "b"
最后,我们需要加入,就像在@ lmo的回答中一样:
DT[setorderv(dcast(oDT, letter ~ rid), as.character(1:n))$letter, on="letter"]
# or
DT[chk_ties(unique(DT$letter), 1L), on=.(letter)]
可以在这里写on=.(letter)
或on="letter"
。