У меня огромный data.table
, и мне нужно создавать новые столбцы на основе условий внутри существующих столбцов.
Допустим, мои данные выглядят так:
library(data.table)
dt=data.table(ID=rep(1:3,1000000),LABEL=rep(c("A","A","B"),1000000),COND=rep(c("C","D","D"),1000000),VALUE=sample(letters,1000000,replace=T))
Теперь мне нужно присвоить значения новому столбцу WHATEVER
в зависимости от значений в других столбцах. Допустим, я делаю это в цикле:
dt$WHATEVER=as.numeric(NA)
for(id in dt[,unique(ID)]){
for(label in dt[,unique(LABEL)]){
n=dt[which(ID==id&LABEL==label&COND=="C"),cumsum(grepl("a",VALUE))]
set(dt,
i=dt[,which(ID==id&LABEL==label&COND=="C")],
j="WHATEVER",
value=n)
}
}
Если я system.time()
это, я получаю:
user system elapsed
0.788 0.000 0.788
Однако мой набор данных (и мой код) намного сложнее и занимают часы. Поэтому я попытался setkey
к столбцам, которые я использую для выбора данных как внутри, так и внутри цикла, но я практически не изменился.
setkey(dt,ID,LABEL,COND)
for(id in dt[,unique(ID)]){
for(label in dt[,unique(LABEL)]){
#setkey(dt,ID,LABEL,COND)
n=dt[which(ID==id&LABEL==label&COND=="C"),cumsum(grepl("a",VALUE))]
set(dt,
i=dt[,which(ID==id&LABEL==label&COND=="C")],
j="WHATEVER",
value=n)
}
}
... как видите:
user system elapsed
0.801 0.020 0.820
Есть ли что-то, что я делаю неправильно или могло быть лучше? (Я знаю, что могу изменить, чтобы применить функции. Мой вопрос - data.table wise)
По просьбе Хенрика я покажу пример моего набора данных и объясню, что я пытаюсь сделать. Мой набор данных выглядит так:
ID NAME PROGRAM
1: 2056 CE 348
2: 2056 CE 348
3: 2056 AE 348
4: 2056 CE 348
5: 2056 AE 348
6: 2056 AE 348
7: 2056 CE 348
8: 2056 AE 348
9: 2056 BC 348
10: 2056 CB 348
Я пытаюсь подсчитать, для каждого идентификатора, сколько раз появляется каждое ИМЯ, и назначить для NEWCOLUMN номер, который сообщает мне, какое время это (порядок имеет значение, и, возможно, setkey может испортить это, хотя Я мог бы обойти это), но только для некоторой ПРОГРАММЫ.
Позже я использую значение, назначенное новому столбцу, чтобы создать еще один, который сообщает мне, какое ИМЯ было сделано ПЕРВЫМ и ПОСЛЕДНИМ, снова для каждого идентификатора и только для определенной ПРОГРАММЫ. (Этот еще медленнее, так как он сделан каким-то другим столбцом), хотя ответ PoGibas может помочь ускорить его.