ggplot: how to align two time-series plots on the x axis? - r

I am struggling with the following problem. Consider this (simple) example
library(grid)
library(gridExtra)
library(gtable)
library(dplyr)
library(lubridate)
options("digits.secs"=3)
time1 = c('2013-01-03 22:04:21.549', '2013-01-03 22:04:22.549', '2013-01-03 22:04:23.559', '2013-01-03 22:04:24.559' )
value1 = c(1,2,3,4)
data1 <- data_frame(time1, value1)
data1 <- data1 %>% mutate(time1 = ymd_hms(time1))
time2 = c('2013-01-03 22:04:21.800', '2013-01-03 22:04:22.549', '2013-01-03 22:04:25.559', '2013-01-03 22:04:26.559' )
value2 = c(1,2,3,4)
data2 <- data_frame(time2, value2)
data2 <- data2 %>% mutate(time2 = ymd_hms(time2))
g1 <- ggplot(data1, aes(x = time1, y = value1)) +geom_point()
g2 <- ggplot(data2, aes(x = time2, y = value2)) +geom_point()
graph_1 <- arrangeGrob(g1, g2, ncol=1)
grid.draw(graph_1)
which gives
as you can see the x- axis is not properly aligned.
Any ideas how to do that? Alternative solutions like How to align two plots with ggplot? do not work here.
Many thanks!!

You can either use the same limit for both plots (first) or use the facet_grid to align the range for plots (second).
# first method
mx <- ymd_hms("2013-01-03 22:04:21.000")
mn <- ymd_hms("2013-01-03 22:04:27.000")
grid.arrange(g1 + scale_x_datetime(limits=c(mx, mn)),
g2 + scale_x_datetime(limits=c(mx, mn)))
# second method
names(data1) <- c("time", "value")
names(data2) <- c("time", "value")
df <- bind_rows(first=data1, second=data2, .id="group")
ggplot(df, aes(x=time, y=value)) + geom_point() + facet_grid(group ~ .)

You can set the limits of both plots to the range of the data:
xmin <- ymd_hms(min(time1,time2))
xmax <- ymd_hms(max(time1,time2))
g1 <- ggplot(data1, aes(x = time1, y = value1)) + geom_point() +
theme(axis.title.x = element_blank()) + xlim(xmin, xmax)
g2 <- ggplot(data2, aes(x = time2, y = value2)) + geom_point() +
xlim(xmin, xmax)

Related

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)

How to add gaps using geom_tile in R?

I plot a heatmap using geom_tile (ggplot2):
library("reshape2")
library("ggplot2")
x <- matrix(1:12, nrow=3)
rownames(x) <- LETTERS[1:3]
colnames(x) <- letters[1:4]
x_melted <- melt(x)
x_melted$group1 <- rep(c("T1","T2"), each=6)
ggplot(x_melted, aes(x = Var1, y = Var2)) + geom_tile(aes(fill = value))
But I need add a gap according to group1 in x_melted so that a gap was produced between the first two rows and the last two rows. How could this be added?
One way would be to use facets -
x_melted$group1 = factor(x_melted$group1, levels = c("T2", "T1"))
ggplot(x_melted, aes(x = Var1, y = Var2)) +
geom_tile(aes(fill = value)) +
facet_grid(group1 ~ ., scales = "free_y")

R ggplot2: draw segment between points

How can I use geom_segment to draw lines on plot, after the data have been melted with reshape2?
# Tiny dataset
facet_group <- c("facet1", "facet1", "facet2", "facet2")
time_group <- c("before", "after", "before", "after")
variable1 <- c(1,5,4,7)
variable2 <- c(2,4,5,8)
variable3 <- c(4,5,6,7)
data <- data.frame(facet_group, time_group, variable1, variable2, variable3)
# Melt data
library(reshape2)
data_melt <- melt(data, id.vars = c("facet_group", "time_group"))
Plot the data:
# Plot 1
library(ggplot2)
ggplot(data_melt, aes(x=variable, y=value, group = time_group)) +
geom_point(aes(color = time_group))
Add faceting:
# Plot 2
ggplot(data_melt, aes(x=variable, y=value, group = time_group)) +
geom_point(aes(color = time_group)) +
facet_grid(facet_group ~ .)
I want to draw a segments from the "before" point to the "after" point for each variable. (see mock up image). How can I do this? I tried some things with geom_segment but I kept having errors. Will casting the data into a new data frame help?? Thanks!
data_cast <- dcast(data_melt, variable + facet_group ~ time_group)
Final "ideal" plot:
You were definitely on the right track with the casted data. Give this a shot:
ggplot(data_melt, aes(x=variable, y=value)) +
geom_point(aes(color = time_group)) +
facet_grid(facet_group ~ .) +
geom_segment(data = data_cast, aes(x = variable, xend = variable,
y = before, yend = after),
arrow = arrow(),
colour = "#FF3EFF",
size = 1.25)

ggplot for loop outputs all the same graph

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)

Grouped bins with multiple y axis

I have a data frame with five columns and five rows. the data frame looks like this:
df <- data.frame(
day=c("m","t","w","t","f"),
V1=c(5,10,20,15,20),
V2=c(0.1,0.2,0.6,0.5,0.8),
V3=c(120,100,110,120,100),
V4=c(1,10,6,8,8)
)
I want to do some plots so I used the ggplot and in particular the geom_bar:
ggplot(df, aes(x = day, y = V1, group = 1)) + ylim(0,20)+ geom_bar(stat = "identity")
ggplot(df, aes(x = day, y = V2, group = 1)) + ylim(0,1)+ geom_bar(stat = "identity")
ggplot(df, aes(x = day, y = V3, group = 1)) + ylim(50,200)+ geom_bar(stat = "identity")
ggplot(df, aes(x = day, y = V4, group = 1)) + ylim(0,15)+ geom_bar(stat = "identity")
My question is, How can I do a grouped ggplot with geom_bar with multiple y axis? I want at the x axis the day and for each day I want to plot four bins V1,V2,V3,V4 but with different range and color. Is that possible?
EDIT
I want the y axis to look like this:
require(reshape)
data.m <- melt(df, id.vars='day')
ggplot(data.m, aes(day, value)) +
geom_bar(aes(fill = variable), position = "dodge", stat="identity") +
facet_grid(variable ~ .)
You can also change the y-axis limits if you like (here's an example).
Alternately you may have meant grouped like this:
require(reshape)
data.m <- melt(df, id.vars='day')
ggplot(data.m, aes(day, value)) +
geom_bar(aes(fill = variable), position = "dodge", stat="identity")
For the latter examples if you want 2 Y axes then you just create the plot twice (once with a left y axis and once with a right y axis) then use this function:
double_axis_graph <- function(graf1,graf2){
graf1 <- graf1
graf2 <- graf2
gtable1 <- ggplot_gtable(ggplot_build(graf1))
gtable2 <- ggplot_gtable(ggplot_build(graf2))
par <- c(subset(gtable1[['layout']], name=='panel', select=t:r))
graf <- gtable_add_grob(gtable1, gtable2[['grobs']][[which(gtable2[['layout']][['name']]=='panel')]],
par['t'],par['l'],par['b'],par['r'])
ia <- which(gtable2[['layout']][['name']]=='axis-l')
ga <- gtable2[['grobs']][[ia]]
ax <- ga[['children']][[2]]
ax[['widths']] <- rev(ax[['widths']])
ax[['grobs']] <- rev(ax[['grobs']])
ax[['grobs']][[1]][['x']] <- ax[['grobs']][[1]][['x']] - unit(1,'npc') + unit(0.15,'cm')
graf <- gtable_add_cols(graf, gtable2[['widths']][gtable2[['layout']][ia, ][['l']]], length(graf[['widths']])-1)
graf <- gtable_add_grob(graf, ax, par['t'], length(graf[['widths']])-1, par['b'])
return(graf)
}
I believe there's also a package or convenience function that does the same thing.
First I reshaped as described in the documentation in the link below the question.
In general ggplot does not support multiple y-axis. I think it is a philosophical thing. But maybe faceting will work for you.
df <- read.table(text = "day V1 V2 V3 V4
m 5 0.1 120 1
t 10 0.2 100 10
w 2 0.6 110 6
t 15 0.5 120 8
f 20 0.8 100 8", header = TRUE)
library(reshape2)
df <- melt(df, id.vars = 'day')
ggplot(df, aes(x = variable, y = value, fill = variable)) + geom_bar(stat = "identity") + facet_grid(.~day)
If I understand correctly you want to include facets in your plot. You have to use reshape2 to get the data in the right format. Here's an example with your data:
df <- data.frame(
day=c("m","t","w","t","f"),
V1=c(5,10,20,15,20),
V2=c(0.1,0.2,0.6,0.5,0.8),
V3=c(120,100,110,120,100),
V4=c(1,10,6,8,8)
)
library(reshape2)
df <- melt(df, "day")
Then plot with and include facet_grid argument:
ggplot(df, aes(x=day, y=value)) + geom_bar(stat="identity", aes(fill=variable)) +
facet_grid(variable ~ .)

Resources