Выберите / назначить данным.таблица, когда имена переменных хранятся в символьном векторе
как вы ссылаетесь на переменные в data.table
если имена переменных хранятся в символьном векторе? Например, это работает для data.frame
:
df <- data.frame(col1 = 1:3)
colname <- "col1"
df[colname] <- 4:6
df
# col1
# 1 4
# 2 5
# 3 6
как я могу выполнить эту же операцию для сведения.таблица, с или без :=
нотации? Очевидная вещь dt[ , list(colname)]
не работает (и я не ожидал этого).
3 ответа:
два способа программно выберите переменной(ы):
with = FALSE
:DT = data.table(col1 = 1:3) colname = "col1" DT[, colname, with = FALSE] # col1 # 1: 1 # 2: 2 # 3: 3
'dot dot' (
..
) префикс:DT[, ..colname] # col1 # 1: 1 # 2: 2 # 3: 3
для дальнейшего описания 'dot dot' (
..
нотация), см. новые возможности в 1.10.2 (в настоящее время он не описан в тексте справки).до присвоить в переменную(ы), оберните LHS
:=
in скобки:DT[, (colname) := 4:6] # col1 # 1: 4 # 2: 5 # 3: 6
последний известен как столбец plonk, потому что вы заменяете весь вектор столбца ссылкой. Если подмножество
i
присутствовал, он бы назначил по ссылке. Родители вокруг(colname)
- это стенография, введенная в версии v1.9.4 на CRAN Oct 2014. Вот это новость:используя
with = FALSE
С:=
теперь не рекомендуется во всех случаях, учитывая, что упаковка затем из:=
с круглыми скобками был предпочтительным в течение некоторого времени.colVar = "col1" DT[, colVar := 1, with = FALSE] # deprecated, still works silently DT[, (colVar) := 1] # please change to this DT[, c("col1", "col2") := 1] # no change DT[, 2:4 := 1] # no change DT[, c("col1","col2") := list(sum(a), mean(b)] # no change DT[, `:=`(...), by = ...] # no change
см. также подробности на
?`:=`
:DT[i, (colnamevector) := value] # [...] The parens are enough to stop the LHS being a symbol
и ответа на дополнительные вопросы в комментарии, вот один из способов (как обычно есть много способов) :
DT[, colname := cumsum(get(colname)), with = FALSE] # col1 # 1: 4 # 2: 9 # 3: 15
или, возможно, Вам будет легче читать, писать и отлаживать только до
eval
apaste
, аналогично построению динамического оператора SQL для отправки на сервер:expr = paste0("DT[,",colname,":=cumsum(",colname,")]") expr # [1] "DT[,col1:=cumsum(col1)]" eval(parse(text=expr)) # col1 # 1: 4 # 2: 13 # 3: 28
если вы так можно определить вспомогательную функцию
EVAL
:EVAL = function(...)eval(parse(text=paste0(...)),envir=parent.frame(2)) EVAL("DT[,",colname,":=cumsum(",colname,")]") # col1 # 1: 4 # 2: 17 # 3: 45
вот это
data.table
1.8.2 автоматически оптимизируетj
для повышения эффективности может быть предпочтительно использоватьeval
метод. Элементget()
inj
запрещает некоторые оптимизации, например.или нет
set()
. Низкая накладная, функциональная форма:=
, что было бы хорошо здесь. Смотрите?set
.set(DT, j = colname, value = cumsum(DT[[colname]])) DT # col1 # 1: 4 # 2: 21 # 3: 66
*это не ответ на самом деле, но у меня нет достаточно уличного кредита, чтобы оставлять комментарии :/
в любом случае, для тех, кто может искать, чтобы на самом деле создать новый столбец в таблице данных с именем, хранящимся в переменной, у меня есть следующее, чтобы работать. Я понятия не имею, как это работает. Есть предложения по улучшению? Можно ли предположить, что безымянный новый столбец всегда будет иметь имя V1?
colname <- as.name("users") # Google Analytics query is run with chosen metric and resulting data is assigned to DT DT2 <- DT[, sum(eval(colname, .SD)), by = country] setnames(DT2, "V1", as.character(colname))
обратите внимание, что я могу ссылаться на него просто отлично в сумме () но не могу заставить его назначить на том же шаге. Кстати, причина, по которой мне нужно это сделать, - colname будет основываться на вводе пользователя в блестящем приложении.
для нескольких столбцов и функции, применяемой к значениям столбцов.
при обновлении значений из функции, RHS должен быть объектом списка, поэтому с помощью цикла на
.SD
Сlapply
будет делать трюк.В приведенном ниже примере целочисленные столбцы преобразуются в числовые
a1 <- data.table(a=1:5, b=6:10, c1=letters[1:5]) sapply(a1, class) # show classes of columns # a b c1 # "integer" "integer" "character" # column name character vector nm <- c("a", "b") # Convert columns a and b to numeric type a1[, j = (nm) := lapply(.SD, as.numeric ), .SDcols = nm ] sapply(a1, class) # a b c1 # "numeric" "numeric" "character"