简体   繁体   中英

R: Stacked area chart with line and secondary axis

My goal is to produce a stacked area chart with a secondary axis referring to the case number of the data points represented in the area chart as a line.

This is the data frame:

df_prep <- data.frame(year = rep(1990:2017, 2), 
n = rep(c(427, 428, 448, 504, 499, 500, 654, 786, 875, 862, 875, 835, 787, 781, 784, 800, 796, 793, 790, 760, 731, 711, 677, 607, 568, 537, 485, 475), 2), 
values = c(0.04498506, 0.04710173, 0.04807318, 0.04995567, 0.04130670, 0.05112505, 0.04881195, 0.04836573, 0.05010657, 0.04147296, 0.04196852, 0.04856052, 0.05232518, 0.05043970, 0.04506930, 0.03781005, 0.03477578, 0.03190302, 0.03957772, 0.03223425, 0.03292258, 0.03507017, 0.03270658, 0.03248077, 0.02896229, 0.03023061, 0.03281597, 0.03035403, 0.05607519, 0.06112640, 0.06138485, 0.06867888, 0.06051572, 0.06281798, 0.06956896, 0.05799622, 0.05921514, 0.04770948, 0.03884279, 0.05292109, 0.06081987, 0.07052489, 0.05634209, 0.05422748, 0.05292595, 0.07114513, 0.07859847, 0.07719619, 0.08114787, 0.07771912, 0.08199433, 0.08366473, 0.10369285, 0.11383821, 0.11015112, 0.10004794),
type = c(rep("st.debt", 28), rep("lt.debt", 28)))

For further preparation I calculated a normalizing ratio between the variables n and values :

normalizer <- sum(aggregate(values ~ type, data = df_prep, max)$values / max(df_prep$n))

My current graph is this:

在此处输入图像描述

library(ggplot2)
ggplot() +
geom_area(data = df_prep, aes(y = values, x = year, fill = type)) + 
geom_line(data = df_prep[1:28, ], aes(y = (n * normalizer), x = year)) + 
scale_fill_manual(values = c("grey50", "black")) 

Crucially, however, the final graph should include:

  • Two y axes: the first (left) representing the values variable, the second (right) the n variable;
  • a legend showing all three variables shown in the graph.

I have looked up several similar questions but was unable to adapt the respective answers to my problem. Thank you very much for your help.

Edit:

Thanks to amrrs' answer, I was able to adapt the code. However, the two axes were now out of line with each other so I first had to change the normalizer manually:

normalizer <- 0.2 / 1000

Afterwards, I could refine the graph:

在此处输入图像描述

ggplot() +
geom_area(data = df_prep, aes(y = values, x = year, fill = type)) + 
geom_line(data = df_prep[1:28, ], aes(y = (n * normalizer), x = year, linetype = "n")) + 
scale_fill_manual(values = c("grey50", "black"))  +
scale_y_continuous(name = "% total assets", limits = c(0, 0.2), breaks = seq(0, 0.2, 0.05), labels = seq(0, 20, 5), sec.axis = sec_axis(name =  "n", ~. / normalizer, breaks = seq(0, 1000, 250), labels = seq(0, 1000, 250))) + 
scale_x_continuous(name = "year", breaks = seq(1990, 2017, 3)) +
ggtitle("DEU") + 
theme(plot.title = element_text(hjust = 0.5))

Not sure if exactly solves the entire problem. My answer is based on this documentation and partly this answer

df_prep <- data.frame(year = rep(1990:2017, 2), 
                      n = rep(c(427, 428, 448, 504, 499, 500, 654, 786, 875, 862, 875, 835, 787, 781, 784, 800, 796, 793, 790, 760, 731, 711, 677, 607, 568, 537, 485, 475), 2), 
                      values = c(0.04498506, 0.04710173, 0.04807318, 0.04995567, 0.04130670, 0.05112505, 0.04881195, 0.04836573, 0.05010657, 0.04147296, 0.04196852, 0.04856052, 0.05232518, 0.05043970, 0.04506930, 0.03781005, 0.03477578, 0.03190302, 0.03957772, 0.03223425, 0.03292258, 0.03507017, 0.03270658, 0.03248077, 0.02896229, 0.03023061, 0.03281597, 0.03035403, 0.05607519, 0.06112640, 0.06138485, 0.06867888, 0.06051572, 0.06281798, 0.06956896, 0.05799622, 0.05921514, 0.04770948, 0.03884279, 0.05292109, 0.06081987, 0.07052489, 0.05634209, 0.05422748, 0.05292595, 0.07114513, 0.07859847, 0.07719619, 0.08114787, 0.07771912, 0.08199433, 0.08366473, 0.10369285, 0.11383821, 0.11015112, 0.10004794),
                      type = c(rep("st.debt", 28), rep("lt.debt", 28)))

normalizer <- sum(aggregate(values ~ type, data = df_prep, max)$values / max(df_prep$n))


library(ggplot2)
ggplot() +
  geom_area(data = df_prep, aes(y = values, x = year, fill = type)) + 
  geom_line(data = df_prep[1:28, ], aes(y = (n * normalizer), x = year, linetype = "n")) + 
  scale_fill_manual(values = c("grey50", "black"))  +
  scale_y_continuous(sec.axis = sec_axis(name =  "n", ~.))

Created on 2019-03-17 by the reprex package (v0.2.1)

I used the following script to plot the primary axis with both geom_line and geom_point and to plot the secondary axis with geom_area :

t=read.table(sep="\t","https://pastebin.com/raw/wwXz3AaJ",na.strings="x")
t=t[!t$V4=="Ever vaccinated",]

d=as.Date(paste(t$V2,t$V3,1),format="%Y %B %d")

sums=tapply(t$V6,d,sum)
max=max(t$V7,na.rm=T)*t$V6/sums[sapply(d,toString)]

group=factor(t$V4,levels=unique(t$V4))

pal=hcl(c(210,110,110,60,60,60,0,0)+15,c(90,90,70,90,70,60,90,70),c(60,60,75,60,75,90,60,75))
pal=hcl(c(210,110,110,60,60,60,0,0)+15,c(rep(80,8),0),c(80,80,60,80,60,40,80,60,0))

ggplot(t,aes(x=!!d,y=V7,color=!!group))+
geom_area(aes(x=!!d,y=!!max,fill=!!group,color=!!group),size=.1,show.legend=F,alpha=.3)+
geom_line(size=.5)+
geom_point(size=1)+
scale_x_date(breaks=unique(d),expand=expansion(mult=c(.005,.005)),date_labels="%b")+
scale_y_continuous(breaks=seq(0,10000,1000),expand=expansion(mult=c(.005,.005)),sec.axis=sec_axis(trans=~.*100/max(t$V7,na.rm=T),name="Percentage of group"))+
labs(y="Age-standardized mortality rate per 100,000 person-years")+
ggtitle("Age-standardized all-cause mortality in England from January 1 2021 to May 31 2022",subtitle="Data from https://www.ons.gov.uk/peoplepopulationandcommunity/birthsdeathsandmarriages/\ndeaths/bulletins/deathsinvolvingcovid19byvaccinationstatusengland/latest")+
scale_color_manual(values=pal)+
scale_fill_manual(values=pal)+
guides(color=guide_legend(ncol=2))+
theme(
  axis.text=element_text(size=6,color="black"),
  axis.ticks=element_blank(),
  axis.ticks.length=unit(0,"cm"),
  axis.title=element_text(size=8),
  axis.title.x=element_blank(),
  legend.background=element_blank(),
  legend.box.just="center",
  legend.box.margin=margin(0,unit="cm"),
  legend.box.spacing=unit(0,"in"),
  legend.direction="vertical",
  legend.justification="center",
  legend.key=element_rect(fill="white"),
  legend.margin=margin(-5,0,0,0),
  legend.position="bottom",
  legend.text=element_text(size=7,vjust=.5),
  legend.title=element_blank(),
  panel.background=element_rect(fill="white"),
  panel.grid=element_blank(),
  plot.background=element_rect(fill="white"),
  plot.subtitle=element_text(size=6),
  plot.title=element_text(size=10)
)

ggsave("1.png",width=6,height=5)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM