Если я правильно понимаю, ОП хочет обновить каждый из фреймов данных в my.list
, чтобы он содержал одну строку для каждой даты, указанной в векторе дат full
База R
В базе R merge()
может использоваться, как уже упоминалось Hack-R .Однако в приведенном ниже ответе это расширяется для работы со всеми кадрами данных в списке:
# creat dataframe from vector of full dates
full.df <- data.frame(Date = full)
# apply merge on each dataframe in the list
lapply(my.list, merge, y = full.df, all.y = TRUE)
[[1]]
Date Sales
1 2016-04-08 5
2 2016-04-09 NA
3 2016-04-10 10
4 2016-04-11 NA
5 2016-04-12 15
6 2016-04-13 NA
7 2016-04-14 20
8 2016-04-15 NA
9 2016-04-16 25
10 2016-04-17 NA
[[2]]
Date Sales
1 2016-04-08 1
2 2016-04-09 2
3 2016-04-10 3
4 2016-04-11 4
5 2016-04-12 5
6 2016-04-13 6
7 2016-04-14 7
8 2016-04-15 8
9 2016-04-16 9
10 2016-04-17 10
Предостережение
В ответе предполагается, что full
охватываетобщий диапазон Date
всех фреймов данных в списке.
Во избежание любых сбоев, общий диапазон Date
можно извлечь из доступных данных в my.list
:
overall_date_range <- Reduce(range, lapply(my.list, function(x) range(x$Date)))
full <- seq(overall_date_range[1], overall_date_range[2], by = "1 days")
Использование rbindlist()
В качестве альтернативы, список структур данных, которые идентичны по структуре, может храниться в большом файле данных.Дополнительный атрибут указывает, к какому продукту относится каждая строка.Однородная структура упрощает последующие операции.
Приведенный ниже код использует функцию rbindlist()
из пакета data.table
для создания большого data.table
.CJ()
( cross join ) создает все комбинации дат и идентификатора продукта, которые затем объединяются / объединяются для заполнения отсутствующих дат:
library(data.table)
all_products <- rbindlist(my.list, idcol = "product.id")[
CJ(product.id = unique(product.id), Date = seq(min(Date), max(Date), by = "1 day")),
on = .(Date, product.id)]
all_products
product.id Date Sales
1: 1 2016-04-08 5
2: 1 2016-04-09 NA
3: 1 2016-04-10 10
4: 1 2016-04-11 NA
5: 1 2016-04-12 15
6: 1 2016-04-13 NA
7: 1 2016-04-14 20
8: 1 2016-04-15 NA
9: 1 2016-04-16 25
10: 1 2016-04-17 NA
11: 2 2016-04-08 1
12: 2 2016-04-09 2
13: 2 2016-04-10 3
14: 2 2016-04-11 4
15: 2 2016-04-12 5
16: 2 2016-04-13 6
17: 2 2016-04-14 7
18: 2 2016-04-15 8
19: 2 2016-04-16 9
20: 2 2016-04-17 10
Последующие операции могут быть сгруппированы по product.id
, например, для определения количества действительных данных о продажах для каждого продукта:
all_products[!is.na(Sales), .(valid.sales.data = .N), by = product.id]
product.id valid.sales.data
1: 1 5
2: 2 10
Или общие продажи заproduct:
all_products[, .(total.sales = sum(Sales, na.rm = TRUE)), by = product.id]
product.id total.sales
1: 1 75
2: 2 55
При необходимости по какой-либо причине результат может быть преобразован обратно в список с помощью
split(all_products, by = "product.id")