2015-04-04 3 views
3

Я пытаюсь назначить некоторые новые переменные в цикле for (я пытаюсь создать некоторые переменные с общей структурой, но которые подвыборки-зависимые).Назначение через `: =` в цикле `for` (R data.table)

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

DT <- data.table(
    id = rep(1:100, each = 20L), 
    period = rep(-9:10, 100L), 
    grp = rep(sample(4L, size = 100L, replace = TRUE), each = 20L), 
    y = runif(2000, min=0, max=5), key = c("id", "period") 
) 
DT[ , x := cumsum(y), by = id] 
DT2 <- DT[id %in% seq(1, 100, by=2)] 
DT3 <- DT[id %in% seq(1, 100, by=3)] 

for (dd in list(DT, DT2, DT3)){ 
    setkey(setkey(dd, grp)[dd[period==0, sum(x), by = grp], x_at_0_by_grp := V1], id, period) 
} 

Это работает отлично - однако, когда я делаю это, чтобы мой собственный код, он генерирует недействительна .internal.selfref предупреждение (и Безразлично «т создать переменную я хочу):

В [.data.table (SetKey (дт, лечение), дт [posting_rel == 0, сумма (current_balance),: Invalid .internal.selfref обнаружен и фиксируется с копию таблицы , чтобы: = мог добавить этот новый столбец по ссылке. На более ранняя точка, эта таблица данных была скопирована R (или была создана вручную с использованием структуры() или аналогичной). Избегайте ключа < -, имена < - и attr < - который в настоящее время (и странно) может скопировать всю таблицу данных. Используйте вместо этого синтаксис set *, чтобы избежать копирования:? Set,? Setnames и ? Setattr. Кроме того, в R < = v3.0.2 список (DT1, DT2) скопировал весь DT1 и DT2 (список R(), используемый для копирования именованных объектов); обновите до R> v3.0.2, если это кусается. Если это сообщение не помогает, сообщите отчет о работе с данными, чтобы устранить причину.

В самом деле, когда я Подмножество моих данных в только тех столбцы, которые необходим в рамках слияния, он прекрасно работает на моих данных (хотя не сохраняет исходные наборы данных).

Это говорит о том, что это проблема с клавиатурой, но я четко устанавливаю ключи на каждом шагу. Я полностью потерял, как отлаживать это отсюда, потому что я не могу повторить ошибку, кроме моего полного набора данных.

Если я нарушу эту операцию на шаги, ошибка возникает на этапе слияния:

for (dd in list(DT, DT2, DT3)){ 
    dummy <- dd[period==0, sum(x), by = grp] 
    setkey(dd, grp) 
    dd[dummy, x_at_0_by_grp := V1] #***ERROR HERE*** 
    setkey(dd, id, period) 
} 

Быстрое обновление - также производит ошибку, если я бросил это с lapply вместо в for петля.

Любые идеи, что здесь происходит?


UPDATE: Я придумал обходной путь, выполнив:

nnames <- c("dt", "dt2", "dt3") 

dt_list <- list(DT, DT2, DT3) 

for (ii in 1:3){ 
    dummy <- copy(dt_list[[ii]]) 
    dummy[ , x_at_0_by_grp := sum(x[period == 0]), by=grp] 
    assign(nnames[ii], dummy) 
} 

еще хотел бы понять, что происходит, и, возможно, лучший способ присвоения переменных итеративно в подобных ситуациях.

+0

У меня нет объяснения вашей ошибки, но вы можете рассмотреть возможность объединения этих данных в единую таблицу данных и работу с этим. 'DT <- rbindlist (list (dt [, src: = 1], dt2 [, src: = 2], dt3 [, src: = 3]))' Даже если вы не хотите складывать данные, ваши второй шаг не требует слияния, просто используйте 'sum (x [period == 0])' ... 'DT [, x_at_0_by_grp: = sum (x [period == 0]), by =" src, grp " ] ' – Frank

+0

Спасибо за подсказку, чтобы избежать слияния, я об этом не думал. Тем не менее, ошибка все еще возникает, что указывает на то, что проблема заключается в сочетании цикла с вызовом 'list'' data.table' (который упоминается как неприятный в других вопросах, связанных с 'Invalid .internal.selfref') и используя оператор ': =', а не сам слияние. – MichaelChirico

+0

Кроме того, я бы предпочел не объединять данные, потому что 1) каждый поднабор имеет ~ 300 000 наблюдений и 2) я мог бы определить ваш 'src' в моем основном наборе данных как индикатор для подзадачи, но количество подзадач переменные означают, что мне пришлось бы хранить 20-30 переменных с именами подзадачи в исходном наборе данных - более естественным является цикл над наборами данных с постоянным именем для переменных. – MichaelChirico

ответ

1

С 20-30 критериями, сохраняя их за пределами списка (с такими именами, как dt2 и т. Д.), Является слишком неуклюжим, поэтому я просто предполагаю, что у вас есть все они в dt_list.

Я предлагаю сделать таблицы с только стат вы вычислений, а затем rbind ИНГ их:

xxt <- rbindlist(lapply(1:length(dt_list),function(i) 
     dt_list[[i]][,list(cond=i,xx=sum(x[period==0])),by=grp])) 

, который создает

grp cond  xx 
1: 1 1 623.3448 
2: 2 1 784.8438 
3: 4 1 699.2362 
4: 3 1 367.7196 
5: 1 2 323.6268 
6: 4 2 307.0374 
7: 2 2 447.0753 
8: 3 2 185.7377 
9: 1 3 275.4897 
10: 4 3 243.0214 
11: 2 3 149.6041 
12: 3 3 166.3626 

Вы можете легко сливаться обратно, если вы действительно хотите, чтобы эти ВАР , Например, для dt2:

myi = 2 
setkey(dt_list[[myi]],grp)[xxt[cond==myi,list(grp,xx)]] 

Это не решает эту ошибку вы работаете в, но я думаю, что это лучший подход.

+0

Мне это нравится. Две проблемы: 1) некоторые условия не выполняются какой-либо подгруппой - например, одна переменная является квартилями 'x' (выполняется с помощью' cut'), поэтому для хранения этого отдельно требуется столько строк, сколько исходная таблица; 2) Если я хочу объединить все содержимое 'xxt' (что я буду - я в конце концов запускаю регрессии с этими переменными в качестве элементов управления, поэтому гораздо проще иметь все переменные в одной и той же' data.table' и устанавливать ' , data = dt'), кажется, мне понадобится цикл for, который подсказывает мне, что я столкнусь с той же проблемой (не протестировал), если это действительно не проблема с ': =' only. – MichaelChirico

+0

Моя догадка - это ошибка в ': ='. Похоже, у вас есть довольно сложная процедура; Я не знаю, как решить любую из этих проблем. – Frank

Смежные вопросы