#r #dplyr #subset
#r #дплыр #подмножество #dplyr
Вопрос:
Я хочу рассчитать средний объем для каждой группы, установив свой фрейм данных между двумя диапазонами дат.
Я заметил, что не все продукты имеют записи между этими двумя датами и нуждаются в каком-то способе их обработки, поскольку прямо сейчас они записываются как пробелы, в идеале они должны быть заполнены 0, а не пробелами.
Вот повторный:
product <- c("A","A","A","A","B","B","B","B","C")
date1 <- c("2020-06-20","2020-06-26","2020-08-20","2020-08-22","2020-06-26","2020-06-27","2020-08-21","2020-08-22","2019-06-20")
winA_start <- rep("2020-06-24", times = 9)
winA_end <- rep("2020-06-30", times = 9)
winB_start <- rep("2020-08-19", times = 9)
winB_end <- rep("2020-08-26", times = 9)
vol <- c(200,201,600,800,800,1000,50,100,208)
x <- data.frame(product,date1,winA_start,winA_end,winB_start,winB_end,vol)
x[,2:6] <- lapply(x[,2:6], as.Date)
Я хочу запустить следующий код, чтобы вычислить среднее значение как для окна A, так и для окна B
y <- x %>% group_by(product) %>% mutate(WIN_A_AVG = round(mean(vol[date1 >= winA_start amp; date1 <= winA_end]), digits = 0), WIN_B_AVG = round(mean(vol[date1 >= winB_start amp; date1 <= winB_end]), digit = 0))
Это работает по желанию, за исключением продукта C, где date1 не соответствует критериям и поэтому возвращает NaN.
Вместо того, чтобы возвращать NaN, есть ли способ, которым я мог бы отлавливать ошибки такого типа и просто возвращать 0 элегантным способом?
Ответ №1:
Если все, что вы хотите сделать, это изменить отсутствующие данные на ноль, вы можете сделать это в том же операторе mutate .
y <- x %>%
group_by(product) %>%
mutate(WIN_A_AVG = round(mean(vol[date1 >= winA_start amp; date1 <= winA_end]), digits = 0),
WIN_B_AVG = round(mean(vol[date1 >= winB_start amp; date1 <= winB_end]), digit = 0),
WIN_A_AVG = case_when(is.na(WIN_A_AVG) ~ 0,
TRUE ~ WIN_A_AVG),
WIN_B_AVG = case_when(is.na(WIN_B_AVG) ~ 0,
TRUE ~ WIN_B_AVG))
Здесь case_when()
функция просто указывает, что когда результат отсутствует, замените его нулем, в противном случае оставьте его прежним. Однако, если вы хотите отслеживать только те случаи, когда наблюдений не было, тогда вам понадобится что-то вроде приведенного ниже кода. Сначала определяется количество наблюдений, затем заменяются только те, которые имеют нулевые наблюдения на 0. Это будет работать лучше, если есть вероятность, что отсутствуют данные, vol
такие, что вы хотели бы, чтобы среднее значение возвращалось NA
иногда в качестве проверки.
y <- x %>%
group_by(product) %>%
mutate(WIN_A_N = length(vol[date1 >= winA_start amp; date1 <= winA_end]),
WIN_B_N = length(vol[date1 >= winA_start amp; date1 <= winA_end]),
WIN_A_AVG = round(mean(vol[date1 >= winA_start amp; date1 <= winA_end]), digits = 0),
WIN_B_AVG = round(mean(vol[date1 >= winB_start amp; date1 <= winB_end]), digit = 0),
WIN_A_AVG = case_when(WIN_A_N == 0 ~ 0,
TRUE ~ WIN_A_AVG),
WIN_B_AVG = case_when(WIN_B_N == 0 ~ 0,
TRUE ~ WIN_B_AVG)) %>%
select(-WIN_A_N, -WIN_B_N)
y
# A tibble: 9 x 9
# Groups: product [3]
# product date1 winA_start winA_end winB_start winB_end vol WIN_A_AVG WIN_B_AVG
# <chr> <date> <date> <date> <date> <date> <dbl> <dbl> <dbl>
#1 A 2020-06-20 2020-06-24 2020-06-30 2020-08-19 2020-08-26 200 201 700
#2 A 2020-06-26 2020-06-24 2020-06-30 2020-08-19 2020-08-26 201 201 700
#3 A 2020-08-20 2020-06-24 2020-06-30 2020-08-19 2020-08-26 600 201 700
#4 A 2020-08-22 2020-06-24 2020-06-30 2020-08-19 2020-08-26 800 201 700
#5 B 2020-06-26 2020-06-24 2020-06-30 2020-08-19 2020-08-26 800 900 75
#6 B 2020-06-27 2020-06-24 2020-06-30 2020-08-19 2020-08-26 1000 900 75
#7 B 2020-08-21 2020-06-24 2020-06-30 2020-08-19 2020-08-26 50 900 75
#8 B 2020-08-22 2020-06-24 2020-06-30 2020-08-19 2020-08-26 100 900 75
#9 C 2019-06-20 2020-06-24 2020-06-30 2020-08-19 2020-08-26 208 0 0