#r #data.table
#r #data.table
Вопрос:
У меня есть две data.tables в R следующим образом:
DT_A
со столбцами sid
, date
, value1
, value2
, где sid
является первичным ключом и date
является вторичным ключом.
DT_B
содержит столбцы sid
, date1
, date2
, date3
, …., date12
. Вот sid
первичный ключ , и , следовательно , каждая строка соответствует уникальному sid
, а остальные имена столбцов соответствуют вторичным ключам в DT_A
.
Я хочу добавить еще один столбец, в DT_A
который i-я строка содержит соответствующий элемент из таблицы DT_B[sid_i, date_i]
Ниже приведен пример кода и желаемый результат:
require(data.table)
DT_A <- data.table(sid = c(1,2,3,4,5,1,3),
date = c("Jan 2012", "Feb 2012", "April 2012", "May 2012",
"Dec 2012", "Feb 2012", "Oct 2012"),
value1 = rep("1", 7),
value2 = rep("1", 7))
DT_B <- data.table(sid = as.character(c(1,2,3,4,5)),
"Jan 2012" = rep("1", 5),
"Feb 2012" = rep("2", 5),
"March 2012" = rep("3", 5),
"April 2012" = rep("4", 5),
"May 2012" = rep("5", 5),
"June 2012" = rep("6", 5),
"July 2012" = rep("7", 5),
"Aug 2012" = rep("8", 5),
"Sept 2012" = rep("9", 5),
"Oct 2012" = rep("10", 5),
"Nov 2012" = rep("11", 5),
"Dec 2012" = rep("12", 5))
#Set Keys
setkey(DT_A, sid, date)
setkey(DT_B, sid)
#Define Function fun1
fun1 <- function(x){
tryCatch(DT_B[x[1], x[2], with=FALSE], error = function(e) NULL)
}
#Desired Output
DT_A$newCol <- sapply(apply(DT_A, 1, fun1),"[[",1)
DT_A
Хотя мой текущий метод работает на этом небольшом примере, мой фактический DT_A имеет 20 миллионов строк. Этот метод полностью зависает там. Можем ли мы выполнить эту операцию более эффективным способом, используя data.table
or любой другой метод?
Комментарии:
1. Вы не предоставили
DT_A
2. Извините за ошибку, я сделал это сейчас
3. Я думаю, что вопрос следует переформулировать. Речь идет не о выполнении операций по строкам, а о изменении формы и слиянии.
Ответ №1:
Расплавьте свой второй data.table
:
library(reshape2)
DT_B.melted = melt(DT_B, id.vars = 'sid', variable.name = 'date')
После того, как он будет расплавлен, вы можете установить для обоих один и тот же ключ и выполнить соединение / назначение / еще много чего:
setkey(DT_B.melted, sid, date)
setkey(DT_A, sid, date)
DT_A[DT_B.melted, newCol := value]
Комментарии:
1. Я думаю, вам нужно будет добавить
DT_B.melted[,sid:= as.numeric(sid)]
после плавления, иначе он вернет ошибку (по крайней мере, для меня)2. @DavidArenburg вы правы, но я предполагаю, что несоответствие классов — это просто ошибка в OP (т. Е. Это, Вероятно, должно быть исправлено выше по потоку, до того, как начнется плавление)
3. Вау … это работает как ветер, я не знал о функции melt … большое спасибо…