R Заполнение нескольких временных рядов из несбалансированного набора данных панели

У меня есть набор данных панели для ежедневного дохода (и других переменных) по идентификатору, где день с нулевым доходом не сообщается. Я хочу заполнить эти пробелы 0 для своего анализа, что означает, что для каждого временного ряда идентификатора, я должен убедиться, что есть наблюдение за каждым днем. Каждая серия может начинаться или заканчиваться датой, отличной от другой серии. Я пытался использовать пакет "padr", но продолжаю получать ошибку "неиспользованный аргумент", используя следующий пример кода:

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")

Ответы без участия падра также приветствуются.

3 ответа

Решение

Вот новый ответ, который я разработал, который гораздо более применим вне моего одного приложения и использует гораздо меньше кода:

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. Таким образом, для каждого идентификатора его окончательная дата присутствует в столбце 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() 

Поработав некоторое время с падром, я решил написать свою собственную функцию. Эта функция работает для примера, но быстро столкнулась с проблемами с реальными данными. В любом случае, я подумал, что это может пригодиться кому-то еще, поэтому вот оно:

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
Другие вопросы по тегам