#r #list #data.table #extract
#r #Список #data.table #извлечение
Вопрос:
Я получаю таблицу данных (временные ряды для разных продуктов в зависимости от дат) с внешнего сервера, которая может иметь следующее максимальное количество столбцов (дата всегда является первым столбцом, а все остальные столбцы могут существовать или нет, или есть только два дополнительных столбца или что-то еще):
set.seed(123)
dt.data <- data.table(date = seq(as.Date('2020-01-01'), by = '1 day', length.out = 365),
'DEB Cal-2019' = rnorm(365, 2, 1), 'DEB Cal-2021' = rnorm(365, 2, 1),
'DEB Cal-2022' = rnorm(365, 2, 1), 'DEB Cal-2023' = rnorm(365, 2, 1),
'ATB Cal-2019' = rnorm(365, 2, 1), 'ATB Cal-2021' = rnorm(365, 2, 1),
'ATB Cal-2022' = rnorm(365, 2, 1), 'ATB Cal-2023' = rnorm(365, 2, 1),
'TTF Cal-2019' = rnorm(365, 2, 1), 'TTF Cal-2021' = rnorm(365, 2, 1),
'TTF Cal-2022' = rnorm(365, 2, 1), 'TTF Cal-2023' = rnorm(365, 2, 1),
'NCG Cal-2019' = rnorm(365, 2, 1), 'NCG Cal-2021' = rnorm(365, 2, 1),
'NCG Cal-2022' = rnorm(365, 2, 1), 'NCG Cal-2023' = rnorm(365, 2, 1),
'AUTVTP Cal-2019' = rnorm(365, 2, 1), 'AUTVTP Cal-2021' = rnorm(365, 2, 1),
'AUTVTP Cal-2022' = rnorm(365, 2, 1), 'AUTVTP Cal-2023' = rnorm(365, 2, 1),
'ATW Cal-2019' = rnorm(365, 2, 1), 'ATW Cal-2021' = rnorm(365, 2, 1),
'ATW Cal-2022' = rnorm(365, 2, 1), 'ATW Cal-2023' = rnorm(365, 2, 1),
'BRN Cal-2019' = rnorm(365, 2, 1), 'BRN Cal-2021' = rnorm(365, 2, 1),
'BRN Cal-2022' = rnorm(365, 2, 1), 'BRN Cal-2023' = rnorm(365, 2, 1),
'FEUA MDEC1' = rnorm(365, 2, 1),
check.names = FALSE)
Теперь я хотел бы сохранить / извлечь каждый встречающийся столбец со столбцом даты в его собственной таблице данных. В идеале все извлеченные таблицы данных затем добавляются в список. Я знаю, что я должен как-то сделать это с помощью цикла for, но я не могу его решить.
После того, как я получил отдельные таблицы данных для каждого продукта, мне нужно было бы сделать следующее для каждой из таблиц данных (пример таблицы данных теперь используется здесь для AUTVTP Cal-2022
):
DT <- data.table(date = seq(as.Date('2020-01-01'), by = '1 day', length.out = 365),
'AUTVTP Cal-2022' = rnorm(365, 2, 1), check.names = FALSE)
DT <- DT %>%
mutate(month = format(date, '%b'),
date = format(date, '%d')) %>%
tidyr::pivot_wider(names_from = date, values_from = 'AUTVTP Cal-2022') %>%
relocate(`01`, .after = month)
## Calculate monthly and quarterly mean values: ##
DT <- setDT(DT)[, monthAvg := rowMeans(.SD, na.rm = TRUE), .SDcols = -1]
DT <- DT[, quartAvg := mean(monthAvg), ceiling(seq_len(nrow(DT))/3)]
DT <- DT[, yearAvg := mean(monthAvg), ceiling(seq_len(nrow(DT))/12)]
## Round all values of the data table to 2 digits: ##
DT <- DT %>% mutate_if(is.numeric, round, 2)
КАК Я МОГУ ЭТО СДЕЛАТЬ?
Ответ №1:
Преобразовать в длинный формат, затем разделить.
split(
melt(dt.data, id.vars = "date"),
by = "variable", keep.by = FALSE)
Затем вы можете использовать lapply
для итерации по списку и делать все, что делает ваш код tidyverse.
Однако, как правило, вы не должны разделять data.table. Это неэффективно и часто не требуется.
Редактировать:
Я предлагаю вам забыть о разделении. Оберните свой код в функцию, подобную этой:
foo <- function(DT, colname) {
DT <- DT[, c("date", colname), with = FALSE]
DT <- DT %>%
mutate(month = format(date, '%b'),
date = format(date, '%d')) %>%
tidyr::pivot_wider(names_from = date, values_from = colname) %>%
relocate(`01`, .after = month)
## Calculate monthly and quarterly mean values: ##
DT <- setDT(DT)[, monthAvg := rowMeans(.SD, na.rm = TRUE), .SDcols = -1]
DT <- DT[, quartAvg := mean(monthAvg), ceiling(seq_len(nrow(DT))/3)]
DT <- DT[, yearAvg := mean(monthAvg), ceiling(seq_len(nrow(DT))/12)]
## Round all values of the data table to 2 digits: ##
DT %>% mutate_if(is.numeric, round, 2)
}
Затем, когда вам понадобится таблица для определенного столбца в вашем блестящем приложении, вы можете просто вызвать эту функцию:
foo(dt.data, 'DEB Cal-2019')
Если вы настаиваете на предварительном вычислении списка:
lapply(names(dt.data)[names(dt.data) != "date"],
foo, DT = dt.data)
Комментарии:
1. Когда я использую последнюю часть кода, где я вычисляю ежемесячные, квартальные и годовые средние для каждой таблицы данных списка?
2. Вы делаете это перед разделением. Вы можете использовать
lapply
внутри data.table для перебора столбцов.3. Я не совсем знаком с
apply
соглашением? Поскольку мне нужно рассчитать ежемесячные, квартальные и годовые средние значения для каждой небольшой таблицы данных, как я могу это сделать перед разделением?4. Ваш пример кода мне бесполезен, потому что он написан на tidyverse. Я пользователь старой школы R, который этим не пользуется. Ваше объяснение очень неясно. Вы не должны начинать с разделения data.table. Если вам нужно, вы можете закончить с этим. Я все еще не понял, какова ваша фактическая цель. И, пожалуйста, не объясняйте шаги, которые, по вашему мнению , вам нужны.
5. См
help("setNames")
. .
Ответ №2:
Создайте список фреймов данных, используя и первый столбец для каждого списка. split.default
cbind
lapply(split.default(dt.data[, -1], names(dt.data[, -1])), cbind, dt.data[, 1])
Комментарии:
1. Спасибо за ваш ответ. Но тогда мне все равно придется применять вторую часть кода сверху к каждой отдельной таблице данных в списке (ежемесячное, квартальное, годовое среднее значение для каждой таблицы данных и всех таблиц данных, преобразуемых в широкий формат).
2. Из названия и описания вашего вопроса я понимаю, что вы хотите разделить data.table на два столбца списка таблиц данных, которые дает мой ответ. Если вы пишете функцию, которую хотите применить к каждому отдельному списку, вы можете применить функцию, используя
lapply
i.elapply(result_from_above, fun)
.