У меня есть список, включающий большое количество временных рядов временных рядов, охватывающих разные годы.Я использую lapply
, чтобы успешно распаковать список, но я хочу что-то быстрее.Одна сложность заключается в том, что некоторые кадры данных пусты, но я хочу вести их учет, чтобы после распаковки я мог cbind
правильно метить данные.
Я синхронизирую свою текущую попытку с примерами данных, используя microbenchmark.
library("plyr")
library("microbenchmark")
# Create some example dataframes of varying length.
ts1 <- data.frame(year=2004:2019, value=14:29)
ts2 <- data.frame(year=2006:2018, value=18:6)
ts3 <- NULL
ts4 <- data.frame(year=2005:2017, value=25:37)
ts5 <- NULL
# Combine the example dataframes into a list.
ts_data <- list(ts1, ts2, ts3, ts4, ts5)
# Function to unpack time series data if not empty and return a dataframe.
fn_unpack_ts <- function(ts) {
if (!plyr::empty(ts)) {
df <- t(ts$value)
colnames(df) <- ts$year
} else {
df <- NA
}
return(as.data.frame(df))
}
# Use lapply to run through each dataframe.
microbenchmark::microbenchmark(
l_ts <- Reduce(plyr::rbind.fill, lapply(ts_data, fn_unpack_ts)), times=100
)
# Tidy up the final dataframe.
l_ts$df <- NULL
Требуемый выходной фрейм данных выглядит следующим образом:
> l_ts
2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019
1 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
2 NA NA 18 17 16 15 14 13 12 11 10 9 8 7 6 NA
3 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
4 NA 25 26 27 28 29 30 31 32 33 34 35 36 37 NA NA
5 NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA NA
И мои собственные временные рамки для100 повторений в миллисекундах - это:
min lq mean median uq max neval
l_ts 2.844698 3.024238 3.283312 3.093525 3.357831 9.21223 100
Я хотел бы знать, существует ли более эффективный подход к распаковке моих примеров данных.Я подозреваю, что это повлечет за собой не возвращение кадра данных каждый раз, но это единственный способ заставить его работать при использовании rbind.fill
для обработки разного количества лет.
ОБНОВЛЕНИЕ
Очень хорошие решения, предложенные #A.Сулиман и # Уве.Мое тестирование с реальными данными, содержащим 1098 строк и 10 повторений, показывает:
expr mean (ms)
Reduce(rbind.fill, lapply(ts_data, fn_unpack_ts)) 1326.2
purrr::map_dfr(ts_data, fn_unpack_ts) 133.7
dcast(rbindlist(ts_data, idcol="id")[CJ(id=seq_along(ts_data),
year, unique=TRUE), on=.(id, year)], id~year) 15.0
... поэтому я объявляю rbindlist
подход победителем.