【问题标题】:Using dplyr::mutate between two dataframes to create column based on date range在两个数据帧之间使用 dplyr::mutate 根据日期范围创建列
【发布时间】:2015-03-31 16:02:17
【问题描述】:

现在我有两个数据框。一个包含超过 1100 万行的开始日期、结束日期和其他变量。第二个数据框包含加热度日的每日值(基本上是温度测量值)。

set.seed(1)    
library(lubridate)
date.range <- ymd(paste(2008,3,1:31,sep="-"))
daily <- data.frame(date=date.range,value=runif(31,min=0,max=45))
intervals <- data.frame(start=daily$date[1:5],end=daily$date[c(6,9,15,24,31)])

实际上,我的每日数据框有 9 年的每一天,而我的间隔数据框的条目跨越此时间段内的任意日期。我想要做的是在我的intervals 数据框中添加一个名为nhdd 的列,该列对对应于该时间间隔的每日值求和(不包括结束)。

例如,在这种情况下,此新列的第一个条目将是

sum(daily$value[1:5])

第二个是

sum(daily$value[2:8]) and so on.

我尝试使用以下代码

intervals <- mutate(intervals,nhdd=sum(filter(daily,date>=start&date<end)$value))

这不起作用,我认为这可能与未正确引用列有关,但我不确定该去哪里。

我真的很想使用dplyr 来解决这个问题,而不是循环,因为使用 dplyr 1100 万行将花费足够长的时间。我尝试使用更多 lubridate,但 dplyr 似乎不支持 Period 类。

编辑:我现在实际上使用来自as.Date 的日期而不是lubridate,但如何从mutate 中引用不同数据框的基本问题仍然存在

【问题讨论】:

  • 这个新列的第一个条目不是sum(daily$value[1:6]),新列的第二行不是sum(daily$value[2:9])吗?
  • 它可以是任何一种方式,但我的一个变量是一个 id,并且数据框中的某处有另一行具有相同的 id 并且开始日期与上一个结束日期相同,所以为了避免重复计算,我将结尾设为排他性。

标签: r dplyr


【解决方案1】:
eps <- .Machine$double.eps
library(dplyr)
intervals %>% 
  rowwise() %>% 
  mutate(nhdd = sum(daily$value[between(daily$date, start, end - eps )]))
#       start        end     nhdd
#1 2008-03-01 2008-03-06 144.8444
#2 2008-03-02 2008-03-09 233.4530
#3 2008-03-03 2008-03-15 319.5452
#4 2008-03-04 2008-03-24 531.7620
#5 2008-03-05 2008-03-31 614.2481

如果您发现dplyr 解决方案有点慢(主要是由于rowwise),您可能希望使用data.table 来获得纯速度

library(data.table)
setkey(setDT(intervals), start, end)
setDT(daily)[, date1 := date]
foverlaps(daily, by.x = c("date", "date1"), intervals)[, sum(value), by=c("start", "end")]
#        start        end       V1
#1: 2008-03-01 2008-03-06 144.8444
#2: 2008-03-02 2008-03-09 233.4530
#3: 2008-03-03 2008-03-15 319.5452
#4: 2008-03-04 2008-03-24 531.7620
#5: 2008-03-05 2008-03-31 614.2481

【讨论】:

  • 谢谢!我喜欢简单,只是为了完成并使它更容易一些,我认为您可以将between(daily$date, start, end - eps) 替换为between(daily$date, start, end - 1),这样就不包括最后一天(这是我的代码,即使 eps 到位)
猜你喜欢
  • 1970-01-01
  • 2021-04-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-23
  • 1970-01-01
  • 1970-01-01
  • 2021-07-10
相关资源
最近更新 更多