Creating graphs in a loop: one graph different from the others - r

I have an elaborate code to create a series of graphs. I would like to put a vertical line in one of the many graphs I create.
Consider the following simple code:
library(ggplot2)
library(grid)
library(gridExtra)
plots <- list()
for (i in 1:4) {
V1 <- rnorm(1000)
V2 <- seq(1000)
df <- data.frame(V1, V2)
plots[[i]] <- ggplot(df, aes(x= V2, y=V1)) +
geom_point()+
geom_vline(xintercept = 500, color="red")
}
grid.arrange(grobs=plots, nrow=2)
I would like to have the red vertical line for graph 4 but not the others. How would I do this efficiently?

You don't need a for-loop and if-statement for this matter. You can use faceting;
library(ggplot2)
library(grid)
library(gridExtra)
library(dplyr)
set.seed(123) ## set the seed for random numbers to be reproducible
df <- bind_rows(lapply(1:4, function(x)
data.frame(V1=rnorm(1000), V2=seq(1000))), .id = 'facet')
ggplot(df, aes(x= V2, y=V1)) +
geom_point() +
facet_wrap(~facet) +
geom_vline(data=data.frame(xint=500,facet=4), aes(xintercept = xint), color = "red")

just split your plot production and set a condition :)
library(ggplot2)
library(grid)
library(gridExtra)
plots <- list()
for (i in 1:4) {
V1 <- rnorm(1000)
V2 <- seq(1000)
df <- data.frame(V1, V2)
plots[[i]] <- ggplot(df, aes(x= V2, y=V1)) +
geom_point()
if (i == 4) plots[[i]] <- plots[[i]] + geom_vline(xintercept = 500, color="red")
}
grid.arrange(grobs=plots, nrow=2)

Related

How to display the charts row-wise instead of column wise

marrangeGrob apparently displays the charts by column first. How to arrange these charts row-wise instead?
library(gridExtra)
library(tidyr)
library(ggplot2)
dat <- c(2,3,4,5,6,7,8,9,0,1)
time <- 1:10
data <- tibble(dat, time)
p1 <- ggplot(data, aes(x= time, y=dat)) +
geom_point(color="orange")
p2 <- ggplot(data, aes(x= time, y=dat)) +
geom_point(color="blue")
clist <- list(p1,p2)
marrangeGrob(clist, nrow=2, ncol=2, as.table=F )
Using the layout_matrix argument you could specify to add the plots by row (byrow=TRUE):
library(gridExtra)
library(ggplot2)
dat <- c(2,3,4,5,6,7,8,9,0,1)
time <- 1:10
data <- data.frame(dat, time)
p1 <- ggplot(data, aes(x= time, y=dat)) +
geom_point(color="orange")
p2 <- ggplot(data, aes(x= time, y=dat)) +
geom_point(color="blue")
clist <- list(p1,p2)
marrangeGrob(clist, nrow=2, ncol=2,
layout_matrix = matrix(seq_len(4), nrow = 2, byrow = TRUE))

Question about ggplot, for loop and marrangeGrob. Does anyone know how to fix the code when all plots are the same? [duplicate]

I've written a for loop which goes through the columns of a dataframe and produces a graph for each column using ggplot. The problem is the graphs that are output are all the same - they're all graphs of the final column.
The code I've used is:
library(gridExtra)
library(ggplot2)
test1 <- c("Person1","Person2","Person3","Person4","Person5")
test2 <- as.data.frame(c(1,2,3,4,5))
test3 <- as.data.frame(c(2,2,2,2,2))
test4 <- as.data.frame(c(1,3,5,3,1))
test5 <- as.data.frame(c(5,4,3,2,1))
test <- cbind(test1,test2,test3,test4,test5)
rm(test1,test2,test3,test4,test5)
colnames(test) <- c("Person","var1","var2","var3","var4")
for(i in 2:5){
nam <- paste0("graph", i-1)
graph_temp <- ggplot(test, aes(Person, test[,i])) + geom_bar(stat = "identity")
assign(nam, graph_temp)
}
grid.arrange(graph1, graph2, graph3, graph4, ncol=2)
What I'm aiming for is the plot from this code:
library(gridExtra)
library(ggplot2)
test1 <- c("Person1","Person2","Person3","Person4","Person5")
test2 <- as.data.frame(c(1,2,3,4,5))
test3 <- as.data.frame(c(2,2,2,2,2))
test4 <- as.data.frame(c(1,3,5,3,1))
test5 <- as.data.frame(c(5,4,3,2,1))
test <- cbind(test1,test2,test3,test4,test5)
rm(test1,test2,test3,test4,test5)
colnames(test) <- c("Person","var1","var2","var3","var4")
graph1 <- ggplot(test, aes(Person, test[,2])) + geom_bar(stat = "identity")
graph2 <- ggplot(test, aes(Person, test[,3])) + geom_bar(stat = "identity")
graph3 <- ggplot(test, aes(Person, test[,4])) + geom_bar(stat = "identity")
graph4 <- ggplot(test, aes(Person, test[,5])) + geom_bar(stat = "identity")
grid.arrange(graph1, graph2, graph3, graph4, ncol=2)
I know there's a similar question on saving ggplots in a for loop, but I've not managed to get that one to work for this problem.
Here's a more concise way to produce your example:
df <- data.frame(
Person = paste0("Person", 1:5),
var1 = c(1,2,3,4,5),
var2 = c(2,2,2,2,2),
var3 = c(1,3,5,3,1),
var4 = c(5,4,3,2,1)
)
Now, about your plots.
Best solution
Reshape the data frame to 'long' format, and then use facets:
library(ggplot2)
library(tidyr)
gather(df, var, value, -Person) %>%
ggplot(aes(Person, value)) +
geom_bar(stat = "identity") +
facet_wrap(~ var)
Otherwise…
If you gotta stick with a data structure that looks like what you posted, then use aes_string:
library(ggplot2)
library(gridExtra)
g <- lapply(1:4, function(i) {
ggplot(df, aes_string("Person", paste0("var", i))) +
geom_bar(stat = "identity")
})
grid.arrange(grobs = g, ncol = 2)

Symmetric y-axis limits for barchart in ggplot2

I would like to make the y-axis of a bar chart symmetric, so that it's easier to see if positive or negative changes are bigger. Since otherwise this is a bit distorted. I do have working code although it's a bit clumsy and I thought it would be great if I could directly do this in the first ggplot() call. So as to say that ylim directly is symmetrical.
set.seed(123)
my.plot <- ggplot( data = data.table(x = 1:10,
y = rnorm(10,0, 2)), aes(x=x, y=y)) +
geom_bar(stat="identity")
rangepull <- layer_scales(my.plot)$y
newrange <- max(abs(rangepull$range$range))
my.plot +
ylim(newrange*-1, newrange)
What about this :
library(ggplot2)
library(data.table)
set.seed(123)
my.data = data.table(x = 1:10, y = rnorm(10,0, 2))
my.plot <- ggplot(data = my.data)+aes(x=x, y=y) +
geom_bar(stat="identity")+ylim((0-abs(max(my.data$y))),(0+max(abs(my.data$y))))
my.plot
You may want to consider using ceiling:
set.seed(123)
library(ggplot2)
library(data.table)
dT <- data.table(x = 1:10, y = rnorm(10,0, 2))
my.plot <- ggplot(dT, aes(x=x, y=y)) +
geom_bar(stat="identity") +
ylim(-ceiling(max(abs(dT$y))), ceiling(max(abs(dT$y))))
This will give you:
> my.plot

How to use 'facet' to create multiple density plot in GGPLOT

I have the following data created on the fly:
> df <- data.frame( cbind(rnorm(200),rnorm(200, mean=.8),rnorm(200, mean=.9),rnorm(200, mean=1),rnorm(200, mean=.2),rnorm(200, mean=.3)),rnorm(200, mean=4),rnorm(200, mean=.5))
> colnames(df) <- c("w.cancer","w.normal","x.cancer","x.normal","y.cancer","y.normal","z.cancer","z.normal")
> df_log<-log2(df) # ignore the warning with NA
> head(df_log)
What I want to do is to create multiple plots in one panel like the sketch below using 'facet'.
How can I go about it?
You'll have to prepare your data first. I've illustrated this on your data.frame df as it is a proper normal distribution.
require(ggplot2)
require(reshape2)
df$id <- 1:nrow(df)
df.m <- melt(df, "id")
df.m$grp1 <- factor(gsub("\\..*$", "", df.m$variable))
df.m$grp2 <- factor(gsub(".*\\.", "", df.m$variable))
p <- ggplot(data = df.m, aes(x=value)) + geom_density(aes(fill=grp2), alpha = 0.4)
p <- p + facet_wrap( ~ grp1)
p + scale_fill_brewer(palette = "Set1")
Doing the same by replacing df with df_log you'd get something like this:
require(ggplot2)
require(reshape2)
df_log$id <- 1:nrow(df_log)
df.m <- melt(df_log, "id")
df.m$grp1 <- factor(gsub("\\..*$", "", df.m$variable))
df.m$grp2 <- factor(gsub(".*\\.", "", df.m$variable))
p <- ggplot(data = df.m, aes(x=value)) + geom_density(aes(fill=grp2), alpha = 0.5)
p <- p + facet_wrap( ~ grp1)
p

ggplot() lines transparency

How to change the transparency level of lines in ggplot() diagram (i.e. histogram, line plot, etc.)?
For instance consider the code below:
data <- data.frame(a=rnorm(100), b = rnorm(100,.5,1.2))
data <- melt(data)
colnames(data) <- c("Category", "Intensity")
p <- ggplot(data, aes(x=Intensity))
p <- p + geom_density(aes(color=Category), size=2, alpha=.4)
print(p)
I expected the lines would be transparent (as alpha=.4), but they're not.
Simply following #baptiste's directions,
data <- data.frame(a=rnorm(100), b = rnorm(100,.5,1.2))
data <- melt(data)
colnames(data) <- c("Category", "Intensity")
p <- ggplot(data, aes(x=Intensity))
p + geom_line(aes(color=Category), stat="density", size=2, alpha=0.4)

Resources