Как выполнить цикл по столбцам в R, чтобы создать участки?

#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. @энтропия, да, ты можешь.