I want to combine several ggplot2 charts into one using cowplot::plot_grid(). From its documentation:
?plot
Arguments
...
List of plots to be arranged into the grid. The plots can be objects of one of the following classes: ggplot, recordedplot, gtable, or alternative can be a function creating a plot when called (see examples).
So, If I input a list of ggplot2 objects to plot_grid(), it should combine those plots into one, right?
So why won't this work?
p1 <- ggplot(mpg, aes(x = cty, y = hwy, colour = factor(cyl))) +
geom_point(size=2.5)
p2 <- ggplot(diamonds, aes(clarity, fill = cut)) + geom_bar() +
theme(axis.text.x = element_text(angle=70, vjust=0.5))
list(p1, p2) %>%
map(plot_grid)
See the documentation of map (?map), it states that:
.x A list or atomic vector.
.f A function, formula, or atomic vector.
It means the function you provided for .f will be applied to every elements in .x. So the following code
list(p1, p2) %>% map(plot_grid)
is the same as the following code
plot_grid(p1)
plot_grid(p2)
,which is probably not what you want.
What you want is probably this
plot_grid(p1, p2)
Or this
plot_grid(plotlist = list(p1, p2))
You want do.call(), not map(), to pass a list of arguments to a function. For your example above:
library(ggplot2)
p1 <- ggplot(mpg, aes(x = cty, y = hwy, colour = factor(cyl))) +
geom_point(size=2.5)
p2 <- ggplot(diamonds, aes(clarity, fill = cut)) + geom_bar() +
theme(axis.text.x = element_text(angle=70, vjust=0.5))
plots <- list(p1, p2)
do.call(cowplot::plot_grid, plots)
Related
If the labels in the example below were to be overlapping, how could we implement a repel option? Thanks!
means <- df %>%
group_by(cyl) %>%
summarize(across(c(wt, mpg), mean))
ggplot(df) +
aes(x=wt, y=mpg, color=cyl, shape=cyl) +
geom_point() +
geom_point(size=4, data=means) +
geom_label(aes(label=cyl), color="black", data=means) -> fig
fig
If I add the geom_label_repel() from the ggrepel package
fig + geom_label_repel()
I get the error:
geom_label_repel requires the gollowing missing aesthetics: label
You need to map label so that geom_label_repel "sees" it. It doesn't have direct view of the mapping from other geoms. Just itself and the top ggplot call. You thus have two options.
Directly within the function
geom_label_repel(mapping = aes(label = cyl))
or in the top ggplot call
ggplot(data = df, mapping = aes(label = cyl)) +
Note that you'll probably have to specify data as Vincent mentioned in the comment if you want to label the means points.
I start to study R. I'm starting with Iris dataset in the package datasets. To draw som graph I need to use the ggplot2 package. How can I split the Plots window and draw two graphs?
I try with the following code, but only one graph is showed.
iris=datasets::iris
par(mfrow=c(2,1))
ggplot(iris, aes(x=Sepal.Length,y=Sepal.Width,color=Species))+ geom_point(size=3)
ggplot(iris, aes(x=Petal.Length,y=Petal.Width,color=Species))+ geom_point(size=3)
use win.graph() to split the window into two.
Since you have not provided dataset, if you want to create a side by side plot try based on my example below
Try this:
library(cowplot)
iris1 <- ggplot(iris, aes(x = Species, y = Sepal.Length)) +
geom_boxplot() + theme_bw()
iris2 <- ggplot(iris, aes(x = Sepal.Length, fill = Species)) +
geom_density(alpha = 0.7) + theme_bw() +
theme(legend.position = c(0.8, 0.8))
plot_grid(iris1, iris2, labels = "AUTO")
As ggplot2 is based on grid graphics system instead of base plot, par does not effective in adjusting ggplot2 plots, and the latest version of ggplot2 has already supported the arrangement of different plots, and you can set tags for each of them:
iris=datasets::iris
ggplot(iris, aes(x=Sepal.Length,y=Sepal.Width,color=Species))+ geom_point(size=3) + labs(tag = "A") -> p1
ggplot(iris, aes(x=Petal.Length,y=Petal.Width,color=Species))+ geom_point(size=3) + labs(tag = "B") -> p2
p1 + p2
For more sophisticated arrangement, you can use patchwork package to arrange them
I'm using fct_reorder() to order the levels of my factors in ggplot. That works fine for individual plots. But when I use plot_grid() from cowplot, there is some kind of problem. For contrast, to the left, I've used a plot that has fixed factor levels, not using fct_reorder.
Edited:
Here is the actual code I'm using:
#make the base
myplot <-filter(summary_by_intensity_reshaped, str_detect(feature, "binary"), Frequency == "2Hz") %>%
ggplot(., aes(fct_reorder(feature, mean),mean,fill=Intensity, ymax=mean+sem, ymin=mean-sem))
#add the layers
myplot + geom_bar(stat="identity", position=position_dodge()) +
geom_errorbar(aes(width=0.2),position=position_dodge(0.9)) +
labs(x="Behavior",y="Percent of Trials (%)") +
scale_x_discrete(breaks=c("binary_flutter", "binary_hold", "binary_lift", "binary_jump","binary_rear", "binary_lick", "binary_guard", "binary_vocalize"), labels=c("Flutter", "Holding", "Lifting", "Jumping", "Rearing", "Licking", "Guarding", "Vocalizing"))+
facet_grid(~Frequency)+
theme(axis.text.x=element_text(angle=-90))
And the output looks like this:
The problem arises when I try to use 'myplot' in plot_grid(). That's when it renders oddly as in the example below.
I suspect you're using fct_reorder() incorrectly. plot_grid() just takes whatever plot you make and puts it into a grid.
library(ggplot2)
library(cowplot)
library(forcats)
p1 <- ggplot(mpg, aes(class, displ, color = factor(cyl))) + geom_point()
p2 <- ggplot(mpg, aes(fct_reorder(class, displ, mean), displ, color = factor(cyl))) +
geom_point()
plot_grid(p1, p2)
From your x axis title in the plot on the right, it looks to me like you forgot to provide fct_reorder() with the vector to which it should apply the function.
I want to combine these two graphs :
p1 <- ggplot(iris, aes(Sepal.Length)) +
geom_density() +
facet_wrap(~ Species)
p2 <- ggplot(iris, aes(Sepal.Length)) +
geom_density()
To combine, I do :
multiplot(p1, p2, cols = 2)
But it is not the desired shape.
I would like the graph p2 has the same dimensions than others and is situated just next to the last faceted graph.
Thanks for help
Not sure if this is applicable in you generic case, but with facet_grid instead of facet_wrap, you can use the margins argument:
library(ggplot2)
ggplot(iris, aes(Sepal.Length)) +
geom_density() +
facet_grid(. ~ Species, margins = T)
If you question is more generic the answer probably lies in grid.arrange.
Something like this could be a start:
library(gridExtra)
grid.arrange(arrangeGrob(p1, p2,
widths = c(3,1),
heights = c(1,20),
layout_matrix = matrix(c(1,1,NA,2),2)))
As you can see there are several problems (different axes, top strip), but working with grid could gets complicated quickly.
This code should work:
p1 <- ggplot(iris, aes(Sepal.Length)) +
geom_density() +
ylim(limits = c(0, 1.25))+
facet_wrap(~ Species)
p2 <- ggplot(iris, aes(Sepal.Length)) +
geom_density() +
ggtitle("") + # ad empty title as place holder
labs(y = "", x = "") + # hide axis labels
ylim(limits = c(0, 1.25)) + # y axis values should be fixed in both plots
coord_fixed(ratio=20/1) + # ratio of x- and y-axis to reduce width of plot
theme(axis.ticks.y = element_blank(), axis.text.y = element_blank(), axis.line.y = element_blank(),
plot.margin=unit(c(0,0,0.65,-10), "lines")) # margin between plots = "0.65"
I fiddled a bit and used just different styling options to produce this result. If you have more plots than this one I would recommend to use one theme for all.
You can use either the multiplot function that you are already using
multiplot(p1, p2, cols = 2)
or you install the packages gridExtra and grid and use that one:
grid.arrange(p1, p2, ncol=2)
Hope this helps!
I have two dataframes: dataf1, dataf2. They have the same structure and columns.
3 columns names are A,B,C. And they both have 50 rows.
I would like to plot the histogram of column B on dataf1 and dataf2. I can plot two histograms separately but they are not of the same scale. I would like to know how to either put them on the same histogram using different colors or plot two histograms of the same scale?
ggplot() + aes(dataf1$B)+ geom_histogram(binwidth=1, colour="black",fill="white")
ggplot() + aes(dataf2$B)+ geom_histogram(binwidth=1, colour="black", fill="white")
Combine your data into a single data frame with a new column marking which data frame the data originally came from. Then use that new column for the fill aesthetic for your plot.
data1$source="Data 1"
data2$source="Data 2"
dat_combined = rbind(data1, data2)
You haven't provided sample data, so here are a few examples of possible plots, using the built-in iris data frame. In the plots below, dat is analogous to dat_combined, Petal.Width is analogous to B, and Species is analogous to source.
dat = subset(iris, Species != "setosa") # We want just two species
ggplot(dat, aes(Petal.Width, fill=Species)) +
geom_histogram(position="identity", colour="grey40", alpha=0.5, binwidth=0.1)
ggplot(dat, aes(Petal.Width, fill=Species)) +
geom_histogram(position="dodge", binwidth=0.1)
ggplot(dat, aes(Petal.Width, fill=Species)) +
geom_histogram(position="identity", colour="grey40", binwidth=0.1) +
facet_grid(Species ~ .)
As Zheyuan says, you just need to set the y limits for each plot to get them on the same scale. With ggplot2, one way to do this is with the lims command (though scale_y_continuous and coord_cartesian also work, albeit slightly differently). You also should never use data$column indside aes(). Instead, use the data argument for the data frame and unquoted column names inside aes(). Here's an example with some built-in data.
p1 = ggplot(mtcars, aes(x = mpg)) + geom_histogram() + lims(y = c(0, 13))
p2 = ggplot(iris, aes(x = Sepal.Length)) + geom_histogram() + lims(y = c(0, 13))
gridExtra::grid.arrange(p1, p2, nrow = 1)
Two get two histograms on the same plot, the best way is to combine your data frames. A guess, without seeing what your data looks like:
dataf = rbind(dataf1["B"], dataf2["B"])
dafaf$source = c(rep("f1", nrow(dataf1)), rep("f2", nrow(dataf2))
ggplot(dataf, aes(x = B, fill = source)) +
geom_histogram(position = "identity", alpha = 0.7)