R создать вложенный скользящий список в data.table

У меня есть data.table dt со следующей структурой:

country calendar_date                                                     net_revenue
 US    2018-05-17                                3.5,28.0, 3.5, 3.5,10.5, 5.6,...
 US    2018-05-18                           3.5,102.9,229.6,  8.4,  3.5,  2.1,...
 US    2018-05-19                                3.5,13.3,35.0, 7.0,52.5, 3.5,...
 US    2018-05-20                          3.85, 7.00,58.10, 7.00, 3.50, 7.00,...
 US    2018-05-21                               17.5, 3.5, 3.5,10.5, 1.4, 3.5,...
 US    2018-05-22        5.60000, 3.50000,17.50000, 3.50000, 2.10000, 7.05516,...
 US    2018-05-23       17.50000,16.10000,58.01507, 2.80000, 5.60000, 3.50000,...
 US    2018-05-24        3.50000,26.72765, 3.50000,12.60000, 3.50000, 3.50000,...
 US    2018-05-25                           2.1,308.0,  2.1,  2.1,  3.5,  3.5,...
 US    2018-05-26        2.10000, 3.50000,88.90000, 3.50000, 3.50000, 7.75859,...
 US    2018-05-27        5.22087,17.50000, 5.60000, 3.50000, 7.00000, 7.00000,...
 US    2018-05-28                                3.5,35.0, 1.4, 3.5, 7.0,28.0,...
 US    2018-05-29                                9.1, 7.0,23.1, 1.4, 1.4, 9.1,...
 US    2018-05-30                                7.7, 2.1,10.5,15.4,65.1, 3.5,...

Если столбец net_revenue является вложенным списком:

str(dt)
Classes ‘data.table’ and 'data.frame':  14 obs. of  3 variables:
 $ country      : chr  "US" "US" "US" "US" ...
 $ calendar_date: chr  "2018-05-17" "2018-05-18" "2018-05-19" "2018-05-20" ...
 $ net_revenue  :List of 14
  ..$ : num  3.5 28 3.5 3.5 10.5 5.6 14 2.1 3.5 28 ...
  ..$ : num  3.5 102.9 229.6 8.4 3.5 ...
  ..$ : num  3.5 13.3 35 7 52.5 3.5 7 35 3.5 19.6 ...
  ..$ : num  3.85 7 58.1 7 3.5 7 1.4 3.5 34.3 2.1 ...
  ..$ : num  17.5 3.5 3.5 10.5 1.4 3.5 15.4 26.6 10.5 5.6 ...
  ..$ : num  5.6 3.5 17.5 3.5 2.1 ...
  ..$ : num  17.5 16.1 58 2.8 5.6 ...
  ..$ : num  3.5 26.7 3.5 12.6 3.5 ...
  ..$ : num  2.1 308 2.1 2.1 3.5 ...
  ..$ : num  2.1 3.5 88.9 3.5 3.5 ...
  ..$ : num  5.22 17.5 5.6 3.5 7 ...
  ..$ : num  3.5 35 1.4 3.5 7 28 3.5 3.5 3.5 7 ...
  ..$ : num  9.1 7 23.1 1.4 1.4 9.1 7 2.1 5.6 2.1 ...
  ..$ : num  7.7 2.1 10.5 15.4 65.1 3.5 28 3.5 24.5 19.6 ...
 - attr(*, ".internal.selfref")=<externalptr>

Что мне нужно сделать, так это создать столбец net_revenue_roll, который объединяет net_revenue списки 7 последних дат для каждого calendar_date по country, то есть "прокрутка (ly)" применяет функцию (list или c) к вложенному списку в данных. таблица по группам.

Что касается аналогичных вопросов (ссылки в конце), я пробовал до сих пор 3 подхода, но ни один из них, похоже, не работает правильно для этой конкретной проблемы:

### Option 1 - rollapplyr
dt[, net_revenue_roll := zoo::rollapplyr (net_revenue, 7L, list), by = c('country')]

### Option 2 - lapply + .SD
dt[, net_revenue_roll := lapply (.SD, function (x) {list (shift(x, 0L:6L, type = 'lag'))}), by = c('country'), .SDcols = c('net_revenue')]

### Option 3 - Reduce + .SD
dt[, net_revenue_roll := Reduce (list, shift(.SD, 0L:6L, type = 'lag')), by = c('country'), .SDcols = c('net_revenue')]

Я подозреваю, что делаю неправильное предположение о порядке применения функций, но не могу найти ошибку. Какие-либо предложения?

Ссылки: Прокрутка по группам в таблице данных R Как взять прокатный продукт с помощью data.table


person Pietro Franzero    schedule 20.07.2018    source источник
comment
поэтому вам нужны последние 7 значений из каждого списка для каждой даты и страны. это вопрос?   -  person YOLO    schedule 20.07.2018
comment
Привет, @YOLO! Нет, я хочу объединить 7 последних списков для каждой группы дат по странам. Отредактировал вопрос, чтобы было понятнее :)   -  person Pietro Franzero    schedule 20.07.2018
comment
Можете ли вы показать структуру вложенного списка, только первую строку   -  person YOLO    schedule 20.07.2018
comment
@YOLO конечно ... Это список с числовым вектором: [[1]] [1] 3.50000 28.00000 3.50000 3.50000 10.50000 5.60000 14.00000 2.10000 3.50000 28.00000 10.50000 3.42755 7.00000 [14] 2.10000 7.00000 7.00000 8.40000 3.50000 10.50000 11.90000 28.00000 3.50000 3.50000 1.40000 3.50000 4.90000 [27] 14.00000   -  person Pietro Franzero    schedule 20.07.2018
comment
РЕДАКТИРОВАТЬ: я добавил кусок кода с str(dt), чтобы прояснить структуру таблицы данных.   -  person Pietro Franzero    schedule 20.07.2018


Ответы (1)


Используя DT из примечания в конце, преобразуйте каждый элемент списка в символьную строку, используйте rollapplyr и преобразуйте обратно.

library(data.table)
library(zoo)

DT[, ch := sapply(net_revenue, toString)][,
  ch := rollapplyr(ch, 7, toString, partial = TRUE), by = "country"][,
  net_revenue := lapply(strsplit(ch, ","), type.convert)][,
  ch:=NULL]

Примечание

Входные данные в воспроизводимой форме:

library(data.table)

Lines <- "
country calendar_date                                             net_revenue
 US    2018-05-17                                3.5,28.0, 3.5, 3.5,10.5, 5.6
 US    2018-05-18                           3.5,102.9,229.6,  8.4,  3.5,  2.1
 US    2018-05-19                                3.5,13.3,35.0, 7.0,52.5, 3.5
 US    2018-05-20                          3.85, 7.00,58.10, 7.00, 3.50, 7.00
 US    2018-05-21                               17.5, 3.5, 3.5,10.5, 1.4, 3.5
 US    2018-05-22        5.60000, 3.50000,17.50000, 3.50000, 2.10000, 7.05516
 US    2018-05-23       17.50000,16.10000,58.01507, 2.80000, 5.60000, 3.50000
 US    2018-05-24        3.50000,26.72765, 3.50000,12.60000, 3.50000, 3.50000
 US    2018-05-25                           2.1,308.0,  2.1,  2.1,  3.5,  3.5
 US    2018-05-26        2.10000, 3.50000,88.90000, 3.50000, 3.50000, 7.75859
 US    2018-05-27        5.22087,17.50000, 5.60000, 3.50000, 7.00000, 7.00000
 US    2018-05-28                                3.5,35.0, 1.4, 3.5, 7.0,28.0
 US    2018-05-29                                9.1, 7.0,23.1, 1.4, 1.4, 9.1
 US    2018-05-30                                7.7, 2.1,10.5,15.4,65.1, 3.5"
L <- trimws(readLines(textConnection(Lines)))
L <- sub("\\s+", ";", L)
L <- sub("\\s+", ";", L)
DF <- read.table(text = L, header = TRUE, sep = ";", as.is = TRUE)
DF$net_revenue <- lapply(strsplit(DF$net_revenue, ","), type.convert)
DT <- as.data.table(DF)
person G. Grothendieck    schedule 21.07.2018
comment
Привет, @ g-grothendieck! Спасибо за ответ. Это была отличная идея - преобразовать в строку - она ​​действительно работает. Однако этот сценарий находится в стадии разработки, поэтому в идеале я бы хотел что-то более эффективное. Я собираюсь проголосовать за ваш ответ сейчас, но я еще не закрываю вопрос - я хочу посмотреть, сможет ли кто-нибудь дать более эффективный ответ. Ваше здоровье - person Pietro Franzero; 21.07.2018