如何在ggplot中使用外部字符值选择x、y变量并绘制实验对比分面图
实验数据对比绘图的简洁实现方案
问题说明
拥有带sect和item索引的多变量(如x、y、z)实验数据,每个实验会生成所有索引对的变量观测值。需要对比两个实验的对应变量(如实验A的x vs 实验B的x,y、z同理),并按变量分面展示绘图,希望用更简洁的tidy方式实现,避免繁琐的数据转换和变量引用操作。
模拟数据代码
library(tidyr) library(dplyr) library(ggplot2) # 模拟实验数据的函数 simdata <- function(experiment_name) { n <- 3 # 分组数量 m <- 7 # 每组条目数量 tibble( sect = factor(rep(1:n, each = m)), item = factor(rep(1:m, n)), x = (1:(n * m))^1.05 + rnorm(n * m), y = (1:(n * m))^1.15 + rnorm(n * m, sd = 2), z = (1:(n * m))^1.25 + rnorm(n * m, sd = 4), experiment = experiment_name ) } # 生成包含A、B、C三个实验的数据集 set.seed(42) d <- bind_rows(simdata("A"), simdata("B"), simdata("C"))
当前实现方法
当前需要两次pivot转换数据,并用!!sym()处理变量引用,代码较为繁琐:
exps <- list(control = "A", alternative = "B") d_reshaped <- d |> pivot_longer( cols = -c(experiment, sect, item), names_to = "var", values_to = "value" ) |> pivot_wider(names_from = "experiment", values_from = "value") d_reshaped |> ggplot(aes( !!sym(exps$control), !!sym(exps$alternative) )) + geom_point(alpha = 0.5) + facet_grid(~var) + coord_fixed() + labs(title = paste("Experiment", exps, collapse = " vs "))
改进的简洁实现
1. 用.data代词简化变量引用
替代!!sym()的官方推荐方式是使用**.data代词**,代码更简洁且无弃用警告:
exps <- c(control = "A", alternative = "B") d_reshaped <- d |> filter(experiment %in% exps) |> # 只保留需要对比的两个实验 pivot_longer(cols = c(x, y, z), names_to = "var", values_to = "value") |> pivot_wider(names_from = experiment, values_from = value) d_reshaped |> ggplot(aes( x = .data[[exps["control"]]], y = .data[[exps["alternative"]]] )) + geom_point(alpha = 0.5) + facet_wrap(~var) + coord_fixed() + labs(title = paste("Experiment", exps, collapse = " vs "))
2. 用合并数据的方式重塑(另一种直观思路)
通过筛选实验数据后按索引合并,再转换为所需格式,逻辑更清晰:
exps <- c(control = "A", alternative = "B") # 分别提取两个实验的数据 d_control <- d |> filter(experiment == exps["control"]) |> select(-experiment) d_alt <- d |> filter(experiment == exps["alternative"]) |> select(-experiment) # 按索引合并,添加后缀区分实验,再转换为长格式后重塑宽格式 d_compare <- inner_join(d_control, d_alt, by = c("sect", "item"), suffix = c("_control", "_alt")) |> pivot_longer( cols = ends_with("_control") | ends_with("_alt"), names_to = c("var", "experiment"), names_sep = "_" ) |> pivot_wider(names_from = experiment, values_from = value) # 绘图(直接引用列名即可) d_compare |> ggplot(aes(x = control, y = alt)) + geom_point(alpha = 0.5) + facet_wrap(~var) + coord_fixed() + labs(title = paste("Experiment", exps, collapse = " vs "))
说明
.data[[col_name]]是tidyverse中推荐的通过字符串引用列名的方式,比!!sym()更简洁且符合现代语法规范。- 数据转换的核心逻辑(将变量转为长格式后按实验拆分宽格式)是实现按变量分面对比的必要步骤,但可以通过提前筛选实验数据减少不必要的计算。
内容的提问来源于stack exchange,提问作者postylem
相关产品推荐
相关产品推荐

