Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feature request] geom_subplot #147

Open
mkoohafkan opened this issue Jun 7, 2019 · 4 comments
Open

[feature request] geom_subplot #147

mkoohafkan opened this issue Jun 7, 2019 · 4 comments
Labels
feature a feature request or enhancement

Comments

@mkoohafkan
Copy link

mkoohafkan commented Jun 7, 2019

ggsubplot has been deprecated for years, but tidyverse support for list columns and custom annotations in ggplot2 make it pretty easy to mimic its functionality. However, there is some boilerplate logic that I could see fitting into a new geom, i.e. geom_subplot().

First, some examples on how to embed plots in a plot:

# simple example (unlikely use case -- could instead use facet_grid) 
library(dplyr)
library(purrr)
library(ggplot2)

titanic = as.data.frame(Titanic, responseName = "value") %>%
  group_nest(Class, Sex) %>%
  mutate(
    Class = factor(Class),
	Sex = factor(Sex),
	X = as.integer(Class),
	Y = as.integer(Sex),
    plot = map(data, 
	  ~ggplot(.x) + geom_col(aes(x = Survived, y = value))
	),
	annotation = pmap(list(X, Y, plot),
      ~ annotation_custom(ggplotGrob(..3),
        xmin = ..1 - 0.4, xmax = ..1 + 0.4,
        ymin = ..2 - 0.4, ymax = ..2 + 0.4))
  )
ggplot(titanic) + aes(x = Class, y = Sex) + geom_point() + pull(titanic, annotation)

plot1

# mapping example (more likely use case)
library(dplyr)
library(purrr)
library(ggplot2)
library(sf)

nc <- st_read(system.file("shape/nc.shp", package = "sf"))
data(Crime, package = "Ecdat")

ncdat = nc %>%
  st_transform(3857) %>%
  bind_cols(as_tibble(st_coordinates(st_centroid(.))))

crimedat = Crime %>% 
  group_nest(county) %>%
  inner_join(select(st_drop_geometry(ncdat), X, Y, CRESS_ID), by = c("county" = "CRESS_ID")) %>%
  mutate(
    plot = map(data, ~ggplot(.x) + aes(x = year, y = crmrte) + geom_line(color = "red") + theme_void()),
	annotation = pmap(list(X, Y, plot), ~ annotation_custom(ggplotGrob(..3),
      xmin = ..1 - 8000 , xmax = ..1 + 8000,
      ymin = ..2 - 8000 , ymax = ..2 + 8000)) 
  )
    
ggplot(ncdat) + geom_sf() + pull(crimedat, annotation)

plot2

And here's a more sophisticated example (link to blog plost with code).

plot3

I'm thinking a geom_subplot() could handle the last step of transforming a list of plots into custom annotations, replacing the final call to pmap and manual addition of the annotation list to the base plot in the above examples. In other words, the geom would take a dataframe with a list column containing ggplot objects and map them onto the "base" plot. This would provide maximum flexibility for users generating the suplots themselves and avoid a lot of the messy aesthetics that was in ggsubplot. The new geom would accept subplot locations, dimensions, and the subplots themselves (i.e. geom_subplot(aes(x, y, height, width, plot))). At the same time, the new geom could provide helper arguments to

  • ignore missing or empty subplots
  • apply standardized axis limits, font sizes, themes, and theme options
  • expand the axis limits of the base plot (since annotation_custom does not affect scales)
  • potentially assist creating a unified legends and drop legends from individual subplots
  • potentially make a good guess of reasonable subplot height and width based on the extent of base plot

I've been learning more about extending ggplot2 and would be interested in helping develop this functionality, but I don't think I have the necessary expertise to develop this on my own. I also would prefer to contribute to ggforce rather than try to maintain a separate package, since ggforce clearly has a well-developed underlying framework for developing new geoms.

@mkoohafkan
Copy link
Author

mkoohafkan commented Mar 14, 2020

I have developed a new geometry geom_subfig() and am currently hosting it in an experimental package ggsubplot2. I would be interested in contributing this to ggforce rather than maintaining a separate package if there is interest.

library(dplyr)
library(purrr)
library(ggplot2)
#  remotes::install_github("mkoohafkan/ggsubplot2")
library(ggsubplot2)
  
d1 = mtcars %>%
	group_nest(gear, cyl) %>%
	mutate(plot = map(data,
		~ ggplot(.x, aes(x = mpg)) +
			geom_density() +
			theme_bw(base_size = 4)
	))

ggplot(d1, aes(x = gear, y = cyl, plot = plot)) +
	geom_subfig(width = 0.75, height = 0.75)

image

@dlmolloy
Copy link

dlmolloy commented Apr 7, 2020

Was hoping to use this for a project, but the map function seems to crash whenever I apply it to my data. The steps creating plots for each location may need work.

@mkoohafkan
Copy link
Author

@dlmolloy post your issue (with sample data) to the ggsubplot2 issues page and I'll see if I can help. This thread is generally about integrating or developing a subplot geom in ggforce.

@thomasp85
Copy link
Owner

I have been away from the repo. Are you still interested in submitting this into ggforce?

@thomasp85 thomasp85 added the feature a feature request or enhancement label Jan 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature a feature request or enhancement
Projects
None yet
Development

No branches or pull requests

3 participants