r中的复杂求和-不同dfs中的不同列

时间:2018-07-09 11:29:22

标签: r sum

我试图在r中求和。我有2个数据框。其中一列包含3列(标签,开始日期为doy(=年中的某日),结束日期为doy)。另一个由2列组成(doy,bbb(=每天的量))。

现在,我要为df1的每一行从doy.0到doy.end的bbb之和。

# creating df1
tag<-c(1:5)
doy.0<-c(200:204)
doy.end<-c(207:211)
df1<-data.frame(tag, doy.0, doy.end)

# creating df2
doy<-c(200:211)
bbb<-c(12,10,18,16,20,11,15,19,25,23,21,20)
df2<-data.frame(doy,bbb)

  tag doy.0 doy.end
1   1   200     207
2   2   201     208
3   3   202     209
4   4   203     210
5   5   204     211

  doy bbb
1  200  12
2  201  10
3  202  18
4  203  16
5  204  20
6  205  11
7  206  15
8  207  19
9  208  25
10 209  23
11 210  21
12 211  20

所以我想在df1中增加一个bbb之和的列。例如,对于标签1,我希望bbb从doy 200到doy 207(标签1应该为121,标签2应该为134,依此类推)。

我在for循环中玩了一些,但无法弄清楚。我将衷心感谢您的帮助! 另外,如果您可以想到一个更好的标题,请随时进行更改。我什至不知道该怎么称呼这个问题,那真是令人讨厌...

6 个答案:

答案 0 :(得分:0)

您的总和是否始终具有应为8个连续“ bbb”-值之和的模式?然后,它将起作用:

library(dplyr)
library(zoo)    
df1 %>% 
    mutate(newvar = rollsum(df2$bbb, 8))

  tag doy.0 doy.end newvar
1   1   200     207    121
2   2   201     208    134
3   3   202     209    147
4   4   203     210    150
5   5   204     211    154

答案 1 :(得分:0)

df1$sum.bbb<-0

for(i in 1: nrow(df1)){
df1$sum.bbb[i]<-sum(df2[which(df2$doy[] == df1$doy.0[i]):which(df2$doy[] == df1$doy.end[i]),2])
}
> df1
  tag doy.0 doy.end sum.bbb
1   1   200     207     121
2   2   201     208     134
3   3   202     209     147
4   4   203     210     150
5   5   204     211     154

答案 2 :(得分:0)

使用data.frame:

df1b <- do.call(rbind, 
                apply(df1, 
                      1, 
                      function(x) data.frame(tag = rep(x["tag"], x["doy.end"] - x["doy.0"] + 1), 
                                             doy = x["doy.0"]:x["doy.end"])))

merge(df1, aggregate(bbb ~ tag, merge(df1b, df2), sum))
  tag doy.0 doy.end bbb
1   1   200     207 121
2   2   201     208 134
3   3   202     209 147
4   4   203     210 150
5   5   204     211 154

和usign data.table:

library(data.table)
df1 <- as.data.table(df1)
df2 <- as.data.table(df2)

df1[df2, 
    on = .(doy.0 <= doy, doy.end >= doy), 
    allow.cartesian = TRUE][,
      .(doy.0 = min(doy.0), doy.end = max(doy.end), bbb = sum(bbb)),
      by = .(tag)]
   tag doy.0 doy.end bbb
1:   1   200     207 121
2:   2   201     208 134
3:   3   202     209 147
4:   4   203     210 150
5:   5   204     211 154

答案 3 :(得分:0)

使用tidyverse的解决方案,该循环隐藏在purrr :: map中:

replyr::replyr_bind_rows(
  purrr::map(
    replyr::replyr_split(df1,"tag"),
    function(x) data.frame(tag=x$tag,
                           df2 %>% filter((doy>=x$doy.0)&(doy<=x$doy.end)) %>% summarise(bbb=sum(bbb)))
))
#  tag bbb
#1   1 121
#2   2 134
#3   3 147
#4   4 150
#5   5 154

答案 4 :(得分:0)

您可以使用data.table和非等价联接来创建此联接。如果您的总和始终具有相同的模式,则@Len的答案非常好。如果您的总和具有不同的模式,则data.table是一个非常快速的解决方案。

library(data.table)

# add sum of bbb to table 1 from table 2
dt1[, bbb := dt2[dt1, on=.(doy >= doy.0, doy <= doy.end), sum(bbb), by=.EACHI]$V1]


dt1
   tag doy.0 doy.end bbb
1:   1   200     207 121
2:   2   201     208 134
3:   3   202     209 147
4:   4   203     210 150
5:   5   204     211 154

数据:

tag<-c(1:5)
doy.0<-c(200:204)
doy.end<-c(207:211)
dt1<- data.table(tag, doy.0, doy.end) # data.table instead of data.frame

# creating dt2
doy<-c(200:211)
bbb<-c(12,10,18,16,20,11,15,19,25,23,21,20)
dt2<- data.table(doy,bbb) # data.table instead of data.frame

答案 5 :(得分:0)

我们可以进行模糊连接和聚合:

library(fuzzyjoin)
library(dplyr)
fuzzy_join(df1, df2, c(doy.0 = "doy", doy.end = "doy"),
           list(`<=`,`>=`)) %>%
  group_by(tag,doy.0,doy.end) %>%
  summarize_at("bbb",sum) %>%
  ungroup

# # A tibble: 5 x 4
#     tag doy.0 doy.end   bbb
#   <int> <int>   <int> <dbl>
# 1     1   200     207   121
# 2     2   201     208   134
# 3     3   202     209   147
# 4     4   203     210   150
# 5     5   204     211   154

还有R的基础翻译:

x <- expand.grid(tag= df1$tag,doy = df2$doy)
x <- merge(x,df1,all.x=TRUE)
x <- merge(x,df2,all.x=TRUE)
x <- subset(x, doy >= doy.0 & doy <= doy.end)
x <- aggregate(bbb ~ tag, x, sum)
merge(df1,x)
#   tag doy.0 doy.end bbb
# 1   1   200     207 121
# 2   2   201     208 134
# 3   3   202     209 147
# 4   4   203     210 150
# 5   5   204     211 154