Преобразование данных на основе метаданных, избегая циклов for с помощью соединений data.table - PullRequest
0 голосов
/ 26 мая 2020

Проблема: У меня есть следующий объект метаданных data.table. Исходя из этого, я хочу преобразовать столбцы extension и start_date фактической таблицы data.table dt в столбцы даты. У меня есть решение, в котором я перебираю строки meta_dt. Поскольку я хочу избежать циклов for, можете ли вы придумать умное data.table соединение?

library(data.table)

meta_dt <- data.table(
  col_n = c("id", "description", "extension", "start_date"),
  type = c("character", "character", "date", "date"),
  form = c(NA, NA, "%Y-%m-%d", "%Y-%m-%d")
)

dt <- data.table(
  id = c(1, 2, 3, 4),
  description = c("ab", "ac", "ad", "ae"),
  extension = c("2020-01-01", "2020-12-31", "2020-05-01", "2020-01-04"),
  start_date = c("2020-09-01", "2020-11-31", "2020-08-19", "2020-03-14")
)

Ожидаемый результат: Структура ожидаемого результата должна выглядеть следующим образом (т.е. только столбцы, указанные в метаданных как дата, были преобразованы, другие столбцы не затронуты):

Classes ‘data.table’ and 'data.frame':  4 obs. of  4 variables:
 $ id         : num  1 2 3 4
 $ description: chr  "ab" "ac" "ad" "ae"
 $ extension  : Date, format: "2020-01-01" "2020-12-31" ...
 $ start_date : Date, format: "2020-09-01" "2020-11-30" ...

1 Ответ

1 голос
/ 26 мая 2020

Вот вариант с set ():

for (i in seq_along(dt)) {
  correct_type <- meta_dt[col_n == names(dt)[i], type]
  if (!inherits(dt[[i]], correct_type)) {
    if (correct_type %in% c("date", "Date")) {
      format <- meta_dt[col_n == names(dt)[i], form]
      set(dt, j = i, value = as.Date(dt[[i]], format))
    } else {
      set(dt, j = i, value = as(dt[[i]], correct_type))
    }
  }
}

> str(dt)
Classes ‘data.table’ and 'data.frame':  4 obs. of  4 variables:
 $ id         : chr  "1" "2" "3" "4"
 $ description: chr  "ab" "ac" "ad" "ae"
 $ extension  : Date, format: "2020-01-01" "2020-12-31" "2020-05-01" "2020-01-04"
 $ start_date : Date, format: "2020-09-01" NA "2020-08-19" "2020-03-14"

Обратите внимание, что

  • правильное имя класса для объектов даты начинается с верхнего регистра Date
  • 2020-11-31 не является действительной датой в григорианском календаре и поэтому преобразуется в NA.
...