You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 21:28:08