2017-01-06 63 views
1

我對data.table相當陌生,並且有一個基本問題。我試圖重新排序基於這兩列的以下數據表。如何根據帶有關係的多列在R中訂購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

因此,您想首先對「價值」進行分類,然後再對字母進行分類? setorder(DT,value,-letter)怎麼樣? – dleal

+0

不,我想要得到最低值的字母,然後是該字母的所有其他值。然後移動到下一個最小值的字母並獲得所有具有該字母的行。如果有關係,必須比較一個字母的後續值。對不起,如果不明確。 – sandrjekk

回答

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" 

或者,而不是遞歸函數,我意識到,我們可以使這個黑客:

setorderv(dcast(oDT, letter ~ rid), as.character(1:n))$letter 
# [1] "c" "d" "a" "b" 

最後,我們需要加入對,如@改性活生物體的回答是:

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"

+0

一如既往的絕佳回答! – akrun

+0

這適用於我。謝謝! – sandrjekk

+0

@sandrjekk很高興聽到它。 Fyi,你用一個更具說明性的例子來更新這個問題是很好的,但對於那些已經發布答案讓他們知道的人來說,這很有禮貌(通過在他們的回答下評論)。無論如何,我現在只是評論lmo的。 – Frank