2012-10-29 96 views
2

我有一個data.table,包含一個class列和一些值列,根據排列在data.table中的列值的R改變順序

 class v1 v2 v3 
1:  1 10 3 8 
2:  2 2 24 7 
3:  1 70 3 9 

現在,爲的data.table子集(說類= 1),I需要根據排列,我要改變每個 行中的值的順序。舉例來說,如果置換是

3 1 2 

的結果應該

 class v1 v2 v3 
1:  1 8 10 3 
2:  2 2 24 7 
3:  1 9 70 3 

什麼是實現這一目標使用data.table的最佳方式?

我可以選擇將我的數據轉換爲矩陣,如果這樣更有效。謝謝!

+1

我相信有一個錯字。在倒數第二句中,你的意思是'data.table'而不是'data.frame',對吧? – Maiasaura

+0

更正!謝謝 – amir

回答

2

像這樣的東西應該工作

DT <- data.table(class = sample(1:3, 10, TRUE), v1 =sample(10), v2 = sample(10), v3 = sample(10)) 
DT 
    class v1 v2 v3 
1:  1 4 6 6 
2:  1 7 1 5 
3:  1 5 5 10 
4:  1 3 8 7 
5:  3 8 4 3 
6:  3 9 7 9 
7:  2 1 3 8 
8:  2 10 10 2 
9:  1 2 2 4 
10:  2 6 9 1 

# the neworder column contains the new permutations 
swapcols <- data.table(class = 1:3, neworder = list(c(1,2,3), c(3,1,2),c(1,3,2))) 

setkey(DT, class) 
setkey(swapcols, class) 

DT[swapcols, setNames(list(v1,v2,v3)[unlist(neworder)], c('v1','v2','v3'))] 

    class v1 v2 v3 
1:  1 4 6 6 
2:  1 7 1 5 
3:  1 5 5 10 
4:  1 3 8 7 
5:  1 2 2 4 
6:  2 8 1 3 
7:  2 2 10 10 
8:  2 1 6 9 
9:  3 8 3 4 
10:  3 9 9 7 

它可能會更更有效地做點像

DT[swapcols, setcolorder(.SD, unlist(neworder))] 

new <- DT[swapcols, list(v1,v2,v3)[unlist(neworder)]] 
    setnames(new, names(new), c('class', c('v1','v2','v3')) 

你也可以使用:=。像

DT[J(1), `:=`(v1= v2,v2=v3,v3=v1)] 

你可以嘗試在函數中自動執行此的一些方法,但它會EVAL /解析的混亂和do.call


從馬修(在v1.8.3測試):

DT = data.table(class=c(1,2,1),v1=c(10,2,70),v2=c(3,24,3),v3=c(8,7,9)) 
DT 
    class v1 v2 v3 
1:  1 10 3 8 
2:  2 2 24 7 
3:  1 70 3 9 

perm = c(3,1,2) 
DT[class==1,names(DT)[-1]:=.SD[,perm+1,with=FALSE]] 
DT 
    class v1 v2 v3 
1:  1 8 10 3 
2:  2 2 24 7 
3:  1 9 70 3 
+0

最後一部分完美地完成了這項工作。謝謝! – amir

0

我假設結果並不意味着包含class 2行。

的解決方案是相當簡單:

df.new <- subset(df, class=1) 
df.new <- df.new[,c(1,4,2,3)] 

或者你可以一次做到這一切:

df.new <- df[df$class==2,c("class","v3","v1","v2")] 
+0

我其實更喜歡在原地進行編輯。該表有10^5條記錄,我不想每次都複製它。 – amir

+0

然後你可以使用'df < - ...'。這將需要大大不到十分之一秒。 –

+2

我假設每次創建子集/投影並將其分配回自己時,它都會複製到新的數據框。我試圖用data.table來完成它,以避免代碼中的效率低下。 – amir