ggplot2多变量循环函数问题:按文本与眼动指标生成热力图
Fixing Fill Parameter Mapping in ggplot2 Heatmap Function
你说得没错,问题确实出在geom_tile的fill参数上!当你用fill = Measure_list[j]时,ggplot2会把这个字符串当成一个静态值,而不是去提取数据框中对应列的数值——这就导致热力图没法根据指标数据变化颜色。
下面是两种可行的修复方案,推荐第一种(符合现代tidyverse规范):
方案1:使用.data代词(推荐)
.data是tidyverse提供的特殊代词,用来通过字符串引用数据框的列,完美解决你的问题。同时我们还会修正标题,让它显示具体的指标名称而不是索引:
library(stringr) library(reshape2) library(ggplot2) library(ggthemes) library(tidyverse) # 示例数据集 Text <- c(1,1,1,1,2,2,2,2,1,1,1,1,2,2,2,2) Position <- c(1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4) Modified <- c(1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0) Line_on_page <- c(1, 1, 1, 1, 2,2,2,2 ,1 ,1,1,1,2,2,2,2) IA_FIXATION_DURATION <- c(250.3, 70.82, 400, 120.12, 270, 120.5, 100.54, 212.43, 250.3, 70.82, 320.29, 123.12, 260, 121.5, 100.54, 272.43) IA_FIXATION_COUNT <- c(1,0,1,1,3,2,0, 1, 1,0,1,2,3,2,0, 2) IA_LABEL <- c("she", "did", "not", "know", "what", "to", "say", "to", "she", "did", "not", "know", "what", "to", "do", "to") testDF <- data.frame(Text , Position , Line_on_page, Modified, IA_FIXATION_DURATION, IA_FIXATION_COUNT, IA_LABEL) # 手动指定眼动指标列表(避免包含Text、Position等非目标列) Text_list <- unique(testDF$Text) Measure_list <- c("IA_FIXATION_DURATION", "IA_FIXATION_COUNT") # 创建绘图函数 Heatmap_FN <- function(testDF, na.rm = TRUE, ...){ # 循环生成ggplot2图表 for (i in seq_along(Text_list)) { for (j in seq_along(Measure_list)) { current_text <- Text_list[i] current_measure <- Measure_list[j] plots <- ggplot(subset(testDF, Text == current_text)) + geom_tile(aes(x = Position, y = Line_on_page, fill = .data[[current_measure]])) + geom_text(aes(x = Position, y = Line_on_page, label = IA_LABEL), color = "white", size = 2, family = "sans") + scale_fill_viridis_c(option = "C", na.value = "black") + scale_y_reverse() + facet_grid(Page ~ Modified)+ theme(legend.position = "bottom") + ggtitle(paste("Text", current_text, "| Measure:", current_measure)) ggsave(plots, file = paste(current_measure, "_T", current_text, ".pdf", sep = ""), height = 8.27, width = 11.69, units = "in") } } } # 运行函数 Heatmap_FN(testDF)
关键改动说明:
.data[[current_measure]]:用这个语法告诉ggplot,我们要引用数据框中名为current_measure(字符串)的列,而不是把它当成静态值。- 手动指定
Measure_list:原来的代码会把所有数值列都包含进来(比如Text、Position),这些不是你需要的眼动指标,所以手动指定更准确。 - 优化标题和变量命名:把
Text_list[i]和Measure_list[j]赋值给更清晰的变量,标题也改成更易读的格式。
方案2:使用aes_string()(旧方法)
如果你习惯用旧版的语法,可以用aes_string()来传递字符串形式的参数,但这个方法现在已经不被tidyverse推荐了:
# 仅修改geom_tile部分 geom_tile(aes_string(x = "Position", y = "Line_on_page", fill = current_measure))
这样修改后,你的函数就能正确为每个Text和每个眼动指标生成对应的热力图了!
内容的提问来源于stack exchange,提问作者Grig
相关产品推荐
相关产品推荐

