3

I am going to use a dataset and plot that came from a previous problem (Here):

dat <- read.table(text = "   Division Year OperatingIncome
1  A  2012           11460
2  B  2012            7431
3  C  2012           -8121
4  D  2012           15719
5  E  2012             364
6  A  2011           12211
7  B  2011            6290
8  C  2011           -2657
9  D  2011           14657
10 E  2011            1257
11 A  2010           12895
12 B  2010            5381
13 C  2010           -2408
14 D  2010           11849
15 E  2010             517",header = TRUE,sep = "",row.names = 1)

dat1 <- subset(dat,OperatingIncome >= 0)
dat2 <- subset(dat,OperatingIncome < 0)
ggplot() + 
    geom_bar(data = dat1, aes(x=Year, y=OperatingIncome, fill=Division),stat = "identity") +
    geom_bar(data = dat2, aes(x=Year, y=OperatingIncome, fill=Division),stat = "identity") +
    scale_fill_brewer(type = "seq", palette = 1)

It includes the following plot, which is where my question comes in:

Plot of interest

My question: Is it possible for me to change the y-axis label to two different labels on the same side? One would say "Negative Income" and be on the bottom portion of the y-axis. The other would say "Positive Income" and be on the upper portion of the SAME y-axis.

I have seen this question asked in terms of dual y-axis for different scales (on opposite sides), but I specifically want this on the same y-axis. Appreciate any help - I also would prefer to use ggplot2 for this problem, if possible.

Community
  • 1
  • 1
EntryLevelR
  • 273
  • 4
  • 16
  • so you want to add text in two places on the y-axis? – rawr Nov 14 '16 at 22:18
  • Yes (but I would also like control over where each of the y-axis titles begins). – EntryLevelR Nov 14 '16 at 22:21
  • 1
    I guess to add to this, I want to have each title on the y-axis be independent of the other. For example, perhaps I make one blue and one red. – EntryLevelR Nov 14 '16 at 22:22
  • I don't think there's a way to do this within `ggplot2`, but you could use `cowplot`'s [generic plot annotations](https://cran.r-project.org/web/packages/cowplot/vignettes/introduction.html). – Gregor Thomas Nov 14 '16 at 23:03

1 Answers1

5

You can use annotate to add labels for negative and positive income. To add text outside the plot panel, you'll need to turn off clipping. Below are examples of adding text both inside and outside the plot panel:

# Plot
p = ggplot() + 
  geom_bar(data = dat1, aes(x=Year, y=OperatingIncome, fill=Division),stat = "identity") +
  geom_bar(data = dat2, aes(x=Year, y=OperatingIncome, fill=Division),stat = "identity") +
  scale_fill_brewer(type = "seq", palette = 1) +
  geom_hline(yintercept=0, lwd=0.3, colour="grey20") +
  scale_x_continuous(breaks=sort(unique(dat$Year))) +
  theme_bw()

# Annotate inside plot area
p +  coord_cartesian(xlim=range(dat$Year) + c(-0.45,0.4)) + 
  annotate(min(dat$Year) - 0.53 , y=c(-5000,5000), label=c("Negative Income","Positive Income"), 
           geom="text", angle=90, hjust=0.5, size=3, colour=c("red","blue"))

enter image description here

# Annotate outside plot area by turning off clipping
pp = p + coord_cartesian(xlim=range(dat$Year) + c(-0.4,0.4)) + 
  annotate(min(dat$Year) - 0.9, y=c(-6000,10000), label=c("Negative Income","Positive Income"), 
           geom="text", angle=90, hjust=0.5, size=4, colour=c("red","blue")) +
  labs(y="")

pp <- ggplot_gtable(ggplot_build(pp))
pp$layout$clip <- "off"
grid.draw(pp)

enter image description here

You can also use cowplot as suggested by @Gregor. I haven't tried this before, so maybe there's a better approach than what I've done below, but it looks like you have to use viewport coordinates, rather than data coordinates, to place the annotations.

# Use cowplot
library(cowplot)

ggdraw() +
  draw_plot(p + labs(y=""), 0,0,1,1) +
  draw_label("Positive Income", x=0.01, y = 0.5, col="blue", size = 10, angle=90) +
  draw_label("Negative Income", x=0.01, y = 0.15, col="red", size = 10, angle=90) 

enter image description here

I realize the data in the question is just for illustration, but for data like this, a line plot might prove easier to understand:

library(dplyr)

ggplot(dat, aes(x=Year, y=OperatingIncome, color=Division)) + 
  geom_hline(yintercept=0, lwd=0.3, colour="grey50") +
  geom_line(position=position_dodge(0.2), alpha=0.5) +
  geom_text(aes(label=Division), position=position_dodge(0.2), show.legend=FALSE) +
  scale_x_continuous(breaks=sort(unique(dat$Year))) +
  theme_bw() +
  guides(colour=FALSE) +
  geom_line(data=dat %>% group_by(Year) %>% summarise(Net=sum(OperatingIncome), Division=NA),
            aes(x=Year, y=Net), alpha=0.4) +
  geom_text(data=dat %>% group_by(Year) %>% summarise(Net=sum(OperatingIncome), Division=NA),
            aes(x=Year, y=Net, label="Net"), colour="black") 

enter image description here

Or, if a bar plot is required, maybe something like this:

ggplot() + 
  geom_bar(data = dat %>% arrange(OperatingIncome) %>% 
             mutate(Division=factor(Division,levels=unique(Division))), 
           aes(x=Year, y=OperatingIncome, fill=Division), 
           stat="identity", position="dodge") +
  geom_hline(yintercept=0, lwd=0.3, colour="grey20") +
  theme_bw()

enter image description here

eipi10
  • 91,525
  • 24
  • 209
  • 285