2013-05-30 32 views
46

我有一個data.table,我想在某些列上執行相同的操作。這些列的名稱在字符向量中給出。在這個特定的例子中,我想將所有這些列乘以-1。如何將相同的功能應用於data.table中的每個指定列

有些玩具的數據和矢量指定相關列:

library(data.table) 
dt <- data.table(a = 1:3, b = 1:3, d = 1:3) 
cols <- c("a", "b") 

現在我做這種方式,遍歷的特徵向量:

for (col in 1:length(cols)) { 
    dt[ , eval(parse(text = paste0(cols[col], ":=-1*", cols[col])))] 
} 

有沒有辦法做到這直接沒有for循環?

回答

93

這似乎工作:

dt[ , (cols) := lapply(.SD, "*", -1), .SDcols = cols] 

結果是

a b d 
1: -1 -1 1 
2: -2 -2 2 
3: -3 -3 3 

這裏有一些技巧:

  • 因爲有括號中(cols) :=,結果被分配到cols中指定的列,而不是一些名爲「cols」的新變量。
  • .SDcols告訴我們只查看這些列,並允許我們使用D與這些列關聯的.SDS ubset。
  • lapply(.SD, ...).SD上運行,它是列的列表(如所有data.frames和data.tables)。 lapply返回一個列表,所以最後j看起來像cols := list(...)

編輯:這裏的另一種方式,是可能更快,因爲@Arun提到:

for (j in cols) set(dt, j = j, value = -dt[[j]]) 
+12

另一種方法是使用'set'和'for-loop'。我懷疑它會更快。 – Arun

+3

@阿倫我做了一個編輯。這是你的意思嗎?我之前沒有使用'set'。 – Frank

+0

@弗蘭克,非常!它避免了'.SD'的創建。即使對於這個特定的操作,.SD不應該花費太多,因爲它不是爲每個'by'創建的。但是,我仍然喜歡'設置'這個問題。 – Arun

6

我想補充一個答案,當你想改變的列名好。如果你想計算多列的對數,這在實證工作中經常是這樣。

cols <- c("a", "b") 
out_cols = paste("log", cols, sep = ".") 
dt[, c(out_cols) := lapply(.SD, function(x){log(x = x, base = exp(1))}), .SDcols = cols] 
相關問題