Scatterplot with marginal histograms in ggplot2
The gridExtra
package should work here. Start by making each of the ggplot objects:
hist_top <- ggplot()+geom_histogram(aes(rnorm(100)))
empty <- ggplot()+geom_point(aes(1,1), colour="white")+
theme(axis.ticks=element_blank(),
panel.background=element_blank(),
axis.text.x=element_blank(), axis.text.y=element_blank(),
axis.title.x=element_blank(), axis.title.y=element_blank())
scatter <- ggplot()+geom_point(aes(rnorm(100), rnorm(100)))
hist_right <- ggplot()+geom_histogram(aes(rnorm(100)))+coord_flip()
Then use the grid.arrange function:
grid.arrange(hist_top, empty, scatter, hist_right, ncol=2, nrow=2, widths=c(4, 1), heights=c(1, 4))
How to create marginal/histogram plot along with a geom_count plot in R?
You can do that with cowplot
package instead of ggExtra
package.
library(tidyverse)
library(cowplot)
g <-
ggplot(mpg, aes(cty, hwy)) +
geom_count(show.legend = F)
xhist <-
axis_canvas(g, axis = "x") +
geom_histogram(data = mpg,
aes(x = cty),
binwidth = 1,
color = 'lightgray')
yhist <-
axis_canvas(g, axis = "y", coord_flip = TRUE) +
geom_histogram(data = mpg,
aes(x = hwy),
binwidth = 1,
color = 'lightgray') +
coord_flip()
g %>%
insert_xaxis_grob(xhist, grid::unit(1, "in"), position = "top") %>%
insert_yaxis_grob(yhist, grid::unit(1, "in"), position = "right") %>%
ggdraw()
Plotting marginal histograms (as factors) and scatterplot (as numeric) from the same variable in R
If you are willing to give baseplotting a try, here is a function:
plots$scatterWithHists <- function(x, y, histCols=c("lightblue","lightblue"), lhist=20, xlim=range(x), ylim=range(y), ...){
## set up layout and graphical parameters
layMat <- matrix(c(1,4,3,2), ncol=2)
layout(layMat, widths=c(5/7, 2/7), heights=c(2/7, 5/7))
ospc <- 0.5 # outer space
pext <- 4 # par extension down and to the left
bspc <- 1 # space between scatter plot and bar plots
par. <- par(mar=c(pext, pext, bspc, bspc), oma=rep(ospc, 4)) # plot parameters
## barplot and line for x (top)
xhist <- hist(x, breaks=seq(xlim[1], xlim[2], length.out=lhist), plot=FALSE)
par(mar=c(0, pext, 0, 0))
barplot(xhist$density, axes=FALSE, ylim=c(0, max(xhist$density)), space=0, col=histCols[1])
## barplot and line for y (right)
yhist <- hist(y, breaks=seq(ylim[1], ylim[2], length.out=lhist), plot=FALSE)
par(mar=c(pext, 0, 0, 0))
barplot(yhist$density, axes=FALSE, xlim=c(0, max(yhist$density)), space=0, col=histCols[2], horiz=TRUE)
## overlap
dx <- density(x)
dy <- density(y)
par(mar=c(0, 0, 0, 0))
plot(dx, col=histCols[1], xlim=range(c(dx$x, dy$x)), ylim=range(c(dx$y, dy$y)),
lwd=4, type="l", main="", xlab="", ylab="", yaxt="n", xaxt="n", bty="n"
)
points(dy, col=histCols[2], type="l", lwd=3)
## scatter plot
par(mar=c(pext, pext, 0, 0))
plot(x, y, xlim=xlim, ylim=ylim, ...)
}
Just do:
scatterWithHists(x,y, histCols=c("lightblue","orange"))
And you get:
If you absolutely want to use ggMargins
then look up xparams
and yparams
. It says you can send additional arguments to x-margin and y-margin using those. I was only successful in sending trivial things like color. But maybe sending something like xlim
would help.
Align another object with scatterplot+marginal boxplots
You could:
- Change
element_blank
toaxis.text.x = element_text(colour = "white")
so axis text is the same colour as the plot background so not visible, forcing the axis label to be on the vertical position as the main plot. - Include a dummy plot with
NULL
in the call toplot_grid
And, in response to additional question in comments... - use
grid::nullGrob
to make the right hand side plot panel the same height as the main plot panel.
library(ggplot2)
library(cowplot)
# Main plot
pmain <- ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width, color = Species))+
geom_point()+
ggpubr::color_palette("jco")+
theme(legend.position = c(0.8, 0.8))
# Marginal densities along x axis
xdens <- axis_canvas(pmain, axis = "x")+
geom_boxplot(data = iris, aes(x = Sepal.Length, fill = Species),
alpha = 0.7, size = 0.2)+
ggpubr::fill_palette("jco")
# Marginal densities along y axis
# Need to set coord_flip = TRUE, if you plan to use coord_flip()
ydens <- axis_canvas(pmain, axis = "y", coord_flip = TRUE)+
geom_boxplot(data = iris, aes(x = Sepal.Width, fill = Species),
alpha = 0.7, size = 0.2)+
coord_flip()+
ggpubr::fill_palette("jco")
p1 <- insert_xaxis_grob(pmain, xdens, grid::unit(.2, "null"), position = "top")
p2<- insert_yaxis_grob(p1, ydens, grid::unit(.2, "null"), position = "right")
# ggdraw(p2)
# generate a separate bar chart to go alongside
petal.bar <- ggplot(data=iris, aes(y=Petal.Width, x=Species, fill = Species))+
geom_bar(stat="summary", fun="mean", position = "dodge")+
theme(axis.text.x = element_text(colour = "white"),
legend.position = "none")+
geom_point()+
ggpubr::fill_palette("jco")
p3 <- insert_xaxis_grob(petal.bar, grid::nullGrob(), grid::unit(.2, "null"), position = "top")
# place bar chart to the right
plot_grid(p2, NULL, p3, align = "h", axis = "b", nrow = 1, ncol = 3, rel_widths = c(1, 0.1, 0.6))
Created on 2022-01-20 by the reprex package (v2.0.1)
Related Topics
How to Flatten/Merge Overlapping Time Periods
How to Convert a Table to a Data Frame
Error in ≪My Code≫: Target of Assignment Expands to Non-Language Object
Subset Data Frame Based on Multiple Conditions
Remove Na Values from a Vector
How to Make Consistent-Width Plots in Ggplot (With Legends)
Use Variable Names in Functions of Dplyr
How to Print When Using %Dopar%
Sample from Vector of Varying Length (Including 1)
Customize Ggplot2 Axis Labels With Different Colors
Summarizing by Subgroup Percentage in R
Rename Multiple Columns by Names
Test If Characters Are in a String
How to Install Packages in Latest Version of Rstudio and R Version.3.1.1
Ggplot Legends - Change Labels, Order and Title