如何在约束条件下求和

时间:2019-05-22 15:20:17

标签: r dataframe for-loop constraints cumsum

我需要对与某个日期范围相对应的值求和,并且需要对许多主题进行此操作。

在下一个示例中,df1包含三个主题的开始和结束日期,df2包含日期及其对应的值:

df1<-data.frame(sub=c("a","b","c"), 
                start=as.Date(c("2015/10/13","2015/10/13","2015/10/11")), 
                end=as.Date(c("2015/10/16","2015/10/18","2015/10/15")))

df2<-data.frame(date=seq(as.Date("2015/10/11"), as.Date("2015/10/18"), "days"), 
                value=c(32,30,28,15,19,23,35,18))

> df1
  sub      start        end
1   a 2015-10-13 2015-10-16
2   b 2015-10-13 2015-10-18
3   c 2015-10-11 2015-10-15

> df2
        date value
1 2015-10-11    32
2 2015-10-12    30
3 2015-10-13    28
4 2015-10-14    15
5 2015-10-15    19
6 2015-10-16    23
7 2015-10-17    35
8 2015-10-18    18

我想对df2中的valuestart日期开始到df1中的end日期进行求和,我想对每个sub进行求和(实际上是有很多主题(例如,成对的开始日期和结束日期),所以我认为也许应该使用for循环)。

我希望这样:

sub sum
a   85
b   138
c   124

其中a = 28 + 15 + 19 + 23,b = 28 + 15 + 19 + 23 + 35 + 18,c = 32 + 30 + 28 + 15 + 19

感谢您的帮助

3 个答案:

答案 0 :(得分:1)

一个选项是non-equi联接而无需使用任何循环

library(data.table)
setDT(df2)[df1,  .(sub = sub, sum = sum(value)), 
      on = .(date >= start, date <= end), by = .EACHI][, .(sub, sum)]
#    sub sum
#1:   a  85
#2:   b 138
#3:   c 124

或者以fuzzyjoin的方式使用tidy

library(fuzzyjoin)
library(dplyr)
fuzzy_left_join(df2, df1, by = c(date = 'start', date = 'end'), 
        match_fun = list(`>=`, `<=`)) %>% 
  group_by(sub) %>% 
  summarise(value = sum(value))
# A tibble: 3 x 2
#  sub   value
#  <fct> <dbl>
#1 a        85
#2 b       138
#3 c       124

答案 1 :(得分:1)

使用mapply的选项是在start中的enddf1日期之间创建一个日期序列,并将df2和{ {1}} sum

value

答案 2 :(得分:0)

这可以在单个SQL语句中完成,例如:

library(sqldf)

sqldf("select a.sub, sum(b.value) as sum
  from df1 as a
  left join df2 as b on b.date between a.start and a.end
  group by a.sub")

给予:

  sub   sum
1   a    85
2   b   138
3   c   124