Подтвердить что ты не робот

Ссылаясь на столбцы data.table именами, сохраненными в переменных

data.table - фантастический пакет R, и я использую его в библиотеке, которую я разрабатываю. Пока все идет хорошо, за исключением одного осложнения. Кажется, что гораздо сложнее (по сравнению с обычными кадрами данных) ссылаться на столбцы data.table, используя имена, сохраненные в переменных (как для фреймов данных, например: colname="col"; df[df[,colname]<5,colname]=0).

Возможно, что усложняет большинство из них - очевидное отсутствие согласованности синтаксиса на этом в data.table. В некоторых случаях eval(colname) и get(colname), или даже c(colname), похоже, работают. В других случаях решение DT[,colname, with=F] является решением. Однако в других, например, в функциях set() и subset(), я вообще не нашел решения. Наконец, был рассмотрен крайний, хотя и довольно распространенный случай использования (передача имен столбцов в программный файл data.table), и предлагаемые решения, хотя и явно выполняющие свою работу, не кажутся особенно читаемыми...

Возможно, я слишком много усложняю? Если бы кто-нибудь мог наброситься на быстрый чек-лист, ссылаясь на имена столбцов data.table, используя переменные для разных распространенных сценариев, я был бы очень благодарен.

UPDATE:

Некоторые конкретные примеры, которые работают, могут содержать имена столбцов жесткого кода:

x.short = subset(x, abs(dist)<=100)
set(x, which(x$val<10), "val", 0) 

Теперь предположим distcol="dist", valcol="val". Каков наилучший способ сделать это, используя distcol и valcol, но не dist и val?

4b9b3361

Ответ 1

Если вы собираетесь выполнять сложные операции внутри ваших выражений j, вы, вероятно, должны использовать eval и quote. Одна из проблем с текущей версией data.table заключается в том, что среда eval не всегда корректно обрабатывается - eval и quote в data.table (Примечание: там был обновлением этого ответа на основе обновления пакета.) - и текущее исправление для этого - добавить .SD в eval. Насколько я могу судить по нескольким тестам, которые я запускал, это не влияет на скорость (например, имея .SD[1] в j).

Интересно, что этот вопрос вызывает только j, и вы будете нормально использовать eval обычно в i (где .SD пока недоступно).

Другая проблема - назначение, и там у вас должны быть строки. Я знаю один способ извлечь имя строки из цитируемого выражения - это не очень, но это работает. Вот пример, объединяющий все вместе:

x = data.table(dist = c(1:10), val = c(1:10))
distcol = quote(dist)
valcol = quote(val)

x[eval(valcol) < 5,
  capture.output(str(distcol, give.head = F)) := eval(distcol)*sum(eval(distcol, .SD))]

Обратите внимание, как я был в порядке, не добавляя .SD в один eval(distcol), но не будет, если я возьму его из другого eval.

Другой вариант - использовать get:

diststr = "dist"
valstr = "val"

x[get(valstr) < 5, c(diststr) := get(diststr)*sum(get(diststr))]

Ответ 2

Возможно, вы уже знаете об этом решении?

DT[[colname]]

Это вдохновлено решением @eddi в комментариях ниже, используя пример OP:

set.seed(1)
x = data.table(a = 1:10, b=rnorm(10))
colstr="b"
col <- eval(parse(text=paste("quote(",colstr,")",sep="")))
x[eval(col)<0]
x[eval(col)<0,c(colstr):=-100]

Ответ 3

Скажите, что у вас есть имя столбца в переменной x, вы можете сделать

colname = as.name(x)

вы можете использовать colname в функции subset

Ответ 4

eval определенно не рекомендуется для подмножества data.table с использованием динамически сохраняемых переменных. Следующий пример поможет:

# Toy data.table example
DT = data.table(a = c(1,2,3), b = c(4,5,6))

# Saved variable
mVar <- "a"

# Subset
DT[DT[[mVar]] < 2]

eval очень чувствителен к сложным символьным выражениям и обычно не рекомендуется для производственного кода.