如何根据列的唯一值从数据帧创建时间序列列表?

How can I create a list of time series from a dataframe based off a column's unique values?

提问人:chriswang123456 提问时间:6/29/2021 最后编辑:chriswang123456 更新时间:6/29/2021 访问量:146

问:

创建的数据示例

date = seq(as.Date("2019/01/01"), by = "month", length.out = 48)
productB = rep("B",48)
productB = rep("B",48)
productA = rep("A",48)
productA = rep("A",48)
subproducts1=rep("1",48)
subproducts2=rep("2",48)
subproductsx=rep("x",48)
subproductsy=rep("y",48)
b1 <- c(rnorm(30,5), rep(0,18))
b2 <- c(rnorm(30,5), rep(0,18))
b3 <-c(rnorm(30,5), rep(0,18))
b4 <- c(rnorm(30,5), rep(0,18))

创建数据帧

dfone <- data.frame("date"= rep(date,4),
         "product"= c(rep(productB,2),rep(productA,2)),
         "subproduct"= c(subproducts1,subproducts2,subproductsx,subproductsy),
         "actuals"= c(b1,b2,b3,b4))

如何创建基于上述数据帧上的子产品拆分训练/测试的时间序列列表?有 192 行和 4 个子产品,因此每个子产品有 48 行,这意味着 4 个时间序列,但由于训练和测试拆分,我希望列表中有 8 个元素。

编辑:

for(i in unique(dfone$subproduct)) {
    nam <- paste("df", i, sep = ".")
    assign(nam, dfone[dfone$subproduct==i,])
}

list_df <- list(df.1,df.2,df.x,df.y) %>%
lapply( function(x) x[(names(x) %in% c("date", "actuals"))])

for (i in 1:length(list_df)) {
   assign(paste0("df", i), as.data.frame(list_df[[i]]))
  }
combined_dfs <- merge(merge(merge(df1, df2, by='date', all=T), df3, 
by='date', all=T),df4,by="date",all=T)
colnames(combined_dfs) <-  
c("date","actualB1","actualB2","actualAx","actualAy")


list_ts <- lapply(combined_dfs, function(t) 
ts(t,start=c(2019,1),end=c(2021,6), frequency = 12)) %>%
              lapply( function(t) ts_split(t,sample.out= 
(0.2*length(t))))    # creates my train test split
list_ts <- do.call("rbind", list_ts)  #Creates a list of time series

上面几乎是我想要的,但是有没有更简单的方法来完成 merge(merge() 部分?

r dplyr 时间序列 数据操作 train-test-split

评论


答:

2赞 Jon Spring 6/29/2021 #1

像这样的东西?

library(dplyr)
train_frac = 0.8
dfone_split <- dfone %>%
  mutate(set = sample(c("train", "test"), n(), replace = TRUE, 
                      prob = c(train_frac, 1 - train_frac)))
dfone_train <- dfone_split %>% filter(set == "train")
dfone_test <- dfone_split %>% filter(set == "test")

您还可以查看该软件包,它提供了多种方法来控制拆分,例如在窗口中使用时间采样。rsample

评论

0赞 chriswang123456 6/29/2021
嘿,我已经更新了我上面的帖子。我唯一想改变的是combined_dfs部分。有没有办法更改代码,这样如果我有 100 个独特的子产品,我就不需要连续添加 merge()?
0赞 Jon Spring 6/29/2021
这似乎是一个不同的问题,我在您的帖子中没有看到足够的信息来重现它。我见过类似的问题,答案是这样的:stackoverflow.com/questions/14096814/......
0赞 chriswang123456 6/29/2021
哎呀,我添加了使该代码块运行所需的函数。问题是它并不比我目前拥有的解决方案好。在 R 中使事情自动化/减少硬代码具有挑战性