R: Align plots with different x ranges - r

I have two dataframes dataA and dataB, both of which contain a time and a value column. Time columns are closely related, but non-identical. Now, I generate two plots with ggplot, e.g.:
plotA <- ggplot(dataA) + geom_line(aes(x = time, y = value))
plotB <- ggplot(dataB) + geom_line(aes(x = time, y = value))
How can I use grid.arrange or a similar function to display the two plots vertically and so that x-axis labels and grid lines align?

You could use facets to align the plots.
Firstly, both data sets need to be combined:
dataAB <- rbind(dataA[c("time", "value")], dataB[c("time", "value")])
A new column indicates the original data set:
dataAB$ind <- c(rep("A", nrow(dataA)), rep("B", nrow(dataB)))
Plot:
library(ggplot2)
ggplot(dataAB) +
geom_line(aes(x = time, y = value)) +
facet_wrap( ~ ind, ncol = 1, scales = "free_y")

Related

Represent dataset in column bar in R using ggplot [duplicate]

I have a csv file which looks like the following:
Name,Count1,Count2,Count3
application_name1,x1,x2,x3
application_name2,x4,x5,x6
The x variables represent numbers and the applications_name variables represent names of different applications.
Now I would like to make a barplot for each row by using ggplot2. The barplot should have the application_name as title. The x axis should show Count1, Count2, Count3 and the y axis should show the corresponding values (x1, x2, x3).
I would like to have a single barplot for each row, because I have to store the different plots in different files. So I guess I cannot use "melt".
I would like to have something like:
for each row in rows {
print barplot in file
}
Thanks for your help.
You can use melt to rearrange your data and then use either facet_wrap or facet_grid to get a separate plot for each application name
library(ggplot2)
library(reshape2)
# example data
mydf <- data.frame(name = paste0("name",1:4), replicate(5,rpois(4,30)))
names(mydf)[2:6] <- paste0("count",1:5)
# rearrange data
m <- melt(mydf)
# if you are wanting to export each plot separately
# I used facet_wrap as a quick way to add the application name as a plot title
for(i in levels(m$name)) {
p <- ggplot(subset(m, name==i), aes(variable, value, fill = variable)) +
facet_wrap(~ name) +
geom_bar(stat="identity", show_guide=FALSE)
ggsave(paste0("figure_",i,".pdf"), p)
}
# or all plots in one window
ggplot(m, aes(variable, value, fill = variable)) +
facet_wrap(~ name) +
geom_bar(stat="identity", show_guide=FALSE)
I didn't see #user20650's nice answer before preparing this. It's almost identical, except that I use plyr::d_ply to save things instead of a loop. I believe dplyr::do() is another good option (you'd group_by(Name) first).
yourData <- data.frame(Name = sample(letters, 10),
Count1 = rpois(10, 20),
Count2 = rpois(10, 10),
Count3 = rpois(10, 8))
library(reshape2)
yourMelt <- melt(yourData, id.vars = "Name")
library(ggplot2)
# Test a function on one piece to develope graph
ggplot(subset(yourMelt, Name == "a"), aes(x = variable, y = value)) +
geom_bar(stat = "identity") +
labs(title = subset(yourMelt, Name == 'a')$Name)
# Wrap it up, with saving to file
bp <- function(dat) {
myPlot <- ggplot(dat, aes(x = variable, y = value)) +
geom_bar(stat = "identity") +
labs(title = dat$Name)
ggsave(filname = paste0("path/to/save/", dat$Name, "_plot.pdf"),
myPlot)
}
library(plyr)
d_ply(yourMelt, .variables = "Name", .fun = bp)

ggplot : Plot two bars and one line?

I need to plot two bars and one line. I have 3 data frames as this:
require(ggplot2)
df.0 <- data.frame(x = c(1:5), y = rnorm(5))
df.1 <- data.frame(x = c(1:5), y = rnorm(5))
df.2 <- data.frame(x = c(1:5), y = runif(5))
ggplot(df.0, aes(x=x, y=y)) +
geom_line(aes(x=x, y=y))+
geom_bar(data=df.1, aes(x=x, y=y),stat = "identity",position="dodge")+
geom_bar(data=df.2, aes(x=x, y=y),stat = "identity",position="dodge")
I can't manage to plot the bars and the line in the correct way. It should look as the image below.
I'm not familiar with ggplot2. I've read a lot of links, and I can't find a post similar to my question.
Thanks for your time and interest.
Combine the data frames - at least the two for the bar plot. Dodging is done within a single geom_bar layer, not between two separate ones.
df_bar = rbind(df.1, df.2)
df_bar$id = rep(c("df.1", "df.2"), times = c(nrow(df.1), nrow(df.2)))
ggplot(df.0, aes(x = x, y = y)) +
geom_line() +
geom_col(data = df_bar, aes(fill = id), position="dodge")
Other changes: no need to repeat aes(x = x, y = y) in every layer. If it's in the original ggplot() it will be inherited. Also geom_col is a nice way of geom_bar(stat = 'identity').

grouping labels in ggplot

Here's my attempt to create a heatmap using ggplot2.
#DATA
set.seed(42)
df1 = data.frame(ID = paste0("I", 1:40),
group = rep(c("Dry", "Rain"), each = 20),
subgroup = rep(paste0("S", 1:4), each = 10),
setNames(data.frame(replicate(8, rnorm(40))), letters[1:8]))
library(reshape2)
df1 = melt(df1, id.vars = c("ID", "group", "subgroup"))
df1 = df1[order(df1$group, df1$subgroup),]
df1$fact = paste(df1$subgroup, df1$ID)
df1$fact = factor(df1$fact, levels = unique(df1$fact))
#PLOT
library(ggplot2)
ggplot(df1, aes(x = variable, y = fact, fill = value)) +
geom_tile() +
scale_y_discrete(labels = df1$subgroup[!duplicated(df1$ID)])
The plot is exactly what I want except for the fact that the labels S1, S2, S3, and S4 repeat 10 times each. Is there a way to display them only one time and then put some kind of break between S1, S2, S3, and S4.
I am also curious if there is way to put group to the left of subgroup in the plot as a secondary y-axis but that is optional.
You can use facet_grid which would address both having a subgroup indicator on the y-axis and a white space separation between the subgroups.
You can also remove y-axis labels in theme to avoid redundancy.
ggplot(df1, aes(x = variable, y = fact, fill = value)) +
geom_tile() +
facet_grid(subgroup~., scales="free_y") +
theme(axis.text.y = element_blank())
Note: scales="free_y" is necessary because fact is not identical across subgroups, see output if this parameter is absent.

Single barplot for each row of dataframe

I have a csv file which looks like the following:
Name,Count1,Count2,Count3
application_name1,x1,x2,x3
application_name2,x4,x5,x6
The x variables represent numbers and the applications_name variables represent names of different applications.
Now I would like to make a barplot for each row by using ggplot2. The barplot should have the application_name as title. The x axis should show Count1, Count2, Count3 and the y axis should show the corresponding values (x1, x2, x3).
I would like to have a single barplot for each row, because I have to store the different plots in different files. So I guess I cannot use "melt".
I would like to have something like:
for each row in rows {
print barplot in file
}
Thanks for your help.
You can use melt to rearrange your data and then use either facet_wrap or facet_grid to get a separate plot for each application name
library(ggplot2)
library(reshape2)
# example data
mydf <- data.frame(name = paste0("name",1:4), replicate(5,rpois(4,30)))
names(mydf)[2:6] <- paste0("count",1:5)
# rearrange data
m <- melt(mydf)
# if you are wanting to export each plot separately
# I used facet_wrap as a quick way to add the application name as a plot title
for(i in levels(m$name)) {
p <- ggplot(subset(m, name==i), aes(variable, value, fill = variable)) +
facet_wrap(~ name) +
geom_bar(stat="identity", show_guide=FALSE)
ggsave(paste0("figure_",i,".pdf"), p)
}
# or all plots in one window
ggplot(m, aes(variable, value, fill = variable)) +
facet_wrap(~ name) +
geom_bar(stat="identity", show_guide=FALSE)
I didn't see #user20650's nice answer before preparing this. It's almost identical, except that I use plyr::d_ply to save things instead of a loop. I believe dplyr::do() is another good option (you'd group_by(Name) first).
yourData <- data.frame(Name = sample(letters, 10),
Count1 = rpois(10, 20),
Count2 = rpois(10, 10),
Count3 = rpois(10, 8))
library(reshape2)
yourMelt <- melt(yourData, id.vars = "Name")
library(ggplot2)
# Test a function on one piece to develope graph
ggplot(subset(yourMelt, Name == "a"), aes(x = variable, y = value)) +
geom_bar(stat = "identity") +
labs(title = subset(yourMelt, Name == 'a')$Name)
# Wrap it up, with saving to file
bp <- function(dat) {
myPlot <- ggplot(dat, aes(x = variable, y = value)) +
geom_bar(stat = "identity") +
labs(title = dat$Name)
ggsave(filname = paste0("path/to/save/", dat$Name, "_plot.pdf"),
myPlot)
}
library(plyr)
d_ply(yourMelt, .variables = "Name", .fun = bp)

Plotting two variables using ggplot2 - same x axis

I have two graphs with the same x axis - the range of x is 0-5 in both of them.
I would like to combine both of them to one graph and I didn't find a previous example.
Here is what I got:
c <- ggplot(survey, aes(often_post,often_privacy)) + stat_smooth(method="loess")
c <- ggplot(survey, aes(frequent_read,often_privacy)) + stat_smooth(method="loess")
How can I combine them?
The y axis is "often privacy" and in each graph the x axis is "often post" or "frequent read".
I thought I can combine them easily (somehow) because the range is 0-5 in both of them.
Many thanks!
Example code for Ben's solution.
#Sample data
survey <- data.frame(
often_post = runif(10, 0, 5),
frequent_read = 5 * rbeta(10, 1, 1),
often_privacy = sample(10, replace = TRUE)
)
#Reshape the data frame
survey2 <- melt(survey, measure.vars = c("often_post", "frequent_read"))
#Plot using colour as an aesthetic to distinguish lines
(p <- ggplot(survey2, aes(value, often_privacy, colour = variable)) +
geom_point() +
geom_smooth()
)
You can use + to combine other plots on the same ggplot object. For example, to plot points and smoothed lines for both pairs of columns:
ggplot(survey, aes(often_post,often_privacy)) +
geom_point() +
geom_smooth() +
geom_point(aes(frequent_read,often_privacy)) +
geom_smooth(aes(frequent_read,often_privacy))
Try this:
df <- data.frame(x=x_var, y=y1_var, type='y1')
df <- rbind(df, data.frame(x=x_var, y=y2_var, type='y2'))
ggplot(df, aes(x, y, group=type, col=type)) + geom_line()

Resources