R中Excel的AVERAGEIFS()

时间:2019-03-20 16:37:08

标签: r

我正在尝试在数据集上重复使用Excel中的AVERAGEIFS函数所做的事情:

EG_df <- data.frame(id = c("red_blue", "white_blue", "red_yellow","white_yellow", "brown_blue", "brown_yellow"), 
                    StartDate = as.Date(c('2019-1-1','2019-3-1','2019-7-1','2018-1-1','2018-3-1','2018-7-1')),
                    EndDate = as.Date(c('2019-6-1','2019-12-1','2019-8-1','2018-1-1','2018-3-1','2018-7-1')),
                    avg_Value = NA
                    )

source <- data.frame(source.id = c("red_blue", "red_blue", "red_blue","brown_yellow", "brown_yellow", "brown_yellow"),
                      source.Date = as.Date(c('2019-1-1','2019-2-1','2019-3-1','2018-7-1','2018-8-1','2018-9-1')),
                     source.Value = c(22,56,32,31,14,7)
                    )

我需要填写的逻辑 EG.df$avg_Value

对于{strong> EG_df 中的每一行,当source.valuesource.DateStartDate之间时,返回EndDate的平均值。

用于澄清的Excel公式:

  

= AVERAGEIFS(source.value,source.id,id,source.Date,“> =”&StartDate,source.Date,“> =”&EndDate)

任何帮助将不胜感激!

4 个答案:

答案 0 :(得分:1)

使用非等额联接可以非常有效地做到这一点:

library(data.table)
setDT(source); setDT(EG_df)

EG_df[, avg_Value := 
  source[copy(.SD), on=.(source.id = id, source.Date >= StartDate, source.Date <= EndDate), mean(x.source.Value), by=.EACHI]$V1
]

             id  StartDate    EndDate avg_Value
1:     red_blue 2019-01-01 2019-06-01  36.66667
2:   white_blue 2019-03-01 2019-12-01        NA
3:   red_yellow 2019-07-01 2019-08-01        NA
4: white_yellow 2018-01-01 2018-01-01        NA
5:   brown_blue 2018-03-01 2018-03-01        NA
6: brown_yellow 2018-07-01 2018-07-01  31.00000

(由于我仅使用提供的摘录source而不是完整表格,所以存在NAs。)

工作原理

使用x[i, j]的{​​{1}}子集,然后求值i,其中j引用.SD ata的S ubset。< / p>

Dx都是表时,i是一个联接,其中x[i, on=, j, by=.EACHI]指定联接条件,并且on=对表的每一行进行评估j

由于i返回了一个未命名的列,因此它的默认名称为j = mean(x.source.Value)

V1的{​​{1}}内,j通过向其分配x[i, j]来创建或修改列v := val

答案 1 :(得分:1)

使用dplyr天秤座

library(dyplr)

df = EG_df %>% 
     left_join(source, by = c('id' = 'source.id')) %>% 
     filter((StartDate <= source.Date) & (source.Date <= EndDate)) %>% 
     group_by(id, StartDate, EndDate) %>% 
     summarise(value = mean(source.Value))

答案 2 :(得分:0)

使用tidyverse

dplyr::inner_join(source,EG_df,by = c("source.id"="id")) %>%
  dplyr::filter(source.Date >= StartDate,
                source.Date <= EndDate) %>%
  dplyr::group_by(source.id,StartDate,EndDate) %>%
  dplyr::summarise(avg_Value = mean(source.Value))

答案 3 :(得分:0)

考虑运行base的{​​{1}}程序包,以获取ID组和日期范围的平均值。然后merge > subset > aggregate将该结果集返回到原始数据集。

merge

Rextester Demo


在旁边-这类似于SQL的greatest-n-per-group问题(正式的StackOverflow标记),在该问题中, agg_df 是子查询或连接到原始表的CTE。