如何使用 ggplot2 在 R 中成功实现“热图绘制和保存”循环

eal*_*ns1 1 plot for-loop r heatmap ggplot2

我正在处理调查数据。调查项目有两组,每组三个项目。我的调查样本中有两名受访者。

我正在尝试按调查项目组生成热图,其中:

  • 受访者位于“y”轴上
  • 他们回答的调查项目位于“x”轴上。

这是一个完全可重现的示例:

    wd <- "D:/Desktop/"
    setwd(wd)

    #--create dataframe

    respondent = c("Respondent_1", "Respondent_1", "Respondent_1","Respondent_1", "Respondent_1", "Respondent_1",
                   "Respondent_2", "Respondent_2", "Respondent_2","Respondent_2", "Respondent_2", "Respondent_2")
    item = c("Item_1", "Item_2", "Item_3","Item_1", "Item_2", "Item_3",
             "Item_1", "Item_2", "Item_3","Item_1", "Item_2", "Item_3") 

    item_group = c("Group_1","Group_1","Group_1","Group_2","Group_2","Group_2",
                   "Group_1","Group_1","Group_1","Group_2","Group_2","Group_2")
    score = c(1, 40, 100, 100, 30, 12, 
              2, 15, 80, 77, 44, 10) 

    high_value_color = c("darkred", "darkred", "darkred",
                         "brown3", "brown3", "brown3")

    plot_df = data.frame(respondent, item, item_group, score, high_value_color) 

    #--write function
    #--inspired from this: http://www.reed.edu/data-at-reed/resources/R/loops_with_ggplot2.html

    plot_list <- unique(plot_df$item_group)

    survey_items.graph <- function(df, na.rm = TRUE, ...) {

    #--loop to generate heatmaps for each group

      for (i in seq_along(plot_list)) { 

        plot <-  ggplot(aes(x = df$item[df$item_group == plot_list[i]], 
                            y = df$respondent[df$item_group==plot_list[i]]), 
                        data = subset(df, df$item_group == plot_list[i])) +
          geom_tile(aes(fill = df$score[df$item_group == plot_list[i]]), colour = "black") + 
          scale_fill_gradient2(low = "azure1", 
                               high = df$high_value_color[df$item_group == plot_list[i]], 
                               guide = "colorbar") +
          geom_text(aes(label = df$score[df$item_group==plot_list[i]], 
                        hjust = 0.5, 
                        angle = 90), 
                        size = 4) +
          ggtitle(df$item_group[df$item_group==plot_list[i]]) +
          theme(panel.grid.major = element_blank(),
                panel.grid.minor = element_blank(),
                panel.background = element_blank(),
                plot.title = element_text(size = 7, face="bold"),
                axis.text.y = element_text(size = 7, face ="bold"),
                axis.text.x = element_text(angle=90, hjust=1),
                axis.title = element_blank(),
                legend.position = "none")
        # save plots as .png
        ggsave(plot, file=paste(wd,"plots/heatmap for ", plot_list[i], ".png", sep=""), scale=2)
        print(plot)
      }
    }

    #--load ggplot2

    library(ggplot2)

    #--execute function on plot dataframe
    survey_items.graph(plot_df)
Run Code Online (Sandbox Code Playgroud)

当我执行代码时,我得到以下两个图:

当前地块

我的直觉告诉我,我没有对代码中“scale_fill_gradient2”部分的“high”参数做正确的事情。

作为测试,当我用可接受的颜色字符串值(例如“brown3”,可以在此处找到其他颜色)替换“high”参数的值时,我得到的图的行为符合我的要求。

调整情节

我想要的是“scale_fill_gradient2”的“high”参数接受数据的“high_value_color”变量中找到的相应项目的值。

Axe*_*man 5

好的。主要问题是将颜色传递给scale_fill_gradient2. 但是,您的代码中还有很多可以改进的地方。具体来说,您只想将裸变量名称传递给aes. 我也不明白为什么你不断地到处重复你的子集。你很可能会让自己陷入麻烦。

以下是我可能会如何解决这样的问题:

首先,我们创建一个更简单的函数:它只直接接受一个数据参数,并简单地用该数据绘制所需的图(无循环)。

survey_items.graph <- function(dat) {
  ggplot(aes(x = item, y = respondent), data = dat) +
    geom_tile(aes(fill = score), colour = "black") + 
    scale_fill_gradient2(low = "azure1", 
                         high = dat$high_value_color[1], 
                         guide = "colorbar") +
    geom_text(aes(label = score), hjust = 0.5, angle = 90, size = 4) +
    ggtitle(dat$item_group[1]) +
    theme(panel.grid.major = element_blank(),
          panel.grid.minor = element_blank(),
          panel.background = element_blank(),
          plot.title = element_text(size = 7, face="bold"),
          axis.text.y = element_text(size = 7, face ="bold"),
          axis.text.x = element_text(angle=90, hjust=1),
          axis.title = element_blank(),
          legend.position = "none")
}
Run Code Online (Sandbox Code Playgroud)

然后,我们split将您的数据存储在 data.frames 列表中,每个item_group:

split_data <- split(plot_df, plot_df$item_group)
Run Code Online (Sandbox Code Playgroud)

然后我们将函数应用于列表中的每个条目,创建一个绘图列表:

plot_list <- lapply(split_data, survey_items.graph)
Run Code Online (Sandbox Code Playgroud)

为了方便起见,我习惯grid.arrange将两个图快速拼接在一起:

library(gridExtra)
do.call(grid.arrange, plot_list)
Run Code Online (Sandbox Code Playgroud)

如果你想保存它们,你可以使用类似的东西:

Map(function(x, i, ...) ggsave(paste0('plot', i, '.png'), x, ...), 
    plot_list, seq_along(plot_list), scale = 2)
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  • @ealfons1 当然有不同的方法,但请至少修复你的“aes”调用。你的方式迟早会从背后咬你一口!有一个美好的周末。 (3认同)