#r #tidyverse #tidyr
#r #tidyverse #тидыр
Вопрос:
Рассмотрим фрейм данных:
df <- data.frame(x = c(1,2,1,1), y = c("a", "a", "b", "a"))
Применив приведенный ниже код
library(tidyverse)
df %>%
pivot_wider(x, names_from = y, values_from = y, values_fn = length, names_prefix = "tot_", values_fill = 0) %>%
mutate(per_a = 100*tot_a / rowSums(select(.,starts_with("tot_")))) %>%
mutate(per_b = 100*tot_b / rowSums(select(.,starts_with("tot_"))))
человек получает результат
<dbl> <int> <int> <dbl> <dbl>
1 1 2 1 66.7 33.3
2 2 1 0 100 0
Мой вопрос таков: возможно ли получить тот же результат, используя один вызов pivot_wider
, то есть без каких-либо mutate
?
Комментарии:
1. о чем
proportions(table(df), 1)*100
?2. Спасибо, @Onyambu. Однако мотивация моего вопроса заключается в том, чтобы выяснить, может ли такой результат быть достигнут с помощью одного
pivot_wider
.3. Я так не думаю. Это
value_fn
агрегирующая функция, и поэтому в данном случае она не подходит. Вероятно, с помощью одного мутирующего вызова4. В документации говорится, что
value_fn
это может быть список функций, @Onyambu.5. да, все объединяется. т.е. в том, что они работают для каждой группы и дают единый / единый результат. в вашем случае у вас есть группы a и b, которые являются зависимыми, поскольку 66.7 получается путем подсчета всех vlues в a И B перед разделением.
Ответ №1:
Я думаю, вам нужно будет group_by
дважды, если вы хотите выполнить pivot_wider
один раз, не mutate
используя каждый per
столбец в процентах отдельно.
df %>%
group_by(x,y) %>%
count(name="tot") %>%
group_by(x) %>%
mutate(per = tot / sum(tot)) %>%
pivot_wider(id_cols = x, names_from=y, values_from=c(tot,per))
## A tibble: 2 x 5
## Groups: x [2]
# x tot_a tot_b per_a per_b
# <dbl> <int> <int> <dbl> <dbl>
#1 1 2 1 0.667 0.333
#2 2 1 NA 1 NA
Для меня это было бы «аккуратно», поскольку вы выполняете все вычисления в 2 сгруппированных развертках в длинных, аккуратных данных, а не пытаетесь вручную выбрать несколько столбцов в широком формате. формат.
Ответ №2:
дополнительный вариант решения
данные.таблица
df <- data.frame(x = c(1,2,1,1), y = c("a", "a", "b", "a"))
library(data.table)
library(magrittr)
setDT(df)[, list(tot = .N), by = list(x, y)] %>%
.[, perc := proportions(tot), by = list(y)] %>%
dcast(x ~ y, value.var = c("tot", "perc"), fill = 0)
#> x tot_a tot_b perc_a perc_b
#> 1: 1 2 1 0.6666667 1
#> 2: 2 1 0 0.3333333 0
Создано 2021-12-10 пакетом reprex (v2.0.1)
tidyverse
library(tidyverse)
df <- data.frame(x = c(1,2,1,1), y = c("a", "a", "b", "a"))
df %>%
pivot_wider(
x,
names_from = y,
values_from = y,
values_fn = length,
names_prefix = "tot_",
values_fill = 0
) %>%
mutate(across(starts_with("tot_"), proportions, .names = "{.col}_prop"))
#> # A tibble: 2 x 5
#> x tot_a tot_b tot_a_prop tot_b_prop
#> <dbl> <int> <int> <dbl> <dbl>
#> 1 1 2 1 0.667 1
#> 2 2 1 0 0.333 0
Создано 2021-12-10 пакетом reprex (v2.0.1)