2016-04-25 76 views
10

我一直在翻譯this questiondata.table解決方案。 (保持簡單我將使用相同的數據集)
V2 == "b我想交換V1 <-> V3之間的列。使用data.table交換兩列之間的值

dt <- data.table(V1=c(1,2,4), V2=c("a","a","b"), V3=c(2,3,1)) 
#V1 V2 V3 
#1: 1 a 2 
#2: 2 a 3 
#3: 4 b 1 

下面的代碼將是data.frame工作解決方案,但是無奈這個量,因爲已經因爲我使用的是data.table沒有意識到現在我決心要找到data.table的解決方案給我。

dt <- data.table(V1=c(1,2,4), V2=c("a","a","b"), V3=c(2,3,1)) 
df <- as.data.frame(dt) 
df[df$V2 == "b", c("V1", "V3")] <- df[df$V2 == "b", c("V3", "V1")] 
# V1 V2 V3 
#1 1 a 2 
#2 2 a 3 
#3 1 b 4 

我試圖寫一個lapply功能,通過我的目標交換列表循環,試圖縮小問題只能更換一個值,試圖調用方式不同的列名,但都沒有成功。
這是我已經成功地得到最接近的嘗試:

> dt[dt$V2 == "b", c("V1", "V3")] <- dt[dt$V2 == "b", c(V3, V1)] 
#Warning messages: 
#1: In `[<-.data.table`(`*tmp*`, dt$V2 == "b", c("V1", "V3"), value = c(1, : 
# Supplied 2 items to be assigned to 1 items of column 'V1' (1 unused) 
#2: In `[<-.data.table`(`*tmp*`, dt$V2 == "b", c("V1", "V3"), value = c(1, : 
# Supplied 2 items to be assigned to 1 items of column 'V3' (1 unused) 

我們怎樣才能獲得data.table解決方案?

回答

8

我們可以嘗試

dt[V2=="b", c("V3", "V1") := .(V1, V3)] 
+0

我猜使用'.SD'比通過'名單(V1,V3快)'? – BenBarnes

+1

@BenBarnes我沒有測試它是否會更快,看起來像'list(V1,V3)'也可以。 – akrun

+0

@eddi,你反對'.SDcols'?如果您有預定義列的向量,我認爲它是更強大的解決方案。 –

2

僅供娛樂。 @akruns的解決方案顯然是優越的。我的理由是,我可以創建一個臨時副本,使有條件的交換,然後刪除該副本在序列中的所有使用[.data.table操作:

dt[, tv1 := V1][V2=="b", V1 := V3][V2=="b", V3 := tv1][ , tv1 := NULL] 

> dt 
    V1 V2 V3 
1: 1 a 2 
2: 2 a 3 
3: 1 b 4 
+0

這換掉了錯誤的價值!看起來很酷的生活 – Bas

+5

啊,是的,我換了一個「a」值而不是「b」值。似乎很難確定,因爲它會很慢。我只貼了它,讓人們可以扔西紅柿。 –

+0

至少可以做一個'bitwXor'解決方案,如果你打算有趣的話;不是有趣的是 – eddi