#r #loops #ggplot2
Вопрос:
У меня есть три столбца в структуре данных: возраст, пол и доход.
Я хочу просмотреть эти столбцы и создать графики на основе содержащихся в них данных.
Я знаю, что в stata вы можете перебирать переменные, а затем запускать команды с этими переменными. Однако приведенный ниже код, похоже, не работает, есть ли эквивалентный способ сделать то, что я хочу сделать в R?
groups <- c(df$age, df$gender, df$income)
for (i in groups){
df %>% group_by(i) %>%
summarise(n = n()) %>%
mutate(prop = n/sum(n)) %>%
ggplot(aes(y = prop, x = i))
geom_col()
}
Ответ №1:
вы также можете использовать tidyverse. Пройдите по вектору имен группирующих переменных с map
помощью . На каждой итерации вы можете оценить !!sym(variable)
имя переменной до group_by
. В качестве альтернативы мы можем использовать across(all_of())
, который может принимать строки непосредственно в качестве имен столбцов. Остальная часть кода в значительной степени совпадает с тем, что вы использовали.
library(dplyr)
library(purrr)
groups <- c('age', 'gender', 'income')
## with !!(sym(.x))
map(groups, ~
df %>% group_by(!!sym(.x)) %>%
summarise(n = n()) %>%
mutate(prop = n/sum(n)) %>%
ggplot(aes(y = prop, x = i))
geom_col()
)
## with across(all_of())
map(groups, ~
df %>% group_by(across(all_of(.x))) %>%
summarise(n = n()) %>%
mutate(prop = n/sum(n)) %>%
ggplot(aes(y = prop, x = i))
geom_col()
)
Если вы хотите использовать цикл for:
groups <- c('age', 'gender', 'income')
for (i in groups){
df %>% group_by(!!sym(i))) %>%
summarise(n = n()) %>%
mutate(prop = n/sum(n)) %>%
ggplot(aes(y = prop, x = i))
geom_col()
}
Комментарии:
1. Тильда-это сокращенная форма для лямбда/анонимных функций в purrr и других пакетах tydiverse, таких как dplyr. Это немного облегчает написание лямбда-функций.
function(x) x
затем может быть просто преобразован в~ .x
. В приведенном выше ответе тильду можно заменить наfunction (.x)
2. Двойной грех взрыва
!!
взят из пакета rlang (и также используется в dplyr). Переменная «группы» представляет собой строку. когда вы преобразуете его в символ с помощью функции sym (), он станет символом (ключом соответствия имени и объекта,). Затем знак двойного взрыва (!!
) вычисляет символ, который возвращает нам нужный столбец. Если вы используете имя столбца непосредственно в качестве строки, оно не будет работать, потому что оно еще не связано ни с одним объектом в фрейме данных. функция group_by() не принимает имена столбцов напрямую. Вы должны преобразовать в символ и оценить.3. Это также можно сделать с помощью других функций dplyr, таких как select() и mutate() или across(), с помощью !! (sym(x)) или с помощью специальных вспомогательных функций, которые принимают строки непосредственно в качестве имен столбцов, таких как
all_of()
илиif_all
4. Я включил версию ответа с
across(all_of))
. Это понятнее для нищих, чем!!(sym(.x))
и в значительной степени то же самое для этого.5. В этом случае вы ищете фактическое значение объекта .x в виде строки, поэтому вам не нужно преобразовывать в символ, просто используйте `ggsave( paste0(«результаты/JS05 — Опрос/», .x, «.png»)
Ответ №2:
Вы можете использовать lapply
df <- data.frame(age = sample(c("26-30", "31-35", "36-40", "41-45"), 20, replace = T),
gender = sample(c("M", "F"), 20, replace = T),
income = sample(c("High", "Medium", "Low"), 20, replace = T),
prop = runif(20))
lapply(df[,c(1:3)], function(x) ggplot(data = df, aes(y = df$prop, x = x)) geom_col())
Комментарии:
1. Большое спасибо, если я не знаю номера столбцов, могу ли я ссылаться на них по имени в lapply?
2. @энтропия, да, ты можешь.