在R语言ggplot2中为时间序列折线添加末尾州名标签
解决思路与代码
你的问题核心是当前数据是宽格式(每个州单独一列),这种结构下直接用geom_text/geom_label会因为数据匹配逻辑冲突报fortify错误。正确的做法是先把数据转成ggplot友好的长格式,再统一处理折线和标签:
步骤1:转长格式数据
用tidyr::pivot_longer把宽格式转为长格式,让州名和对应接种量成为单独的列,方便后续分组绘图和加标签:
# 先加载依赖包(未安装的话先运行 install.packages(c("tidyr", "dplyr"))) library(tidyr) library(dplyr) library(ggplot2) # 转长格式:保留日期列,其他列转为「州名」和「接种量」两列 pf_long <- pivot_longer(pf, cols = -newDate, # 除newDate外的所有列都转成州数据 names_to = "state", values_to = "doses") # 给州设置颜色分组(对应你原来的红蓝分组) color_groups <- data.frame( state = c("WY", "ND", "OK", "ID", "WV", "MA", "HI", "VT", "MD", "CA"), group_color = c(rep("red",5), rep("blue",5)) ) # 合并颜色分组到长数据 pf_long <- merge(pf_long, color_groups, by = "state")
步骤2:提取折线末尾的标签数据
我们只需要每个州最后一条日期记录的接种量来放置标签:
# 提取每个州的最后一行数据(即时间序列的末尾) label_data <- pf_long %>% group_by(state) %>% filter(newDate == max(newDate)) %>% ungroup()
步骤3:绘制带标签的时间序列
现在用长格式数据绘图,只需一次geom_line即可画出所有折线,再用geom_text添加末尾标签:
NewPlot <- ggplot(pf_long, aes(x = newDate, y = doses, color = group_color)) + geom_line(linewidth = 1) + # 统一绘制所有折线,颜色自动匹配分组 # 添加末尾标签:用label_data作为数据源,映射州名到标签文本 geom_text(data = label_data, aes(label = state), hjust = -0.1, # 标签放在折线右侧,避免和线条重叠 vjust = 0.5, show.legend = FALSE) + # 不让标签显示在图例里 # 设置颜色(和你原来的红蓝对应) scale_color_identity(guide = "legend", labels = c("Blue Group", "Red Group")) + labs(title = "Time Series for Total Number of COVID-19 Doses Administered (per 100k) vs. U.S States", x = "Date (Time-Series)", y = "Total Number of COVID-19 Doses Administered (per 100k)", color = "State Groups") + theme(plot.title = element_text(hjust=0.5)) + # 调整x轴范围,给标签预留显示空间(10为日期单位,可根据你的数据调整) xlim(range(pf$newDate)[1], range(pf$newDate)[2] + 10)
关键说明
- 转长格式是解决
fortify错误的核心:宽格式下每个geom_line对应单独列,而geom_text需要统一的数据源,长格式让所有折线和标签共享同一数据结构。 - 如果标签出现重叠,可以用
ggrepel包的geom_text_repel替代geom_text,它会自动调整标签位置避免重叠。
内容的提问来源于stack exchange,提问作者Khoa Dang
相关产品推荐
相关产品推荐

