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

R新手求助:如何重构数据框以使用ggplot绘制分类条形图

解决ggplot分组条形图的数据格式问题

嘿,我来帮你搞定这个问题!你遇到的核心问题是ggplot只认「长格式(tidy data)」的数据,但你现在创建的是宽格式的数据框——列是日期,行是不同的分组类别,这完全不符合ggplot「每一行对应一个观测值」的要求。下面分两步帮你重构数据并画出想要的分组条形图:

第一步:把现有宽格式数据转成ggplot需要的长格式

首先我们需要把你已经计算好的df_conversionrates转成长格式,这里用tidyr包的pivot_longer函数(属于tidyverse家族,和你已经加载的dplyr、ggplot2完美兼容):

# 先加载tidyr包(如果还没装的话先运行install.packages("tidyr"))
library(tidyr)

# 1. 把行名转换为正式列,再将宽格式转成长格式
df_tidy <- df_conversionrates %>%
  rownames_to_column(var = "category") %>%  # 把行名(分组类别)变成单独一列
  pivot_longer(
    cols = -category,  # 除了category列,其他列都要转成观测行
    names_to = "day",  # 原来的列名(日期)存到day列
    values_to = "conversion_rate"  # 原来的转化率数值存到conversion_rate列
  )

# 2. 给类别改个更友好的名字(可选,但图上显示会更清晰)
df_tidy <- df_tidy %>%
  mutate(category = case_when(
    category == "conversionrate_control" ~ "Control Group",
    category == "conversionrate_treatment" ~ "Treatment Group"
  ))

转完之后,你的数据结构会变成这样(每一行是一个「日期+类别」的独立观测):

categorydayconversion_rate
Control GroupMondayxxx
Control GroupTuesdayxxx
Treatment GroupMondayxxx
.........

第二步:用ggplot绘制分组条形图

现在数据格式符合要求了,直接调用ggplot就能画出你想要的「每个日期对应两个条形」的图:

ggplot(df_tidy, aes(x = day, y = conversion_rate, fill = category)) +
  geom_bar(stat = "identity", position = position_dodge(width = 0.8)) +  # position_dodge让同日期的两个条形并排
  labs(
    title = "Daily Conversion Rates: Control vs Treatment",
    x = "Day of Week",
    y = "Conversion Rate (%)",
    fill = "Group"
  ) +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1))  # 日期标签倾斜,避免重叠

额外优化:跳过宽格式,直接生成tidy数据

其实你完全可以跳过先创建宽格式数据框的步骤,直接用dplyr分组计算并生成符合要求的长格式数据,这样代码更简洁高效:

df_tidy <- rocketfuel %>%
  # 按星期几和测试组分组
  group_by(mode_impr_day, test) %>%
  # 计算转化率
  summarise(
    converted = sum(converted == 1),
    total = n(),
    conversion_rate = (converted / total) * 100,
    .groups = "drop"  # 取消分组状态
  ) %>%
  # 把数字编码的星期几和测试组转换成友好名称
  mutate(
    day = case_when(
      mode_impr_day == 1 ~ "Monday",
      mode_impr_day == 2 ~ "Tuesday",
      mode_impr_day == 3 ~ "Wednesday",
      mode_impr_day == 4 ~ "Thursday",
      mode_impr_day == 5 ~ "Friday",
      mode_impr_day == 6 ~ "Saturday",
      mode_impr_day == 7 ~ "Sunday"
    ),
    category = case_when(
      test == 0 ~ "Control Group",
      test == 1 ~ "Treatment Group"
    )
  ) %>%
  # 只保留我们需要的列
  select(day, category, conversion_rate)

这样你直接用这个df_tidy去绘图就可以了,省去了中间转换的步骤~

内容的提问来源于stack exchange,提问作者Max Fisher

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 20:12:37