我正在尝试制作一个条形图,结合功能区/面积图,该图说明每个站的BRT / MRT线路的登机/下车乘客,以及沿走廊按方向划分的乘客量。
初始数据帧如下所示:
df <- data.frame(
mode=c("mrt","mrt","mrt","mrt","mrt","mrt","mrt","mrt","mrt","mrt",
"brt","brt","brt","brt","brt","brt","brt","brt","brt","brt"),
direction=c("Northbound","Northbound","Northbound","Northbound","Northbound",
"Southbound","Southbound","Southbound","Southbound","Southbound",
"Northbound","Northbound","Northbound","Northbound","Northbound",
"Southbound","Southbound","Southbound","Southbound","Southbound"),
station=c("a","b","c","d","e","e","d","c","b","a","a","b","c","d","e","e","d","c","b","a"),
on=c(40,30,20,10,0,40,30,20,10,0,20,15,10,5,0,20,15,10,5,0),
off=c(0,10,20,30,40,0,10,20,30,40,0,5,10,15,20,0,5,10,15,20),
volume=c(40,60,60,40,0,40,60,60,40,0,20,30,30,20,0,20,30,30,20,0))
初始数据帧被转换为ggplot2
的长格式。
library(tidyverse)
df2 <- df %>% gather(key=key,value=trip,on,off) %>% mutate(
station=factor(station,levels=c("a","b","c","d","e"),labels=c("a","b","c","d","e")),
key=factor(key,levels=c("on","off"),labels=c("on","off")),
direction=factor(direction,levels=c("Northbound","Southbound"),
labels=c("Northbound","Southbound")),
mode=factor(mode,levels=c("mrt","brt"),labels=c("mrt","brt")))
打印的df2
如下:
> df2
mode direction station volume key trip
1 mrt Northbound a 40 on 40
2 mrt Northbound b 60 on 30
3 mrt Northbound c 60 on 20
4 mrt Northbound d 40 on 10
5 mrt Northbound e 0 on 0
6 mrt Southbound e 40 on 40
7 mrt Southbound d 60 on 30
8 mrt Southbound c 60 on 20
9 mrt Southbound b 40 on 10
10 mrt Southbound a 0 on 0
11 brt Northbound a 20 on 20
12 brt Northbound b 30 on 15
13 brt Northbound c 30 on 10
14 brt Northbound d 20 on 5
15 brt Northbound e 0 on 0
16 brt Southbound e 20 on 20
17 brt Southbound d 30 on 15
18 brt Southbound c 30 on 10
19 brt Southbound b 20 on 5
20 brt Southbound a 0 on 0
21 mrt Northbound a 40 off 0
22 mrt Northbound b 60 off 10
23 mrt Northbound c 60 off 20
24 mrt Northbound d 40 off 30
25 mrt Northbound e 0 off 40
26 mrt Southbound e 40 off 0
27 mrt Southbound d 60 off 10
28 mrt Southbound c 60 off 20
29 mrt Southbound b 40 off 30
30 mrt Southbound a 0 off 40
31 brt Northbound a 20 off 0
32 brt Northbound b 30 off 5
33 brt Northbound c 30 off 10
34 brt Northbound d 20 off 15
35 brt Northbound e 0 off 20
36 brt Southbound e 20 off 0
37 brt Southbound d 30 off 5
38 brt Southbound c 30 off 10
39 brt Southbound b 20 off 15
40 brt Southbound a 0 off 20
我想达到两种输出类型:
目前,我可以通过以下脚本制作下图:
ggplot(df2,aes(x=station)) +
geom_bar(aes(y=trip,fill=interaction(mode,key)),stat="identity",
position=position_dodge(preserve="single"),width=0.8) +
geom_ribbon(aes(ymin=0,ymax=volume,group=interaction(mode,key),fill=mode),alpha=0.2) +
facet_wrap(~direction,nrow=2)
问题是:
类型1:
-无法在标签为mrt
的x轴上的brt
和mode
之间留空格。我将澄清每种模式的区别。
-x轴上的 可以解决 interaction
函数不能提供mode
和key
的理想顺序。如第一点所述,mrt-on
,mrt-off
,brt-on
,brt-off
是标签的最佳位置。
类型2:
-无法创建分组和堆叠的条形图。
常见问题
-色带不是阶梯状 可以解决
-色带未堆叠( 可以解决 position="stack"
返回错误)
-色带使条形变得更不可见(也许可以通过 可以解决 >
alpha
进行调整,但是可以设置前后关系更好)
我不确定是否可以在ggplot2
中进行这种调整,但是我会建议您获得理想的图形。
我还测试了其他一些示例,例如geom_step
,但效果不佳。另一个问题是,如果我使用geom_area
而不是geom_ribbon
,则还会绘制存储在与volume
相关的key==off
字段中的不必要的值:
ggplot(df2,aes(x=station)) +
geom_bar(aes(y=trip,fill=interaction(mode,key)),stat="identity",
position=position_dodge(preserve="single"),width=0.8) +
geom_area(aes(y=volume,group=interaction(mode,key),fill=interaction(mode,key)),position="stack") +
facet_wrap(~direction,nrow=2)
非常感谢您提出的建议,以期获得我最近几天试图产生的理想结果。
我使用了geom_stepribbon
,它是ggplot2的扩展名:
https://cran.r-project.org/web/packages/RcmdrPlugin.KMggplot2/vignettes/geom-stepribbon.html
此外,有必要使用lag
调整南行的旅客数量,如下所述:
## Prepare df for geom_stepribbon [it requires some more packages]
df3 <- df2 %>% group_by(direction) %>%
mutate_at(vars(volume),funs(ifelse(direction=="Southbound",lag(volume),.))) %>% data.frame()
## Plot
ggplot(df3,aes(x=station)) +
geom_stepribbon(aes(ymin=0,ymax=volume,group=mode,fill=mode),alpha=0.5) +
geom_bar(aes(y=trip,fill=interaction(mode,key)),stat="identity",
position=position_dodge(preserve="single"),width=0.8) +
facet_wrap(~direction,nrow=2)
但是,我仍然遇到以下问题:
mode
之间的空格更多建议,不胜感激。
==更新版本2 ==
通过手动更改以下脚本中的因子级别,可以解决条形上剩余的问题。
ggplot(df5,aes(x=station)) +
geom_stepribbon(aes(ymin=0,ymax=volume,group=mode,fill=mode),alpha=0.5) +
geom_bar(aes(y=trip,fill=factor(interaction(mode,key),
levels=c("mrt.on","mrt.off","brt.on","brt.off"),
labels=c("MRT-Board","MRT-Alight","BRT-Board","BRT-Alight"))),
stat="identity", position=position_dodge(preserve="single"),width=0.8) +
facet_wrap(~direction,nrow=2)
MRT
和BRT
的小节之间的间隔可能有点复杂。
仍然欢迎对剩下的问题堆叠和分组的条形图提出建议。
据报道,@ Axeman不能同时进行堆叠和分组
==最终更新==
当我达到需要制作的脚本时,我将与您分享以下脚本:
但是,我仍然对scale_fill_manual
的工作方式感到困惑。 values
和breaks/labels
的顺序彼此不对应。我只是根据结果进行了手动调整,如果您能提供一些建议使代码更好,我将不胜感激。
## Set year
year <- 18
## df5 corresponds to df3 in the previous update
## Maximum passenger
max.mrt.n <- df5 %>% filter(mode=="mrt" & direction=="Northbound") %>%
summarize(max=max(volume)) %>% as.integer()
max.mrt.s <- df5 %>% filter(mode=="mrt" & direction=="Southbound") %>%
summarize(max=max(volume)) %>% as.integer()
max.brt.n <- df5 %>% filter(mode=="brt" & direction=="Northbound") %>%
summarize(max=max(volume)) %>% as.integer()
max.brt.s <- df5 %>% filter(mode=="brt" & direction=="Southbound") %>%
summarize(max=max(volume)) %>% as.integer()
max.mrt <- data.frame(direction=c("Northbound","Southbound"),label=c(max.mrt.n,max.mrt.s))
max.brt <- data.frame(direction=c("Northbound","Southbound"),label=c(max.brt.n,max.brt.s))
## Set print window
png("CorridorPax.png",height=720, width=960, res=144)
## Specify data frame and x-axis
g <- ggplot(df5,aes(x=station)) +
## Draw step ribbon chart
geom_stepribbon(aes(ymin=0,ymax=volume,
group=factor(mode,levels=c("mrt","brt"),labels=c("MRT Pax.","BRT Pax.")),
fill=factor(mode,levels=c("mrt","brt"),labels=c("MRT Pax.","BRT Pax."))),
alpha=0.4) +
## Draw bar chart
geom_bar(aes(y=trip,fill=factor(interaction(mode,key),
levels=c("mrt.on","mrt.off","brt.on","brt.off"),
labels=c("MRT-Board","MRT-Alight","BRT-Board","BRT-Alight"))),
stat="identity", position=position_dodge(preserve="single"),width=0.8) +
## Facet by direction
facet_wrap(~direction,nrow=2) +
## Appearance
## Title and xy-axis
ggtitle(paste0("Passenger volume of MRT and BRT along the corridor in 20",year)) +
xlab("Station") +
ylab("Number of Daily Passengers ('000)") +
## Theme
theme_bw() +
## Rotate label and adjust font size
theme(title=element_text(size=10),
axis.title=element_text(size=10),
axis.text.x=element_text(angle=90,hjust=1,vjust=0.25,size=10),
axis.text.y=element_text(size=8),
legend.text=element_text(size=8)
) +
## Limit and breaks of y-axis
scale_y_continuous(breaks=seq(0,60,by=5),limits=c(0,60)) +
## Legend
scale_fill_manual(name="Passenger",
values=c("cadetblue2","darkorange","gold",
"royalblue","firebrick","lawngreen"),
breaks=c("MRT Pax.","BRT Pax.","MRT-Board","MRT-Alight","BRT-Board","BRT-Alight"),
labels=c("MRT Pax.","BRT Pax.", "MRT-Board","MRT-Alight","BRT-Board","BRT-Alight")) +
## Maximum load
geom_text(mapping=aes(x=Inf,y=Inf,
label="Maximum sectional load (1,000 pax/day)",vjust=1.3,hjust=1.02),size=3) +
geom_text(data=max.mrt,mapping=aes(x=Inf,y=Inf,
label=paste0("MRT=",label)), vjust=2.6,hjust=2.4,size=3) +
geom_text(data=max.brt,mapping=aes(x=Inf,y=Inf,
label=paste0("BRT=",label)), vjust=2.6,hjust=1.2,size=3)
## Export png
print(g)
## Close printing window
dev.off()