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

时间:2016-09-02 19:37:07

标签: r for-loop plot ggplot2 heatmap

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

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

  • 受访者在'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)

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

current plots

我的直觉告诉我,我没有用我的代码的'scale_fill_gradient2'部分的'high'参数做正确的事情。

作为测试,当我用可接受的颜色字符串值替换'high'参数的值(例如'brown3',其他颜色可以找到here)时,我得到的图表是表现得像我想要的那样。

tweaked plots

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

1 个答案:

答案 0 :(得分:3)

确定。主要问题是将颜色传递给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")
}

然后我们会在data.frames列表中split提升您的数据,每item_group一个:

split_data <- split(plot_df, plot_df$item_group)

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

plot_list <- lapply(split_data, survey_items.graph)

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

library(gridExtra)
do.call(grid.arrange, plot_list)

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

Map(function(x, i, ...) ggsave(paste0('plot', i, '.png'), x, ...), 
    plot_list, seq_along(plot_list), scale = 2)

enter image description here