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

如何在ggbetweenstats中自动生成首日期与后续日期的对比列表?

问题描述

我正在随时间测量一些物理指标,希望使用ggbetweenstats绘制小提琴图。想要让第一个日期组与所有后续日期组进行对比,无需为每张图、每一天手动编写并更新comparisons列表。

尝试的思路是选择所有唯一日期,创建一个两列的数据集(第一列为最早日期,第二列为其他所有日期)再转换为列表,但未达到预期效果,运行代码时报错。

可复现代码

library(nycflights13)

CarrierList <- unique(flights$carrier)
i=12
a <- flights %>% mutate(departureDay = lubridate::make_date(year, month, day)) %>% dplyr::filter(origin =="JFK" & carrier==CarrierList[i]& departureDay<="2013-01-10"& departureDay>="2013-01-02") %>% select(departureDay) %>% unique() %>% arrange(departureDay) %>% slice(1) 
aa <- flights %>% mutate(departureDay = lubridate::make_date(year, month, day)) %>% dplyr::filter(origin =="JFK" & carrier==CarrierList[i]& departureDay<="2013-01-10"& departureDay>="2013-01-02") %>% select(departureDay) %>% unique() %>% arrange(departureDay)%>% slice(2:n())

ggbetweenstats(
    data = flights %>% mutate(departureDay = lubridate::make_date(year, month, day)) %>% dplyr::filter(origin =="JFK" & carrier==CarrierList[i] & departureDay<="2013-01-10" & departureDay>="2013-01-02"),
    x=departureDay,
    y = arr_delay,
    pairwise.display = "none",
    p.adjust.method = "holm", 
    type = "nonparametric",   
    ggtheme  = jtools::theme_apa()) +
    ggsignif::geom_signif(map_signif_level = c("***"=0.001, "**"=0.01, "*"=0.05),
                          comparisons = list(data.frame(a$departureDay,aa$departureDay)
                          ))

报错信息

`Computation failed in `stat_signif()`
Caused by error in `mapped_discrete()`:
! Can't convert `x` <data.frame> to <double>.`

期望效果

希望实现手动编写comparisons列表的等价效果(即最早日期分别与后续每个日期对比),示例手动代码如下:

ggbetweenstats(
    data = flights %>% mutate(departureDay = lubridate::make_date(year, month, day)) %>% dplyr::filter(origin =="JFK" & carrier==CarrierList[i] & departureDay<="2013-01-10" & departureDay>="2013-01-02"),
    x=departureDay,
    y = arr_delay,
    pairwise.display = "none",
    p.adjust.method = "holm", 
    type = "nonparametric",   
    ggtheme  = jtools::theme_apa()) +
    ggsignif::geom_signif(y_position = c(300, 310, 320, 330, 340, 350, 360, 370),
                            map_signif_level = c("***"=0.001, "**"=0.01, "*"=0.05),
                          comparisons = list(c("2013-01-02", "2013-01-03"),
                                             c("2013-01-02", "2013-01-04"),
                                             c("2013-01-02", "2013-01-05"),
                                             c("2013-01-02", "2013-01-06"),
                                             c("2013-01-02", "2013-01-07"),
                                             c("2013-01-02", "2013-01-08"),
                                             c("2013-01-02", "2013-01-09"),
                                             c("2013-01-02", "2013-01-10"))
        )

也曾尝试另一种方法,但无法保留日期格式:

b <- lapply(
    1:7,
    function(i) c(
        combn(a$departureDay, 2)[2, i],
        combn(aa$departureDay, 2)[1, i]
    )
)

解决方案

错误原因

你传递给comparisons的是一个包含数据框的列表,但geom_signif要求的是由字符向量组成的列表,每个向量包含两个要对比的组名称(这里是日期的字符形式),直接传入数据框会导致类型转换错误。

正确生成comparisons列表的方法

可以先提取最早日期的字符形式,再将其与后续每个日期的字符形式配对,生成符合要求的列表:

library(nycflights13)
library(tidyverse)
library(ggstatsplot)
library(ggsignif)
library(jtools)
library(lubridate)

# 提前处理数据,避免重复计算
filtered_data <- flights %>% 
  mutate(departureDay = make_date(year, month, day)) %>% 
  filter(origin == "JFK", 
         carrier == CarrierList[12], 
         departureDay >= "2013-01-02", 
         departureDay <= "2013-01-10")

# 获取排序后的唯一日期向量(字符格式)
unique_dates <- filtered_data %>% 
  pull(departureDay) %>% 
  unique() %>% 
  sort() %>% 
  as.character()

# 生成comparisons列表:第一个日期与所有后续日期配对
comparison_list <- map(unique_dates[-1], ~ c(unique_dates[1], .x))

# 绘制图形
ggbetweenstats(
  data = filtered_data,
  x = departureDay,
  y = arr_delay,
  pairwise.display = "none",
  p.adjust.method = "holm", 
  type = "nonparametric",   
  ggtheme = theme_apa()
) +
  ggsignif::geom_signif(
    y_position = seq(300, 370, by = 10),
    map_signif_level = c("***"=0.001, "**"=0.01, "*"=0.05),
    comparisons = comparison_list
  )

关键步骤说明

  1. 提前过滤数据:避免重复执行相同的mutate和filter操作,提升代码效率和可读性。
  2. 统一日期格式为字符:将日期转换为字符形式,确保geom_signif能正确识别组名称。
  3. 用map生成对比列表:利用purrr::map遍历除第一个日期外的所有日期,自动生成每个对比对,无需手动编写。

这样就能自动生成符合要求的comparisons列表,实现第一个日期与所有后续日期的对比,且代码可复用,无需手动更新。


内容的提问来源于stack exchange,提问作者Massimiliano Landini

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 02:24:55