Plot line on top of stacked bar chart in ggplot2 - r

I have created a stacked bar chart, and I would now like to plot a line on the same graphic, but I can't figure it out. I've added the geom_line() to the ggplot call, but I only end up with the line, not the bar chart.
library(ggplot2)
library(reshape)
# First let's make a toy dataset for our stacked plot/line plot example.
year = c(1,2,3,4,5,6)
stocks = c(2,4,3,2,4,3)
exports = stocks*2
domestic = stocks*3
production = c(15,16,15,16,15,16)
# Make 2 df's: alldata is for stacked bar chart, linedata is for plotting a line on top of it.
alldata = data.frame(year,stocks,exports,domestic)
linedata = data.frame(year,production)
# Make alldata 'long' for the stacking
melteddata = melt(alldata,id.vars="year")
# This works fine: (but hooboy was tricky to figure out the ordering w/ stat="identity" )
plotS1 <- ggplot(melteddata, aes(x=year,y=value,factor=variable,fill=variable,order=-as.numeric(variable)))
plotS1 + geom_bar(stat="identity")
# This plots only the line, not the stacked bar chart :
plotS1 <- ggplot(melteddata)
plotS1 + geom_bar(aes(x=year,y=value,factor=variable,fill=variable,order=-as.numeric(variable)), stat="identity")
plotS1 + geom_line(data=linedata, aes(x=year,y=production))

You were close:
plotS1 <- ggplot(melteddata)
plotS1 + geom_bar(aes(x=year,y=value,factor=variable,fill=variable,
order=-as.numeric(variable)), stat="identity") +
geom_line(data=linedata, aes(x=year,y=production))

Related

How do I make grouped boxplots work in plotly?

I'd like to make a grouped boxplot in plotly in R, but it simply doesn't show up
I'm taking a boxplot that works in ggplot and trying to translate it to r
This is my code
library(fpp)
library(tidyverse)
library(plotly)
library(Hmisc)
gg <-
credit %>%
ggplot(aes(score,
group = cut2(savings, g = 4),
fill = cut2(savings, g = 4))) +
geom_boxplot() +
coord_flip()
ggplotly(gg)
It shows up really nicely in ggplot and then doesn't show at all in plotly

Line plot with bars in secondary axis with different scales in ggplot2

I'm trying to plot a line graph (data points between 0 and 2.5, with interval of 0.5). I want to plot some bars in the same chart on the right-hand axis (between 0 and 60 with interval of 10). I am making some mistake in my code such that the bars get plotted in the left hand axis.
Here's some sample data and code:
Month <- c("J","F","M","A")
Line <- c(2.5,2,0.5,3.4)
Bar <- c(30,33,21,40)
df <- data.frame(Month,Line,Bar)
ggplot(df, aes(x=Month)) +
geom_line(aes(y = Line,group = 1)) +
geom_col(aes(y=Bar))+
scale_y_continuous("Line",
sec.axis = sec_axis(trans= ~. /50, name = "Bar"))
Here's the output
Thanks in advance.
Try this approach with scaling factor. It is better if you work with a scaling factor between your variables and then you use it for the second y-axis. I have made slight changes to your code:
library(tidyverse)
#Data
Month <- c("J","F","M","A")
Line <- c(2.5,2,0.5,3.4)
Bar <- c(30,33,21,40)
df <- data.frame(Month,Line,Bar)
#Scale factor
sfactor <- max(df$Line)/max(df$Bar)
#Plot
ggplot(df, aes(x=Month)) +
geom_line(aes(y = Line,group = 1)) +
geom_col(aes(y=Bar*sfactor))+
scale_y_continuous("Line",
sec.axis = sec_axis(trans= ~. /sfactor, name = "Bar"))
Output:

ggplot only printing gray boxes to file

So SO nailed getting my graph to work, but now i can't get it to print! The end goal is that i need to automate the updating of these plots, so the ggplot and print calls need to be in a function. When i run this code, each file just contains a gray square.
toyfn <- function(plotdata){
library(ggplot2)
plotS1 <- ggplot(plotdata)
plotS1 + geom_bar(aes(x=year,y=value,factor=variable,fill=variable,
order=-as.numeric(variable)), stat="identity") +
geom_line(data=linedata, aes(x=year,y=production))
ggsave('testprint.png',plotS1)
png(filename='testprint2.png')
print(plotS1)
dev.off()
}
library(ggplot2)
library(reshape)
# First let's make a toy dataset for our stacked plot/line plot example.
year = c(1,2,3,4,5,6)
stocks = c(2,4,3,2,4,3)
exports = stocks*2
domestic = stocks*3
production = c(15,16,15,16,15,16)
# Make 2 df's: alldata is for stacked bar chart, linedata is for plotting a line on top of it.
alldata = data.frame(year,stocks,exports,domestic)
linedata = data.frame(year,production)
# Make alldata 'long' for the stacking
melteddata = melt(alldata,id.vars="year")
toyfn(melteddata)
You are saving a plot with no geoms. The plot with geoms will display on the screen, but not in the file.
Try this:
toyfn <- function(plotdata){
plotS1 <- ggplot(plotdata, aes(year, value, factor = variable, fill = variable)) +
geom_bar(stat="identity", aes(order = -as.numeric(variable))) +
geom_line(data=linedata, aes(x=year,y=production))
ggsave('testprint.png', plot = plotS1)
}

Adjusting the width of legend for continuous variable

I have a script below to illustrate my question:
temp.df <- data.frame(x=1:100,y=1:100,z=1:100,stringsAsFactors=FALSE)
chart <- ggplot(data=temp.df,aes(x=x,y=y))
chart <- chart + geom_line(aes(colour=z))
chart <- chart + scale_colour_continuous(low="blue",high="red")
chart <- chart + theme(legend.position="bottom")
# so far so good, but I think the legend positioned at bottom with such a small size is a waste of space, so I want to "widen" it using the line below...
chart <- chart + guides(colour=guide_legend(keywidth=5,label.position="bottom"))
# oops, it changed to legend for categorical variable
How can I widen the "continuous variable" legend positioned at bottom?
Instead of function guides() you should use the function theme() and set the legend.key.width=
temp.df <- data.frame(x=1:100,y=1:100,z=1:100,stringsAsFactors=FALSE)
chart <- ggplot(data=temp.df,aes(x=x,y=y))
chart <- chart + geom_line(aes(colour=z))
chart <- chart + scale_colour_continuous(low="blue",high="red")
chart <- chart + theme(legend.position="bottom")
chart <- chart + theme(legend.key.width=unit(3,"cm"))
You can use guide_colourbar instead of guide_legend in your code :
temp.df <- data.frame(x=1:100,y=1:100,z=1:100,stringsAsFactors=FALSE)
chart <- ggplot(data=temp.df,aes(x=x,y=y))
chart <- chart + geom_line(aes(colour=z))
chart <- chart + scale_colour_continuous(low="blue",high="red")
chart <- chart + theme(legend.position="bottom")
chart + guides(colour=guide_colourbar(barwidth=30,label.position="bottom"))

bar and line plot in one chart with a legend under ggplot2

I would like put a bar and a line plot of two separate but related series on the same chart with a legend (the bar plot is of quarterly growth the line plot is of annual growth).
I currently do it with a data.frame in wide format and code like this:
p <- ggplot() +
geom_bar(df, aes(x=Date, y=quarterly), colour='blue') +
geom_line(df, aes(x=Date, y=annual), colour='red')
but I cannot work out how to add a legend, which has a red line labeled 'Annual Growth'; and a blue square labeled 'Quarterly Growth'.
Alternatively, I cannot work out how to have differnt geoms for different series with a long-form data.frame.
UPDATE:
The following example code gets me part of the way towards a solution, but with a really ugly duplicate legend. Still looking for a complete solution ... This approach is based on putting the data in long form and then plotting subsets of the data ...
library(ggplot2)
library(reshape)
library(plyr)
library(scales)
### --- make a fake data set
x <- rep(as.Date('2012-01-01'), 24) + (1:24)*30
ybar <- 1:24
yline <- ybar + 1
df <- data.frame(x=x, ybar=ybar, yline=yline)
molten <- melt(df, id.vars='x', measure.vars=c('ybar', 'yline'))
molten$line <- ifelse(molten$variable=='yline', TRUE, FALSE)
molten$bar <- ifelse(molten$variable=='ybar', TRUE, FALSE)
### --- subset the data set
df.line <- subset(molten, line==TRUE)
df.bar <- subset(molten, bar==TRUE)
### --- plot it
p <- ggplot() +
geom_bar(data=df.bar, mapping=aes(x=x, y=value, fill=variable, colour=variable),
stat='identity', position='dodge') +
geom_line(data=df.line, mapping=aes(x=x, y=value, colour=variable)) +
opts(title="Test Plot", legend.position="right")
ggsave(p, width=5, height=3, filename='plot.png', dpi=150)
And an example plot ...
By use of the subset argument to geoms.
> x=1:10;df=data.frame(x=x,y=x+1,z=x+2)
> ggplot(melt(df),
aes(x,value,color=variable,fill=variable))+
geom_bar(subset=.(variable=="y"),stat="identity")+
geom_line(subset=.(variable=="z"))

Resources