多时间区间完成率绘图:按第三变量拆分的ggplot实现问题
解决方法
你的原代码没法得到正确结果,核心问题是当前数据是宽格式,而ggplot需要的是每一行对应一个独立观测的长格式数据,另外你在aes里的x、y写法完全错误,c(Jan,Feb,Mar)和Jan:Mar都不是正确的变量引用方式。
步骤1:把宽格式数据转成长格式
用tidyr包的pivot_longer函数(属于tidyverse生态,和ggplot2适配性最好),把月份列合并成一列,完成率对应另一列:
# 先加载需要的包 library(tidyverse) # 转换数据格式 df_long <- df %>% pivot_longer(cols = -location, # 除了location列,其他列都要转换 names_to = "month", # 新的月份列名 values_to = "completion_rate") # 新的完成率列名
转换后的df_long结构示例:
# A tibble: 15 × 3 location month completion_rate <int> <chr> <dbl> 1 1 Jan 0.5 2 1 Feb 0.4 3 1 Mar 0.25 4 2 Jan 0.6 5 2 Feb 0.33 6 2 Mar 0.2 ...
步骤2:绘制时间变化图表
现在用长格式数据绘图,因为是展示随时间的变化,用geom_line+geom_point会比单纯的点图更直观:
ggplot(df_long, aes(x = month, y = completion_rate, color = factor(location), group = location)) + geom_line(linewidth = 1) + # 绘制折线 geom_point(size = 3) + # 加上数据点 labs(x = "月份", y = "完成率", color = "地点") + # 设置标签 scale_y_continuous(labels = scales::percent) + # 把y轴转成百分比显示 theme_minimal() # 用简洁的主题
原代码错误原因
- 宽格式下,每个月份是单独的列,ggplot无法直接识别“时间序列”的逻辑,必须把所有月份的数值放到同一列,同时用另一列标记月份。
aes(x=c(Jan,Feb,Mar))这种写法会把三个列的数值直接拼接成一个向量,但丢失了每个数值对应的月份和地点关联;y=Jan:Mar是生成列的索引,完全不是你要的完成率数值,逻辑完全错误。
内容的提问来源于stack exchange,提问作者M3Lba
相关产品推荐
相关产品推荐

