如何使用非每日数据创建每日时间序列

时间:2019-02-08 13:39:28

标签: r dataframe

我有一个这样写的CSV文件

Date        Data
1/5/1980    25
1/7/1980    30
2/13/1980   44
4/13/1980   50

我希望R产生这样的东西

Date        Date
1/1/1980    
1/2/1980
1/3/1980
1/4/1980
1/5/1980    25
1/6/1980 
1/7/1980    30

然后我想R像这样

Date        Date
1/1/1980    
1/2/1980
1/3/1980
1/4/1980
1/5/1980    25
1/6/1980    25
1/7/1980    30

我想要两个单独的data.tables创建一个仅包含实际数据,然后创建另一个具有最后一个观察结果的表。

感谢所有帮助!

编辑:我还将需要填充的所有NA都更改为0

3 个答案:

答案 0 :(得分:1)

解决方案是:

  • 创建具有连续日期的data.frame
  • 将其与原始data.frame合并
  • 使用na.locf中的zoo函数来结转数据

这是代码。我使用lubridate处理日期。

library(lubridate)
df$Date <- mdy(df$Date)
successive <-data.frame(Date =  seq( as.Date(as.yearmon(df$Date[1])), df$Date[length(df$Date)], by="days"))

successive是连续日期的向量。现在正在合并:

result <- merge(df,successive,all.y = T,on = "Date")

向前传播:

library(zoo)
result$Data <- na.locf(result$Data,na.rm = F)


          Date Data
1   1980-01-05   25
2   1980-01-06   25
3   1980-01-07   30
4   1980-01-08   30
5   1980-01-09   30
6   1980-01-10   30
7   1980-01-11   30
8   1980-01-12   30
9   1980-01-13   30
10  1980-01-14   30
11  1980-01-15   30
12  1980-01-16   30
13  1980-01-17   30
14  1980-01-18   30
15  1980-01-19   30
16  1980-01-20   30
17  1980-01-21   30
18  1980-01-22   30
19  1980-01-23   30
20  1980-01-24   30
21  1980-01-25   30

数据:

df <- read.table(text = "Date        Data
                 1/5/1980    25
                 1/7/1980    30
                 2/13/1980   44
                 4/13/1980   50", header = T)

答案 1 :(得分:1)

您也可以使用tidyverse

library(tidyverse)

df %>%
  mutate(Date = as.Date(Date, "%m/%d/%Y")) %>%
  complete(Date = seq(as.Date(format(min(Date), "%Y-%m-01")), max(Date), by = "day")) %>%
  fill(Data) %>%
  replace(., is.na(.), 0)

前10行:

# A tibble: 104 x 2
   Date        Data
   <date>     <dbl>
 1 1980-01-01     0
 2 1980-01-02     0
 3 1980-01-03     0
 4 1980-01-04     0
 5 1980-01-05    25
 6 1980-01-06    25
 7 1980-01-07    30
 8 1980-01-08    30
 9 1980-01-09    30
10 1980-01-10    30

我已将最小日期的月份和年份的第一天,以及最大日期的最大值作为起点;当然可以根据需要进行调整。

编辑:@Sotos对更简洁的方法提出了更好的建议(通过更好地使用format参数):

df %>%
  mutate(Date = as.Date(Date, "%m/%d/%Y")) %>%
  complete(Date = seq(as.Date(format(min(Date), "%Y-%m-01")), max(Date), by = "day")) %>%
  fill(Data)

答案 2 :(得分:1)

假定结果应从第一个日期的月份的第一天开始,并在最后的日期结束,并且输入数据帧在结尾处的注释中可重复显示DF,请转换{{1 }}到动物园对象DF,创建一个日期网格z合并它们,以给出动物园对象g(填充为零)和z0(填充na.locf ),还可以选择将其转换回数据帧,或者直接保留原样,以便您可以使用zoo进行进一步处理。

zz

data.table

该问题提及数据表,如果该问题涉及data.table包,则添加:

library(zoo)

z <- read.zoo(DF, header = TRUE, format = "%m/%d/%Y")
g <- seq(as.Date(as.yearmon(start(z))), end(z), "day")

z0 <- merge(z, zoo(, g), fill = 0)  # zero filled
zz <- na.locf0(merge(z, zoo(, g)))  # na.locf filled

# optional
DF0 <- fortify.zoo(z0)  # zero filled
DF2 <- fortify.zoo(zz)  # na.locf filled

变化

  1. 我不清楚这个问题是在询问零填充答案和library(data.table) DT0 <- data.table(DF0) # zero filled DT2 <- data.table(DF2) # na.locf filled 填充答案,还是只是na.locf填充答案,其剩余NA值均为0填充但假定前一种情况。如果您想填写na.locf填写的答案中剩下的NA,请添加:

    na.locf
  2. 如果要在上个月末而不是最后日期结束,请用zz[is.na(zz)] <- 0 替换end(z)

  3. 如果要从第一个日期而不是第一个月的第一个月开始,请用as.Date(as.yearmon(end(z)), frac = 1)替换as.Date(as.yearmon(start(z)))

  4. 作为(3)的替代方法,从第一个日期开始到最后一个日期结束,我们可以简单地转换为start(z)然后返回。请注意,由于ts类无法直接处理Date类,因此我们需要在第二行还原ts类。

    Date

注意

z2.na <- as.zoo(as.ts(z))
time(z2.na) <- as.Date(time(z2.na))
zz20 <- replace(z2.na, is.na(z2.na), 0)     # zero filled
zz2 <- na.locf0(z2.na)                      # na.locf filled