I want that the two plots on top of each other have the same size. The problem is that the length of tick labels are different and therefore the plots are not aligned. Just making the font smaller is not a solution because it's not reader friendly. There must be a way to say how big a plot should be just within ggplot.
I just want to control the size of the plot manually regardless whether I have to bar plots or a bar plot and boxplot etc. How do I accomplish this?
library(ggplot2)
library(grid)
library(gridExtra)
df1 <- data.frame(a = as.factor(1:20), b = runif(20, 500000, 900000))
df2 <- data.frame(a = as.factor(1:20), c = rnorm(2000))
plot1 <- ggplot(df1, aes(x = a, y =b)) + geom_bar(stat = "identity")
plot2 <- ggplot(df2, aes(x = a, y =c)) + geom_boxplot()
grid.arrange(plot1,
plot2,
ncol = 1)
Here is my example:
As one of the comments mentioned, package cowplot has the functionality you need.
library(ggplot2)
library(cowplot)
df1 <- data.frame(a = as.factor(1:20), b = runif(20, 5, 9))
df2 <- data.frame(a = as.factor(1:20), b = runif(20, 50000, 90000))
plot1 <- ggplot(df1, aes(x = a, y =b)) + geom_bar(stat = "identity")
plot2 <- ggplot(df2, aes(x = a, y =b)) + geom_bar(stat = "identity")
#see ?plot_grid for more details
plot_grid(plot1,plot2,ncol = 1, align = "v", rel_heights = c(.7, .3))
Created on 2019-01-12 by the reprex package (v0.2.1)
Related
I have a simple geom_point plot, in which the x variable is ordinal, taking 5 values (coded 1:5).
In the plot I would like to replace it with 5 corresponding text labels. Is it possible to do it in ggplot?
You should be able to do this with scale_x_discrete.
library(ggplot2)
df <- data.frame(x = 1:5, y = sample(1:10, 5, TRUE))
qplot(factor(x),y, data = df) +
scale_x_discrete(breaks = 1:5, labels=c("foo","bar","baz","phi","fum")) +
xlab(NULL)
scale_x_discrete should do it:
x <- sample(1:5, 20, T)
y <- rnorm(20) + x
df <- data.frame(x = ordered(x), y = y)
ggplot(df,aes(x,y)) + geom_point() +
scale_x_discrete(breaks = 1:5, labels = letters[1:5])
Here is a reproducible example I think encapsulates your Q (?):
require(ggplot2)
dat <- data.frame(X = sample(1:5, 100, replace = TRUE),
Y = rnorm(100))
It isn't immediately clear what data you have, but if you mean something like this:
(p1 <- ggplot(dat, aes(x = X, y = Y)) + geom_point())
Then I think you want a stripchart, which can be achieved in ggplot via a factor
dat2 <- within(dat, X <- factor(X, labels = letters[1:5]))
(p2 <- ggplot(dat2, aes(x = X, y = Y)) + geom_point())
If this isn't what you mean, can you edit your Q to provide an example?
Another option using scale_x_continuous where the breaks and labels are specified on a numerical continuous axis. Here is some reproducible code:
library(ggplot2)
df <- data.frame(x = 1:5, y = sample(1:10, 5, TRUE))
ggplot(df, aes(x = x, y = y)) +
geom_point() +
scale_x_continuous(breaks = c(1:5), labels = c("A", "B", "C", "D", "E"))
Created on 2023-02-03 with reprex v2.0.2
Say I have three SQUARE plots p1 p2 p3 made from the ggplot2 package. I applied ggarrange command under ggpubr package to make a 1*3 plot after that. Here are the commands:
library(ggplot2)
library(ggpubr)
library(gridExtra)
data <- data.frame(matrix(seq(1, 30, 1), 2))
for(i in 1:5){
plot1 <- ggplot(data = data, aes(y = data[, (i*3-2)])) +
theme(aspect.ratio = 1)
plot2 <- ggplot(data = data, aes(y = data[, (i*3-1)])) +
theme(aspect.ratio = 1)
plot3 <- ggplot(data = data, aes(y = data[, (i*3)])) +
theme(aspect.ratio = 1)
p <- ggarrange(plot1, plot2, plot3,
ncol = 3, common.legend = TRUE, legend = "bottom")
grid.arrange(p, top = paste(colnames(data)[i]), heights = c(1, 1))
}
The rmarkdown output (below) shows a large white space below the arranged plots:
Is there any way to remove it? What I thought is to change the default size of canvas..
I am trying to combine two FACETED ggplot objects with coord_equal() using cowplot::plot_grid() or egg::ggarrange() and vertically align them.
The egg::ggarrange() approach works fine for UNFACETED plots, with the solution posted here.
However, the egg::ggarrange() solution breaks down when faceting is included. The plots are correctly aligned, but the units of the y-axes are twice as large as those of the x-axes. Any suggestions for how to generalize this for faceting?
dat1 <- data.frame(x = rep(1:10, 2), y = 1:20, z = rep(c("A", "B"), 10))
dat2 <- data.frame(x = 1:10, y = 1:10, z = rep(c("A", "B"), 5))
plot1 <- ggplot(dat1, aes(x=x, y=y)) +
geom_point() + coord_equal() + facet_wrap(~z)
plot2 <- ggplot(dat2, aes(x=x, y=y)) +
geom_point() + coord_equal() + facet_wrap(~z)
egg::ggarrange(plot1, plot2, ncol = 1)
it seems to be a simple fix,
library(egg)
b <- body(gtable_frame)
b[6] <- parse(text="if (fixed_ar) {
ar <- as.numeric(g$heights[tt[1]]) / as.numeric(g$widths[ll[1]])
height <- width * (ar / length(ll))
g$respect <- FALSE
}")
body(gtable_frame) <- b
assignInNamespace("gtable_frame", gtable_frame, ns = 'egg')
The main problem is that plot1 and plot2 have different aspect ratios.
This is plot1:
And this plot2:
You can try to keep the aspect ratio using, i.e. theme(aspect.ratio=1) instead of coord_equal():
require(ggplot2)
dat1 <- data.frame(x = rep(1:10, 2), y = 1:20, z = rep(c("A", "B"), 10))
dat2 <- data.frame(x = 1:10, y = 1:10, z = rep(c("A", "B"), 5))
plot1 <- ggplot(dat1, aes(x=x, y=y)) + geom_point() + theme(aspect.ratio=1)+
facet_wrap(~z)
plot2 <- ggplot(dat2, aes(x=x, y=y)) + geom_point() + theme(aspect.ratio=1)+
facet_wrap(~z)
egg::ggarrange(plot1, plot2, ncol = 1,heights = c(1,10))
Hope it serves.
I am trying to plot bar graphs on a map following this example: How to plot barchart onto ggplot2 map. This works fine but in contrast to the example I would like to add x and y axis. The problem is that the y range of the data differs considerably across the regions for which I would like to create the bar graphs.
In order to produce comparable graphs (i.e. where the y axis has an identical dimension), I apply the same y limits to all graphs and adjust the breaks for each graph. This is, however, not a good solution as some of the graphs (p2 in this case) have a large empty area above and below the bars. In order to make it work, I am looking for a method top crop the graphs to remove the empty areas, while at the same time maintaining the dimensions of the graph so that y axis can be compared.
library(dplyr)
library(ggplot2)
df <- data.frame(type = c("A", "B", "A", "B"), country = c("NLD", "NLD", "BEL", "BEL"), value = c(10, -10, 5, 2))
df1 <- filter(df, country == "NLD")
p1 <- ggplot(data = df1) +
geom_col(aes(x = type, y = value)) +
scale_y_continuous(limits = c(min(df$value), max(df$value)), breaks = seq(min(df1$value), max(df1$value), 2)) +
theme_bw()
p1
df2 <- filter(df, country == "BEL")
p2 <- ggplot(data = df2) +
geom_col(aes(x = type, y = value)) +
scale_y_continuous(limits = c(min(df$value), max(df$value)), breaks = seq(min(df2$value), max(df2$value), 2)) +
theme_bw()
p2
Have you tried coord_fixed for each of the plot? If you can control the width of each plot the same, the height of bars will be comparable.
library(dplyr)
library(ggplot2)
library(gridExtra)
df <- data.frame(type = c("A", "B", "A", "B"), country = c("NLD", "NLD", "BEL", "BEL"), value = c(10, -10, 5, 2))
df1 <- filter(df, country == "NLD")
p1 <- ggplot(data = df1) +
geom_col(aes(x = type, y = value)) +
# scale_y_continuous(limits = c(min(df$value), max(df$value)), breaks = seq(min(df1$value), max(df1$value), 2)) +
theme_bw()
df2 <- filter(df, country == "BEL")
p2 <- ggplot(data = df2) +
geom_col(aes(x = type, y = value)) +
# scale_y_continuous(limits = c(min(df$value), max(df$value)), breaks = seq(min(df2$value), max(df2$value), 2)) +
theme_bw()
x_range <- length(unique(df$type))
y_range1 <- max(df1$value) - min(df1$value)
y_range2 <- max(df2$value) - min(df2$value)
g1 <- p1 + coord_fixed(ratio = x_range / y_range1)
g2 <- p2 + coord_fixed(ratio = x_range / y_range1)
# example output
grid.arrange(g1, g2, nrow = 1)
How do I show legend for the following ggplot bar plot?
tmp <- data.frame(group = LETTERS[1:10], id = 10:1, a = runif(10), b = runif(10))
ggplot(tmp) + geom_bar(aes(x = reorder(group, id), a + b, group = 1), stat = 'identity')
Update: I have two charts arranged using grid.arrange from gridExtra. Both charts have the same number of bars, but one has legend. I thought that by adding any legend to the second chart, I will align the bars (make width of plot area of both plots the same):
tmp <- data.frame(group = LETTERS[1:10], id = 10:1,
a = runif(10), b = runif(10), c = rnorm(10))
p1 <- ggplot(tmp) + geom_bar(aes(x = reorder(group, id), c, fill = a), stat = 'identity')
p2 <- ggplot(tmp) + geom_bar(aes(x = reorder(group, id), a + b, group = 1), stat = 'identity')
library(gridExtra)
grid.arrange(p1, p2, heights = c(2, 1) )
Now, it looks like this:
You can try something like this for p2, which will create a new legend for the bottom graph.
p2 <- ggplot(tmp) + geom_bar(aes(x = reorder(group, id), a + b, group = 1, fill = 0), stat = 'identity') +
guides(fill=guide_legend(title="Title"))
This is what i needed
guides(fill=guide_legend(title="Title"))
Thanks