Excel AVERAGEIFS () в R - PullRequest
       2

Excel AVERAGEIFS () в R

1 голос
/ 20 марта 2019

Я пытаюсь продублировать то, что вы будете делать с функцией AVERAGEIFS в Excel в моем наборе данных:

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:

Для каждой строки в EG_df вернуть среднее значение source.value, когда source.Date находится между StartDate и EndDate.

Формула Excel, для уточнения:

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

Любая помощь будет принята с благодарностью!

Ответы [ 4 ]

1 голос
/ 20 марта 2019

Использование библиотеки 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))
1 голос
/ 20 марта 2019

Вы можете сделать это довольно эффективно с помощью неэквивалентного соединения:

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

(Есть NA, так как я просто использую предоставленную выдержку source вместо полной таблицы.)

Как это работает

x[i, j] подмножеств с использованием i, а затем оценивает j, внутри которого .SD относится к S ubset D ata.

Когда x и i являются обеими таблицами, x[i, on=, j, by=.EACHI] является соединением, где on= задает условия соединения и j оценивается для каждой строки i.

Поскольку j = mean(x.source.Value) возвращает неназванный столбец, он получает имя по умолчанию V1.

Внутри j из x[i, j], v := val создает или изменяет столбец v, присваивая ему val.

0 голосов
/ 20 марта 2019

Рассмотрим пакет base с merge > subset > aggregate для средних значений по группе идентификаторов и диапазону дат.Затем merge этот набор результатов возвращается к исходному набору данных.

# MERGE > SUBSET > AGGREGATE
agg_df <- aggregate(cbind(avgValue=source.Value) ~ id + StartDate + EndDate,
                    subset(merge(EG_df, source, by.x="id", by.y="source.id", all.x=TRUE),
                           source.Date >= StartDate & source.Date <= EndDate),
                    FUN=mean)

# MERGE WITH ORIGINAL DATASET
merge(EG_df, agg_df, by=c("id", "StartDate", "EndDate"), all.x=TRUE)

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

Rextester Demo


В стороне - это похоже на проблему SQL наибольшее-на-группу (официальный StackOverflowtag) где agg_df будет подзапросом или CTE, присоединенным к исходной таблице.

0 голосов
/ 20 марта 2019

с использованием 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))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...