#r #dplyr
Вопрос:
Я сталкиваюсь со странностью summarise
, используя case_when
с. Я использую case_when
, потому что мне нужно выполнить другой расчет для подмножества моих групп. Но когда я это делаю, группы не распадаются, как ожидалось. Когда я запустил его без case_when
, он рухнул. Вот пример.
Вот что я попробовал.
df %>%
group_by(grp) %>%
summarize(value = case_when(grp == "g4" ~ sum(x),
T ~ weighted.mean(x, w)),
.groups = "keep") %>%
ungroup()
## A tibble: 12 x 2
#grp value
#<chr> <dbl>
#1 g1 0.466
#2 g1 0.466
#3 g1 0.466
#4 g2 0.439
#5 g2 0.439
#6 g2 0.439
#7 g3 0.0885
#8 g3 0.0885
#9 g3 0.0885
#10 g4 15839
#11 g4 15839
#12 g4 15839
Как вы можете видеть, все группы дублируются, а не сворачиваются. Если я выну case_when
(или ifelse
) и использую одно вычисление для столбца, то фрейм данных выйдет, как и ожидалось, хотя значение «g4» неверно, так как я не использовал правильную функцию.
df %>%
group_by(grp) %>%
summarize(value = weighted.mean(x, w),
.groups = "keep") %>%
ungroup()
## A tibble: 4 x 2
#grp value
#<chr> <dbl>
#1 g1 0.466
#2 g2 0.439
#3 g3 0.0885
#4 g4 6726.
Что здесь происходит и как мне это исправить? Я знаю, что могу использовать distinct
, но я хотел бы сделать это правильно и понять, почему я не получаю ожидаемый результат.
Данные:
df <- structure(list(var = c("A", "A", "A", "A", "B", "B", "B", "B",
"C", "C", "C", "C"), grp = c("g1", "g2", "g3", "g4", "g1", "g2",
"g3", "g4", "g1", "g2", "g3", "g4"), x = c(0.374, 0.348, 0.067,
1531, 0.484, 0.461, 0.088, 8943, 0.47, 0.437, 0.095, 5365), w = c(4300,
4300, 4300, 4300, 19572, 19572, 19572, 19572, 15461, 15461, 15461,
15461)), row.names = c(NA, -12L), class = c("tbl_df", "tbl",
"data.frame"))
Ответ №1:
Это связано с тем, что grp == "g4"
сравнение возвращает более одного значения в каждой группе. Например, для группы 'g1'
он возвращает 3 значения.
df$grp[df$grp == 'g1'] == "g4"
#[1] FALSE FALSE FALSE
Поскольку входным условием является длина 3, выходные данные также будут иметь 3 значения. Чтобы иметь только одно значение в каждой группе, условие также должно возвращать только одно значение. Ты можешь завернуть его внутрь all
.
library(dplyr)
df %>%
group_by(grp) %>%
summarize(value = case_when(all(grp == "g4") ~ sum(x),
T ~ weighted.mean(x, w)),
.groups = "drop")
# A tibble: 4 x 2
# grp value
# <chr> <dbl>
#1 g1 0.466
#2 g2 0.439
#3 g3 0.0885
#4 g4 15839
Вы также можете использовать if
/ else
, так как здесь есть только 2 результата.
df %>%
group_by(grp) %>%
summarize(value = if(all(grp == "g4")) sum(x) else weighted.mean(x, w), .groups = "drop")