Даты совпадения из списка фреймов данных в R - PullRequest
0 голосов
/ 29 мая 2018

У меня есть список из 100+ временных рядов временных рядов my.list с ежедневными наблюдениями за каждым продуктом в отдельном фрейме данных.Некоторые значения являются NA без какой-либо записи даты.Я хотел бы обновить каждый фрейм данных в этом списке, чтобы показать дату и NA, если у него нет записи на эту дату.

Даты:

start = as.Date('2016/04/08')
full <- seq(start, by='1 days', length=10)

Образец временного рядаДанные:

d1 <- data.frame(Date = seq(start, by ='2 days',length=5), Sales = c(5,10,15,20,25))
d2 <- data.frame(Date = seq(start, by= '1 day', length=10),Sales = c(1, 2, 3,4,5,6,7,8,9,10))
my.list <- list(d1, d2)

Я хочу объединить все значения даты full в каждый фрейм данных, и если совпадений не существует, то sales равен NA:

   my.list

[[d1]]
Date    Sales
2016-04-08    5
2016-04-09    NA
2016-04-10    10
2016-04-11    NA
2016-04-12    15
2016-04-13    NA
2016-04-14    20
2016-04-15    NA
2016-04-16    25
2016-04-17    NA


[[d2]]
Date    Sales
2016-04-08    1
2016-04-09    2
2016-04-10    3
2016-04-11    4
2016-04-12    5
2016-04-13    6
2016-04-14    7
2016-04-15    8
2016-04-16    9
2016-04-17    10

1 Ответ

0 голосов
/ 30 мая 2018

Если я правильно понимаю, ОП хочет обновить каждый из фреймов данных в 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")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...