【问题标题】:R: Cumulative sum with missing datesR:缺失日期的累计和
【发布时间】:2015-08-21 10:34:10
【问题描述】:

我有两个数据框,一个(数据框 1)包含日期和每个日期的一些观察结果。在另一个表(数据框 2)中,我的日期比其他数据框中的 更多

我想要做的是计算数据框 1 的累积总和,并将结果放入数据框 2。数据框 2 中存在但数据框 1 中不存在的任何日期都应该简单地具有前一天的值

数据框 1

Date        Obs  
2015-01-10  2  
2015-01-11  3  
2015-01-16  1  
2015-01-20  4  

数据框 2

Date       cumSum
2015-01-09  0
2015-01-10  2
2015-01-11  5
2015-01-12  5
2015-01-13  5
2015-01-14  5
2015-01-15  5
2015-01-16  6
2015-01-17  6
2015-01-18  6
2015-01-19  6
2015-01-20 10
2015-01-21 10

如果有任何不清楚的地方,请告诉我。 任何帮助都会很棒!

谢谢,

迈克

【问题讨论】:

  • 是的,如果不清楚,抱歉

标签: r cumsum


【解决方案1】:

我们可以使用data.table的devel版本,即v1.9.5(安装devel版本的说明是here

我们将第一个 'data.frame' ('df1') 转换为 'data.table' (setDT(df1)),使用 on 选项加入 'df2' 的 'Date' 列(在开发版)。我们通过计算 i (!is.na(Obs)) 中的行索引指定的 'Obs' 的累积总和,根据“Obs”中的非 NA 元素创建“Cumsum”列。然后,我们可以使用 library(zoo) 中的 na.locfNA 值替换为非 NA 以前的值并更新“Cumsum”列。由于 'Obs' 列不在预期的输出中,我们可以将其分配 (:=) 为 NULL。

library(data.table)#v1.9.5+
library(zoo)
res <- setDT(df1)[df2['Date'], on='Date'][!is.na(Obs), Cumsum:=cumsum(Obs)
           ][, Cumsum:=na.locf(Cumsum, na.rm=FALSE)][, Obs := NULL]
res
#         Date Cumsum
# 1: 2015-01-09     NA
# 2: 2015-01-10      2
# 3: 2015-01-11      5
# 4: 2015-01-12      5
# 5: 2015-01-13      5
# 6: 2015-01-14      5
# 7: 2015-01-15      5
# 8: 2015-01-16      6
# 9: 2015-01-17      6
#10: 2015-01-18      6
#11: 2015-01-19      6
#12: 2015-01-20     10
#13: 2015-01-21     10

如果需要,我们可以将 'Cumsum' 中的 NA 值替换为 '0'

res[is.na(Cumsum), Cumsum:=0]

或者正如 @Khashaa 在 cmets 中提到的那样,我们可以在没有 na.locf 的情况下使用 roll=Inf 来做到这一点

 setDT(df1)[,cumSum:=cumsum(Obs),][df2['Date'],
                       on='Date',roll=Inf][, Obs:= NULL][]

或者另一个选项是matchna.locf 以获取数字索引并将非NA索引(来自match)替换为'Obs'的累积总和,如果需要,请像以前一样使用na.locf ,我们可以将NA替换为0。

df2$Cumsum <- na.locf(cumsum(df1$Obs)[match(df2$Date, df1$Date)], na.rm=FALSE)

数据

df1 <- structure(list(Date = structure(c(16445, 16446, 16451, 16455),
class = "Date"), 
Obs = c(2L, 3L, 1L, 4L)), .Names = c("Date", "Obs"), 
row.names = c(NA, -4L), class = "data.frame")

df2 <-  structure(list(Date = structure(c(16444, 16445, 16446, 16447, 
16448, 16449, 16450, 16451, 16452, 16453, 16454, 16455, 16456
), class = "Date"), cumSum = c(0L, 2L, 5L, 5L, 5L, 5L, 5L, 6L, 
6L, 6L, 6L, 10L, 10L)), .Names = c("Date", "cumSum"), row.names = c(NA, 
-13L), class = "data.frame")

【讨论】:

  • 感谢您的回复。我收到一个错误“未使用的参数(on ='Date')。我检查过,我的列名都是“日期”,df1 是一个数据框,df2 也是一个数据框。任何想法为什么会发生这个错误?再次感谢!
  • @Mike on 仅在开发版本中可用。如果您使用的是 1.9.4,我们必须使用 setkey。即 setkey(setDT(df1), 'Date')`
  • 会不会像这样:setkey(setDT(df1)[df2['Date'], on='Date'])[!is.na(Obs), Cumsum:=cumsum(Obs) ][, Cumsum:=na.locf(Cumsum, na.rm=FALSE)][, Obs := NULL]?
  • 太棒了,完美运行!所以 setkey 函数只是告诉函数在加入数据框时使用哪个列名?谢谢阿克伦!!
  • 不去动物园,df1[,cusum:=cumsum(Obs),];df1[df2, roll=Inf]
猜你喜欢
  • 1970-01-01
  • 2020-11-22
  • 2021-11-21
  • 2020-02-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多