【问题标题】:R: Automatically Producing HistogramsR:自动生成直方图
【发布时间】:2021-07-22 10:28:32
【问题描述】:

我正在使用 R 编程语言。我为此示例创建了以下数据集:

var_1 <- rnorm(1000,10,10)
var_2 <- rnorm(1000, 5, 5)
var_3 <- rnorm(1000, 6,18)

favorite_food <- c("pizza","ice cream", "sushi", "carrots", "onions", "broccoli", "spinach", "artichoke", "lima beans", "asparagus", "eggplant", "lettuce", "cucumbers")
favorite_food <-  sample(favorite_food, 1000, replace=TRUE, prob=c(0.5, 0.45, 0.04, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001))


response <- c("a","b")
response <- sample(response, 1000, replace=TRUE, prob=c(0.3, 0.7))


data = data.frame( var_1, var_2, var_3, favorite_food, response)

data$favorite_food = as.factor(data$favorite_food)
data$response = as.factor(data$response)

从这里开始,我想为这个数据集中的两个分类变量制作直方图,并将它们放在同一页面上:

#make histograms and put them on the same page (note: I don't know why the "par(mfrow = c(1,2))" statement is not working)
par(mfrow = c(1,2))

histogram(data$response, main = "response"))

histogram(data$favorite_food, main = "favorite food"))

我的问题:是否可以为给定数据集中的所有分类变量自动生成直方图(无需手动为每个变量编写“histogram()”语句)并将它们打印在同一页面上?使用“ggplot2”库来解决这个问题会更好吗?

我可以为数据集中的每个单独的分类变量手动编写“histogram()”语句,但我正在寻找一种更快的方法来做到这一点。是否可以使用“for 循环”来做到这一点?

谢谢

【问题讨论】:

  • 注意这段代码的重现性不太好,因为你没有说你使用哪个包来调用histogram,而且这些调用结束时似乎有一些多余的括号
  • [正如后续问题所暗示的,我认为 OP 使用的是hist,但在这里写了histogram。]

标签: r loops ggplot2 data-visualization histogram


【解决方案1】:

这里尝试使用cowplot & ggplot2

library(ggplot2)
library(dplyr)
library(foreach)
library(cowplot)

list_variables <- c("response", "favorite_food")
all_plot <- foreach(current_var = c(list_variables)) %do% {
  # need to do this to avoid ggplot reference to same summary data afterward.
  data_summary_name <- paste0(current_var, "_summary")
  eval(substitute(
    {
      graph_data <- data %>%
        group_by(!!sym(current_var)) %>%
        summarize(count = n(), .groups = "drop") %>%
        mutate(share = count / sum(count))
      plot <- ggplot(graph_data) +
        geom_bar(mapping = aes(x = !!sym(current_var), y = share), width = 1,
          fill = "#00FFFF", color = "#000000", stat = "identity") +
        scale_y_continuous(labels = scales::percent) +
        ggtitle(current_var) + ylab("Perecent of Total") +
        theme_bw()
    }, list(graph_data = as.name(data_summary_name))
  )) 
  return(plot)
}

plot_grid(plotlist = all_plot, ncol = 2)

注意:关于我为什么使用evalsubstitue 的参考,您可以参考ggplot2 generate same plot for different variables in a for loop 上的这个问题

使用 facet_wrap 作为与 QuishSwash 类似的方法,而是以份额计算数据

list_variables <- c("response", "favorite_food")
# Calculate share for choosen variables defined in list_variables 
# You can adjust by having some variables selection based on some condition
summary_df <- bind_rows(foreach(current_var = c(list_variables)) %do% {
  data %>%
    group_by(variable = !!sym(current_var)) %>%
    summarize(count = n(), .groups = "drop") %>%
    mutate(share = count / sum(count),
      variable_name = current_var)
})

ggplot(summary_df) +
  geom_bar(
    aes(x = variable, y = share),
    fill = "#00FFFF", color = "#000000", stat = "identity") +
  facet_wrap(~variable_name, scales = "free") +
  scale_y_continuous(labels = scales::percent) +
  theme_bw()

reprex package (v2.0.0) 于 2021 年 4 月 29 日创建

【讨论】:

  • 谢谢!有没有办法替换list_variables对象,自动把所有变量名放到list_variables中,不用单独写?
  • @stats555 有很多方法可以做到这一点,并且已经在其他答案中说明了。这真的取决于你的数据集。在这种情况下,如果只是考虑因素,那么来自@RonakShah 的cols &lt;- names(data)[sapply(data, is.factor)] 答案简洁而美观
【解决方案2】:

这是在 for 循环中使用 barplot 的基本 R 替代方案:

cols <- names(data)[sapply(data, is.factor)]


#This would need some manual adjustment if number of columns increase
par(mfrow = c(1,length(cols))) 

for(i in cols) {
  barplot(table(data[[i]]), main = i)
}

【讨论】:

【解决方案3】:

ggplot2/tidyverse 的解决方案是将每一列加长为数据,然后使用 faceting 将它们全部绘制在同一页面中:

(编辑以仅绘制因子变量)

factor_vars <- sapply(data, is.factor)

varnames <- names(data)

deselect_not_factors <- varnames[!factor_vars]

library(tidyr)
library(ggplot2)

data_long <- data %>%
  pivot_longer(
    cols = -deselect_not_factors,
    names_to = "category",
    values_to = "value"
  )

ggplot(data_long) +
  geom_bar(
    aes(x = value)
  ) +
  facet_wrap(~category, scales = "free")

【讨论】:

  • 谢谢!但是假设变量都有不同的名称 - 有没有办法只选择分类变量(即因子)?
  • 我已经编辑了通过找出哪些列是因素然后在cols 参数中排除它们来做到这一点pivot_longer
  • 非常感谢!只是一个问题:是否可以使用“dplyr”和“reahape2”库中的函数替换“pivot_longer”开始?再次感谢您的帮助!
  • 使用meltcast 来自reshape2 的一些填充物,您可能可以获得与pivot_longer 相同的结果,但没有真正的理由仍然使用该软件包。 tidyverse(包括dplyrtidyr)是reshape2 的现代和更用户友好的演变。消息:只需安装tidyr
【解决方案4】:

作为替代方案,您可以利用出色的DataExplorer package

请注意,直方图适用于连续变量,因此您希望为分类变量创建条形图。这可以按如下方式完成:

if(require(DataExplorer)==FALSE) install.packages("DataExplorer"); library(DataExplorer)
DataExplorer::plot_histogram(data) # plots histograms for continuous variables
DataExplorer::plot_bar(data) # bar plots for categorical variables

详情请咨询package manual

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-24
    • 1970-01-01
    • 1970-01-01
    • 2019-06-06
    • 1970-01-01
    相关资源
    最近更新 更多