Ggplot2 and incrementing numbers in titles of a series of plots - r

When you create a series of plots with ggplot2, how can you programmatically add a number in the plot title to show which plot it is in the series? The examples below have Plot 1, Plot 2 and Plot 3 hard coded in the title; how can ggplot put in 1, 2, 3, etc.? The plots will be inserted in a document at different places.
df <- data.frame(var1 = seq(1:10), var2 = seq(3:12))
p1 <- ggplot(df, aes(x = var1, y = var2)) + geom_point() + ggtitle("Plot 1")
p2 <- ggplot(df, aes(x = var1, y = var2)) + geom_point() + ggtitle("Plot 2")
p3 <- ggplot(df, aes(x = var1, y = var2)) + geom_point() + ggtitle("Plot 3")
http://cran.r-project.org/doc/FAQ/R-FAQ.html#How-can-I-substitute-into-a-plot-label_003f addresses variables and expressions but I need some kind of incremental counter.
How to add a title to a ggplot when the title is a variable name? doesn't seem to help
Is something like the following possible?
plot_counter <- 1
p2 <- ggplot(df, aes(x = var1, y = var2)) + geom_point() + ggtitle(paste("Plot", plot_counter + 1")

I'm not sure I get what you are trying to do. This does what I understood from your question:
df <- data.frame(var1 = seq(1:10), var2 = seq(3:12))
i <- 0
library(ggplot2)
p1 <- ggplot(df, aes(x = var1, y = var2)) + geom_point() +
ggtitle(paste("Plot", i <- i+1))
p2 <- ggplot(df, aes(x = var1, y = var2)) + geom_point() +
ggtitle(paste("Plot", i <- i+1))
p3 <- ggplot(df, aes(x = var1, y = var2)) + geom_point() +
ggtitle(paste("Plot", i <- i+1))
print(p1)
print(p2)
print(p3)
Are you using knitr? That might change the answer.

Related

is it possible to create a ggMarginal plot without desaggredating the data?

I have a data frame with some points and their frequency of occurrence and I want to plot points (balls) using their frequency to represent their size. But I also want to use ggMarginal to create the marginal plots. The code bellow creates the marginal without taking in account their frequencies.
library(ggplot2)
df <- data.frame("x" = 1:5, "y" = c(5,8,8,12,10), "f" = c(4,5,8,8,5))
p <- ggplot(df, aes(x=x, y=y, size=f)) + geom_point() + theme_bw()
ggExtra::ggMarginal(p, data=df, type = "histogram")
I don't want to create another data frame with disaggregated data. But it would lead to the right marginals. As presented bellow:
# disaggregated data
df2 <- df[ rep(1:nrow(df), df$f), c("x", "y") ]
p <- ggplot(df2, aes(x=x, y=y)) + geom_point() + theme_bw()
ggExtra::ggMarginal(p, data=df2, type = "histogram")
But even if I try to use both data frames, the resulting marginals still go wrong.
p <- ggplot(df, aes(x=x, y=y, size=f)) + geom_point() + theme_bw()
ggExtra::ggMarginal(p, data=df2, type = "histogram")
Is it possible to create the marginals with disaggregating the data? How?
If 1. is not possible, how to do it anyway, since none of the examples above provided the desired plot?
It can be done with cowplot package.
library(tidyverse)
library(cowplot)
df <- data.frame("x" = 1:5,
"y" = c(5,8,8,12,10),
"f" = c(4,5,8,8,5))
df2 <- df[rep(1:nrow(df), df$f), c("x", "y") ]
p <-
ggplot(df, aes(x=x, y=y, size=f)) +
geom_count() +
theme_bw()
xhist <-
axis_canvas(p, axis = "x") +
geom_histogram(data = df2, aes(x = x), color = 'lightgray')
yhist <-
axis_canvas(p, axis = "y", coord_flip = TRUE) +
geom_histogram(data = df2, aes(x = y), color = 'lightgray') +
coord_flip()
p %>%
insert_xaxis_grob(xhist, grid::unit(1, "in"), position = "top") %>%
insert_yaxis_grob(yhist, grid::unit(1, "in"), position = "right") %>%
ggdraw()

add y=0 line in some plots facet_grid ggplot2

I have a big plot, using facet_grid().
I want to add a vertical line to indicate y=0, but only in some of the plot.
Reproducible example -
df <- data.frame(x = 1:100, y = rnorm(100,sd=0.5), type = rep(c('A','B'), 50))
ggplot(df) + facet_grid(type~.) +
geom_point(data = df[df$type == 'A',], mapping = aes(x=x, y=y)) +
geom_rect(data = df[df$type == 'B',], mapping=aes(xmin=x,ymin=0,xmax=(x+2),ymax=y)) +
theme(panel.background=element_rect(fill="white"))
I want the line only in the top ptot for example.
Just create another data object for an hline geom and make sure to include the relevant faceted variable.
df <- data.frame(x = 1:100, y = rnorm(100,sd=0.5), type = rep(c('A','B'), 50))
ggplot(df) + facet_grid(type~.) +
geom_point(data = df[df$type == 'A',], mapping = aes(x=x, y=y)) +
geom_rect(data = df[df$type == 'B',], mapping=aes(xmin=x,ymin=0,xmax=(x+2),ymax=y)) +
geom_hline(data = data.frame(type="A", y=0), mapping=aes(yintercept=y)) +
theme(panel.background=element_rect(fill="white"))

add titles to ggplot2 plot as titles are showed in facet_wrap plots

It's posible to add titles to a single plot, like:
library(ggplot2)
gdURL <- "http://www.stat.ubc.ca/~jenny/notOcto/STAT545A/examples/gapminder/data/gapminderDataFiveYear.txt"
gDat <- read.delim(file = gdURL)
jDat <- droplevels(subset(gDat, continent != "Oceania"))
str(jDat)
jYear <- 2007
q <- ggplot(subset(jDat, year == jYear),
aes(x = gdpPercap, y = lifeExp)) + scale_x_log10()
q + geom_point()
q + geom_point(aes(size = sqrt(pop/pi)), pch = 21)
As titles are showed (In a grey box and integrated with the plot) in a facet_wrap plot like this??:
r <- q +
geom_point(aes(size = sqrt(pop/pi)), pch = 21, show_guide = FALSE) +
scale_size_continuous(range=c(1,40))
r <- r + facet_wrap(~ continent)
r + aes(fill = continent)
Per #jraab comment, one way to accomplish this is add a dummy column and use facet_grid:
jDat$dummy <- NA
ggplot(subset(jDat, year == jYear), aes(x = gdpPercap, y = lifeExp)) +
scale_x_log10() +
geom_point() +
facet_grid(. ~ dummy)
If you want to manipulate the title, you could use:
facet_grid(. ~ dummy, labeller=label_bquote("My New Title"))

Combined bar plot and points in ggplot2

I would like to plot a "combined" bar plot with points.
Consider to following dummy data:
library(ggplot2)
library(gridExtra)
library(dplyr)
se <- function(x){sd(x)/sqrt(length(x))}
p1 <- ggplot(mtcars, aes(y=disp, x=cyl, fill=cyl))
p1 <- p1 + geom_point() + theme_classic() + ylim(c(0,500))
my_dat <- summarise(group_by(mtcars, cyl), my_mean=mean(disp),my_se=se(disp))
p2 <- ggplot(my_dat, aes(y=my_mean,x=cyl,ymin=my_mean-my_se,ymax=my_mean+my_se))
p2 <- p2 + geom_bar(stat="identity",width=0.75) + geom_errorbar(stat="identity",width=0.75) + theme_classic() + ylim(c(0,500))
The final plot should look like that:
You can add layers together, but if they have different data and/or aesthetics you'll want to include the data and aes arguments in each graphical layer.
p3 <- ggplot() +
geom_bar(data=my_dat, aes(y=my_mean,x=cyl,ymin=my_mean-my_se,ymax=my_mean+my_se), stat="identity", width = 0.75) +
geom_errorbar(data=my_dat, aes(y=my_mean,x=cyl,ymin=my_mean-my_se,ymax=my_mean+my_se), width = 0.75) +
geom_point(data=mtcars, aes(y=disp, x=cyl, fill=cyl)) +
ylim(c(0,500)) +
theme_classic()
If you want to make it so that the the points are off to the side of the bars, you could subtract an offset from the cyl values to move over the points. Like #LukeA mentioned, by changing the geom_point to geom_point(data=mtcars, aes(y=disp, x=cyl-.5, fill=cyl)).
You can specify each layer individually to ggplot2. Often you are using the same data frame and options for each geom, so it makes sense to set defaults in ggplot(). In your case you should specify each geom separately:
library(ggplot2)
library(gridExtra)
library(dplyr)
se <- function(x){sd(x)/sqrt(length(x))}
my_dat <- summarise(group_by(mtcars, cyl),
my_mean = mean(disp),
my_se = se(disp))
p1 <- ggplot() +
geom_bar(data = my_dat,
aes(y = my_mean, x = cyl,
ymin = my_mean - my_se,
ymax = my_mean + my_se), stat="identity", width=0.75) +
geom_errorbar(data = my_dat,
aes(y = my_mean, x = cyl,
ymin = my_mean - my_se,
ymax = my_mean + my_se), stat="identity", width=0.75) +
geom_point(data = mtcars, aes(y = disp, x = cyl, fill = cyl)) +
theme_classic() + ylim(c(0,500))
p1

ggplot: relative frequencies of two groups

I want a plot like this except that each facet sums to 100%. Right now group M is 0.05+0.25=0.30 instead of 0.20+0.80=1.00.
df <- rbind(
data.frame(gender=c(rep('M',5)), outcome=c(rep('1',4),'0')),
data.frame(gender=c(rep('F',10)), outcome=c(rep('1',7),rep('0',3)))
)
df
ggplot(df, aes(outcome)) +
geom_bar(aes(y = (..count..)/sum(..count..))) +
facet_wrap(~gender, nrow=2, ncol=1)
(Using y = ..density.. gives worse results.)
here's another way
ggplot(df, aes(outcome)) +
geom_bar(aes(y = ..count.. / sapply(PANEL, FUN=function(x) sum(count[PANEL == x])))) +
facet_wrap(~gender, nrow=2, ncol=1)
I usually do this by simply precalculating the values outside of ggplot2 and using stat = "identity":
df1 <- melt(ddply(df,.(gender),function(x){prop.table(table(x$outcome))}),id.vars = 1)
ggplot(df1, aes(x = variable,y = value)) +
facet_wrap(~gender, nrow=2, ncol=1) +
geom_bar(stat = "identity")

Resources