为何同一数据集在R基础绘图中连线混乱,ggplot却正常?
问题:R基础plot函数为何会连接不同分组的点?
我用R基础包的plot函数绘制折线图时,花了数小时排查数据问题,直到改用ggplot绘图才得到预期结果。现在想搞清楚,为什么基础plot函数会把不同分组的点连接起来。
简化可复现数据集
DF3 = read.table( text=" .session_id dayhour average 1 4319703577 0 47.43 2 4319703577 1 48.00 3 4319703577 2 48.52 4 4319703577 3 48.78 5 4319703577 4 48.13 6 4319703577 5 47.52 7 4319703577 6 44.40 8 4319703577 7 29.70 9 4319703577 8 6.70 10 4319703577 9 2.28 11 4319703577 10 1.07 12 4319703577 11 0.02 13 4319703577 15 0.57 14 4319703577 16 1.45 15 4319703577 17 0.68 16 4319703577 22 9.70 17 4319703577 23 39.67 18 5577150313 0 51.48 19 5577150313 1 52.60 20 5577150313 2 52.88 21 5577150313 3 52.10 22 5577150313 4 50.72 23 5577150313 5 33.45 24 5577150313 6 7.70 25 5577150313 7 1.92 26 5577150313 8 0.58 27 5577150313 10 0.50 28 5577150313 11 1.00 29 5577150313 12 1.93 30 5577150313 13 3.80 31 5577150313 14 2.33 32 5577150313 15 2.83 33 5577150313 16 3.00 34 5577150313 17 2.38 35 5577150313 18 2.00 36 5577150313 19 2.00 37 5577150313 20 3.50 38 5577150313 21 13.68 39 5577150313 22 37.38 40 5577150313 23 51.23", )
可复现绘图代码
### ggplot绘制(预期结果) DF3 %>% arrange( .session_id, dayhour ) %>% ggplot( aes( dayhour, average, col=.session_id ) ) + geom_line()+ geom_vline( xintercept = 20.5, linetype=2 ) + geom_vline( xintercept = 10.5, linetype=2 ) ### 基础plot绘制(问题结果) DF3 %>% arrange( .session_id, dayhour ) %T>% {a <<- .} %>% with( plot( a$dayhour, a$average, col=.session_id, type = "b" ) ) abline( v = 20.5, lty=2 ) abline( v = 10.5, lty=2 )
注:原代码中with()里的a$dayhour存在逻辑问题,这里临时用%T>% {a <<- .}修正,确保能运行。
绘图结果对比
- ggplot结果:两条独立折线,分别对应
.session_id的两个分组,线条颜色区分清晰,无跨分组连接。 - 基础plot结果:所有点按数据框的行顺序依次连接,即使颜色区分了分组,不同分组的点仍然被连成了一条混乱的折线。
补充:更简单的复现例子
# 加载内置数据集 data <- ggplot2::economics_long # 美国经济时间序列 ### ggplot绘制 data %>% group_by( variable, wday = lubridate::wday( date ) ) %>% summarize( value = round(sum(value), 2) ) %>% ggplot( aes( wday, value, col=variable ) ) + geom_line() ### 基础plot绘制 data %>% group_by( variable, wday = lubridate::wday( date ) ) %>% summarize( value = round(sum(value), 2) ) %>% with( plot( wday, value, col=factor(variable), type = "b" ) )
补充结果对比
- ggplot结果:每个
variable对应一条独立折线,分组清晰。 - 基础plot结果:所有点按行顺序连接,跨
variable分组形成杂乱线条。
原因解析与解决方法
核心原因
基础plot和ggplot的设计逻辑完全不同:
- ggplot是声明式绘图:当你在
aes()中指定col=分组变量时,ggplot会自动将数据按该变量分组,为每个分组单独绘制折线,无需额外操作。 - 基础plot是命令式绘图:
plot(..., type="b")仅会按照输入的x、y向量的原始顺序依次连接点。哪怕你用col=分组变量给点/线上色,它也不会自动识别分组,只会把所有点按顺序连起来。
基础plot的修正方法
要在基础plot中实现分组折线,需要手动拆分分组:
方法1:循环分组,用lines()添加线条
# 先整理数据 DF3_arranged <- DF3 %>% arrange(.session_id, dayhour) # 获取分组列表 session_groups <- unique(DF3_arranged$.session_id) # 绘制第一个分组 with(subset(DF3_arranged, .session_id == session_groups[1]), plot(dayhour, average, col=.session_id, type="b", ylim=range(DF3_arranged$average), xlab="dayhour", ylab="average")) # 依次添加其他分组的线条 for (s in session_groups[-1]) { with(subset(DF3_arranged, .session_id == s), lines(dayhour, average, col=s, type="b")) } # 添加辅助线 abline(v=20.5, lty=2) abline(v=10.5, lty=2)
方法2:转宽格式后用matplot绘制
library(tidyr) # 将长格式转为宽格式 DF3_wide <- DF3 %>% arrange(.session_id, dayhour) %>% pivot_wider(names_from = .session_id, values_from = average) # 用matplot绘制多组折线 matplot(DF3_wide$dayhour, DF3_wide[,-1], type="b", col=1:length(session_groups), pch=1, xlab="dayhour", ylab="average")
内容的提问来源于stack exchange,提问作者DiegoJArg
相关产品推荐
相关产品推荐

