R从不平衡的面板数据集中填充多个时间序列

R Padding multiple time series from within an unbalanced panel data set

我有一个按 ID 显示每日收入(和其他变量)的面板数据集,其中收入为 0 的那一天未报告。我想用 0 填充这些空白以进行分析,这意味着对于每个 ID 的时间序列,我需要确保每天都有一个观察值。每个系列可以在不同于其他系列的日期开始或结束。我一直在尝试使用 "padr" 包,但使用以下示例代码时我一直收到 "unused argument" 错误:

library(padr)
library(dplyr)
#unbalanced panel data
ID <- c(1,1,1,1,
        2,2,2,2,2,2,
        3,3,3,3,3,3,3,
        4,4,4)
DT <-  today() + c(1,3,4,5, #ID = 1
                  3,4,7,8,9,10, #ID = 2
                  2,5,6,7,8,9,10, #ID = 3
                  8,10,11) #ID = 4

#The end date denote the max date for each ID
EndDT <-  today() + c(5,5,5,5, #ID = 1
                      13,13,13,13,13,13, #ID = 2
                      10,10,10,10,10,10,10, #ID = 3
                      15,15,15) #ID = 4

#random variables v1 and v2 to represent revenue and other variables
set.seed(1)
v1 <- rnorm(20,mean = 10000, sd = 5)
v2 <- rnorm(20,mean = 5000, sd = 1.5)

df <- as.data.frame(cbind(ID,DT,EndDT,v1,v2))

#format to simpler date
df$DT <- as.Date(DT, origin="1970-01-01")
df$EndDT <- as.Date(EndDT, origin="1970-01-01")

df_padded <- arrange(df,ID,DT) %>%
          pad(by='DT',group='ID', end_val='EndDT') %>%
          fill_by_value(v1,v2, value=0)

我的错误信息:

Error in pad(., by = "DT", group = "ID", end_val = "EndDT") : 
  unused argument (group = "ID")

也非常欢迎不涉及 padr 的回答。

和padr折腾了一段时间,决定自己写一个函数。此函数适用于示例集,但很快 运行 就会遇到真实数据的问题。无论哪种方式,我认为这可能对其他人有用,所以在这里:

date.pad <- function(df, date.var, group, replace.vars, new.val=0){
  require("dplyr")
  require("lazyeval")
  require("lubridate")
  tempdf1 <- arrange_(df,group,date.var)
  finaldf <- tempdf1[0,]
  unique.id <- unique(tempdf1[,group])
  nonreplaced.vars <- setdiff(colnames(tempdf1),replace.vars)
  nonreplaced.vars <- nonreplaced.vars[!nonreplaced.vars==date.var]

  for(i in seq_along(unique.id)){
    filter_criteria <- interp(~y==x, .values=list(y=as.name(group),x=i)) #necessary for NSE
    tempdf2 <- filter_(tempdf1,filter_criteria) 
    min.date <- min(tempdf2[[date.var]])
    max.date <- max(tempdf2[[date.var]])
    all.days <- as.Date(seq(min.date,max.date,by="days"),origin="1970-01-01")
    distinct.days <- unique(tempdf2[,date.var])
    app.days <- as.Date(setdiff(all.days,distinct.days),origin="1970-01-01")
    tempdf3 <- tempdf2[0,]

      for(n in seq_along(app.days)){
          tempdf3[n,date.var] <- app.days[n]
      }
      for(j in seq_along(nonreplaced.vars)){
          tempdf3[1:nrow(tempdf3),nonreplaced.vars[j]] <- tempdf2[1,nonreplaced.vars[j]]
      }
      finaldf <- bind_rows(finaldf,tempdf3)
  }
  finaldf[replace.vars] <-new.val
  finaldf <- bind_rows(finaldf,df) %>% arrange_(group,date.var)
  return(finaldf)
} 

for.exmpl <- date.pad(df=df1, date.var="DT", group="ID", replace.vars=c("v1","v2"), new.val=0)
for.exmpl

这是我设计的一个新答案,它在我的一个应用程序之外更适用,并且使用的代码更少:

library(tidyverse)

temp <- group_by(df1,ID) %>%
        complete(DT = seq.Date(min(DT),max(EndDT),by="day")) %>%
        fill(EndDT,sometext) %>%
        arrange(ID,DT)
temp[is.na(temp)] <- 0
View(temp)

这导致:

# A tibble: 33 x 6
# Groups:   ID [4]
      ID DT         EndDT          v1    v2 sometext
   <dbl> <date>     <date>      <dbl> <dbl> <chr>   
 1    1. 2018-05-04 2018-05-08  9997. 5001. textvar
 2    1. 2018-05-05 2018-05-08     0.    0. textvar
 3    1. 2018-05-06 2018-05-08 10001. 5001. textvar
 4    1. 2018-05-07 2018-05-08  9996. 5000. textvar
 5    1. 2018-05-08 2018-05-08 10008. 4997. textvar
 6    2. 2018-05-06 2018-05-16 10002. 5001. textvar
 7    2. 2018-05-07 2018-05-16  9996. 5000. textvar
 8    2. 2018-05-08 2018-05-16     0.    0. textvar
 9    2. 2018-05-09 2018-05-16     0.    0. textvar
10    2. 2018-05-10 2018-05-16 10002. 5000. textvar
# ... with 23 more rows

(请忽略 "sometext" 变量。我在下面测试我的函数时创建了它。)

您的代码没有 运行,因为您在 end_val 参数中指定了一个字符。这应该是 Date,您只能在所有组中指定一个日期。

为了用 padr 做你想做的事,你应该结合 DT 和 EndDT 列。这样,对于每个 ID,其最终日期都出现在 DT 列中:

df %>% 
  group_by(ID) %>% 
  summarise(DT = max(EndDT)) %>% 
  mutate(v1 = NA, v2 = NA) %>% 
  bind_rows(df %>% select(-EndDT), .) %>% 
  group_by(ID, DT) %>% 
  filter(row_number() == 1) %>% 
  group_by(ID) %>% 
  pad()