开发者

Add vertical lines to ggplot2 bar plot

开发者 https://www.devze.com 2023-02-19 11:45 出处:网络
I am doing some research on non-defaulters and defaulters with regards to banking. In that context I am plotting their distributions relative to some score in a bar plot. The higher the score, the bet

I am doing some research on non-defaulters and defaulters with regards to banking. In that context I am plotting their distributions relative to some score in a bar plot. The higher the score, the better the credit rating.

Since the number of defaults is very limited compared to the number of non-defaults plotting the defaults and non-defaults on the same bar plot is not very giving as you hardly can see the defaults. I then make a second bar plot based on the defaulters' scores only, but on the same interval scale as the full bar plot of both the scores of the defaulters and non-defaulters. I would then like to add vertical lines to the first bar plot indicating where the highest defaulter score is located and the lowest defaulter score is located. That is to get a view of where the distribution of the defaulters fit into that of the overall distribution of both defaulters and non-defaulters.

Below is the code I am using replaced with (seeded) random data instead.

library(ggplot2)

#NDS represents non-defaults and DS defaults on the same scale
#although here being just some random normals for the sake of simplicity.
set.seed(10)
NDS<-rnorm(10000,sd=1)-2
DS<-rnorm(100,sd=2)-5

#Cutoffs are const开发者_如何学Cructed such that intervals of size 0.3 
#contain all values of NDS & DS
minCutoff<--9.3
maxCutoff<-2.1

#Generate the actual interval "bins"
NDS_CUT<-cut(NDS,breaks=seq(minCutoff, maxCutoff, by = 0.3))
DS_CUT<-cut(DS,breaks=seq(minCutoff, maxCutoff, by = 0.3))

#Manually generate where to put the vertical lines for min(DS) and max(DS)
minDS_bar<-levels(cut(NDS,breaks=seq(minCutoff, maxCutoff, by = 0.3)))[1]
maxDS_bar<-levels(cut(NDS,breaks=seq(minCutoff, maxCutoff, by = 0.3)))[32]

#Generate data frame - seems stupid, but makes sense
#when the "real" data is used :-)
NDSdataframe<-cbind(as.data.frame(NDS_CUT),rep(factor("State-1"),length(NDS_CUT)))
colnames(NDSdataframe)<-c("Score","Action")
DSdataframe<-cbind(as.data.frame(DS_CUT),rep(factor("State-2"),length(DS_CUT)))
colnames(DSdataframe)<-c("Score","Action")
fulldataframe<-rbind(NDSdataframe,DSdataframe)
attach(fulldataframe)

#Plot the full distribution of NDS & DS
# with geom_vline(xintercept = minDS_bar) + geom_vline(xintercept = maxDS_bar)
# that unfortunately does not show :-(
fullplot<-ggplot(fulldataframe, aes(Score, fill=factor(Action,levels=c("State-2","State-1")))) +     geom_bar(position="stack") + opts(axis.text.x = theme_text(angle = 45))  + opts    (legend.position = "none")    + xlab("Scoreinterval") + ylab("Antal pr. interval") + geom_vline(xintercept = minDS_bar) + geom_vline(xintercept = maxDS_bar) 

#Generate dataframe for DS only
#It might seem stupid, but again makes sense
#when using the original data :-)
DSdataframe2<-cbind(as.data.frame(DS_CUT),rep(factor("State-2"),length(DS_CUT)))
colnames(DSdataframe2)<-c("theScore","theAction")

#Calucate max number of observations to adjust bar plot of DS only
myMax<-max(table(DSdataframe2))+1
attach(DSdataframe2)

#Generate bar plot of DS only
subplot<-ggplot(fulldataframe, aes(theScore, fill=factor(theAction))) + geom_bar        (position="stack") + opts(axis.text.x = theme_text(angle = 45))  + opts(legend.position = "none") +     ylim(0, myMax) + xlab("Scoreinterval") + ylab("Antal pr. interval")

#plot on a grid
grid.newpage()
pushViewport(viewport(layout = grid.layout(2, 1)))
vplayout <- function(x, y)
viewport(layout.pos.row = x, layout.pos.col = y)
print(fullplot, vp = vplayout(1, 1))
print(subplot, vp = vplayout(2, 1))

#detach dataframes
detach(DSdataframe2)
detach(fulldataframe)

Furthermore, if anybody has an idea of how I can align the to plot so that correct intervals are just below/above each other on the grid plot

Hope somebody is able to help!

Thanks in advance,

Christian


Wrap aes around the xintercept in the geom_vline layer:

... + geom_vline(aes(xintercept = minDS_bar)) + geom_vline(aes(xintercept = maxDS_bar)) 


Question 1:

Since you provide the vertical lines as data, you have to map the aesthetics first, using aes()

fullplot <-ggplot(
        fulldataframe, 
        aes(Score, fill=factor(Action,levels=c("State-2","State-1")))) +     
        geom_bar(position="stack") + 
        opts(axis.text.x = theme_text(angle = 45))  + 
        opts    (legend.position = "none")    + 
        xlab("Scoreinterval") + 
        ylab("Antal pr. interval") + 
        geom_vline(aes(xintercept = minDS_bar)) + 
        geom_vline(aes(xintercept = maxDS_bar)) 

Second question:

To align the plots, you can use the align.plots() function in package ggExtra

install.packages("dichromat")
install.packages("ggExtra", repos="http://R-Forge.R-project.org")
library(ggExtra)

ggExtra::align.plots(fullplot, subplot)

Add vertical lines to ggplot2 bar plot

0

精彩评论

暂无评论...
验证码 换一张
取 消