Заполнение data.table из меньших data.tables - PullRequest
0 голосов
/ 18 января 2020

Я ищу способ заполнить Result data.table из меньших data.tables, которые приходят из расчетов. Мой подход был следующим:

#CREATE EXAMPLE

library(data.table)

# The empty table to be filled

DT <- data.table(
   "ID" = c("a", "b", "c", "d"),
   "A" = numeric(4),
   "B" = numeric(4))

   ID A B
1:  a 0 0
2:  b 0 0
3:  c 0 0
4:  d 0 0

# Table with part of the results
DT_short <- data.table(
         "ID" = c("a", "b", "d"),
         "A" = 1:3,
         "B" = 1:3)

   ID A B
1:  a 1 1
2:  b 2 2
3:  d 3 3

Я хотел бы заполнить строки и столбцы в соответствии с их именем. Мне удалось получить доступ к части большого data.table, которую я хочу изменить на

nm1 <- names(DT_short)
DT[ID %in% DT_short[, ID], ..nm1]
#Bonus question: Why do I have to assign nm1 before, how do I make it work directly in []?

Теперь я хотел бы заменить эту часть DT на маленькую таблицу DT_short, но все, что я пытался (как <- или :=, или что-то вроде merge) не сработало. Например, ошибка object '..nm1' not found для DT[ID %in% DT_short[, ID], ..nm1] <- DT_short

Пожалуйста, помогите мне, предоставив решение или указав мне правильное направление. (Поскольку данные, с которыми я работаю, довольно маленькие - 10 ^ 2 столбца, 10 ^ 2 строки, ~ 40 небольших файлов, которые нужно объединить, число <10 ^ 9 на поле - и другие люди будут использовать мой код, читаемость важнее, чем производительность.) </p>

РЕДАКТИРОВАТЬ

В ответ Ронак Шах. Когда я тестирую ваше решение с помощью приведенного ниже кода, оно работает отлично, без каких-либо ошибок / предупреждений. Прежде чем принять решение, я хотел бы убедиться, что оно работает и для других / знаю, почему оно вызывает предупреждения для вас, а не для меня.

library(data.table)
packageVersion('data.table')
#[1] ‘1.12.8’

#the empty table to be filled
DT <- data.table(
  "ID" = c("a", "b", "c", "d"),
  "A" = numeric(4),
  "B" = numeric(4),
  "C" = numeric(4)
)
#   ID A B C
#1:  a 0 0 0
#2:  b 0 0 0
#3:  c 0 0 0
#4:  d 0 0 0

#table with part of the results
DT_short <- data.table(
  "ID" = c("a", "b", "d"),
  "A" = 1:3,
  "B" = 1:3
)
#   ID A B
#1:  a 1 1
#2:  b 2 2
#3:  d 3 3

#table with part of the results 2
DT_shorter <- data.table(
  "ID" = c("c"),
  "A" = 7,
  "B" = 70,
  "C" = 3.14
)
#   ID A  B    C
#1:  c 7 70 3.14


DT[match(DT_short$ID, DT$ID), match(names(DT_short), names(DT))] <- DT_short
DT[match(DT_shorter$ID, DT$ID), match(names(DT_shorter), names(DT))] <- DT_shorter
DT
#   ID A  B    C
#1:  a 1  1 0.00
#2:  b 2  2 0.00
#3:  c 7 70 3.14
#4:  d 3  3 0.00

Ответы [ 3 ]

1 голос
/ 20 января 2020

Другой вариант - использовать объединение обновлений:

cols <- setdiff(names(DT_short), "ID")
DT[DT_short, on=.(ID), (cols) := mget(paste0("i.", cols))]
1 голос
/ 18 января 2020

Вот один из возможных подходов. Для каждого столбца в mycols вы хотите присвоить значения из DT_short. Когда вы сделаете это, вы захотите использовать match() и получить индексы, и использовать его для создания нового вектора. Создав новый data.table, вы хотите заменить NA на 0.

library(data.table)

mycols <- names(DT)[2:3]

as.data.table(lapply(mycols, function(x){
    DT_short[match(x = DT$ID, table = DT_short$ID), ..x]}))[,
      (mycols) := replace(x = .SD, list = is.na(.SD), values = 0),
      .SDcols = mycols][]

#   A B
#1: 1 1
#2: 2 2
#3: 0 0
#4: 3 3
0 голосов
/ 19 января 2020

Поскольку вы упомянули, что с другими решениями у вас все в порядке, эту часть легко выполнить с базовыми фреймами данных R путем подстановки строки и столбцов меньших фреймов данных из более крупных и назначения более короткого фрейма данных.

df1 <- data.frame(DT)
df2 <- data.frame(DT_short)
df1[match(df2$ID, df1$ID), match(names(df2), names(df1))] <- df2

df1
#  ID A B
#1  a 1 1
#2  b 2 2
#3  c 0 0
#4  d 3 3

Я не думаю, что правильно делать то же самое с data.table, но если мы запустим приведенный выше код, он будет работать (по крайней мере, для общего примера)

DT[match(DT_short$ID, DT$ID), match(names(DT_short), names(DT))] <- DT_short

, но возвращает большое предупреждающее сообщение, которое подтверждает, что это неверный подход для data.tables.

...