1

Here's some toy data.

library(tidyverse)

df <- structure(list(district = c(1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 
3), office = c("GOV", "WAG", "USS", "WST", "GOV", "WAG", "USS", 
"WST", "GOV", "WAG", "USS", "WST"), margin = c(-10.6296758104738, 
-11.0540006895039, -16.2188249213812, -15.4710156423517, -12.7093173035638, 
-12.9545865749955, -17.3703863277323, -17.4593332847035, -10.1910380671443, 
-10.984606653898, -14.8799042051138, -15.8511248029804)), row.names = c(NA, 
-12L), class = c("tbl_df", "tbl", "data.frame"))

> df
# A tibble: 12 × 3
   district office margin
      <dbl> <chr>   <dbl>
 1        1 GOV     -10.6
 2        1 WAG     -11.1
 3        1 USS     -16.2
 4        1 WST     -15.5
 5        2 GOV     -12.7
 6        2 WAG     -13.0
 7        2 USS     -17.4
 8        2 WST     -17.5
 9        3 GOV     -10.2
10        3 WAG     -11.0
11        3 USS     -14.9
12        3 WST     -15.9

I'd like to make a scatterplot of each combination of the values in the office column. I want the plots to be a grid like this:

GOV WAG USS WST
                GOV
                WAG
                USS
                WST

Here is a kludgy version of what I mean, using a custom function and the {{patchwork}} package.

facet_office <- function(xoffice){
  df %>%
    group_by(district) %>%
    mutate(x = margin[office == xoffice]) %>%
    ggplot(aes(x, margin)) +
    geom_point() +
    scale_x_continuous(name = xoffice, limits = c(min(df$margin), max(df$margin))) +
    scale_y_continuous(limits = c(min(df$margin), max(df$margin))) +
    facet_grid(rows = ~office)
}

library(patchwork)

(facet_office("GOV") / facet_office("WAG") / facet_office("USS") / facet_office("WST"))

enter image description here

I'd like to do this in one step using ggplot2::facet_grid, which requires both a row and column variable to be specified. I'd like to specify that each value in office should be both a row and a column. The grid should contain each unique combination. Does anyone have a suggestion for a better way to do this?

John J.
  • 1,450
  • 1
  • 13
  • 28

2 Answers2

3

One option would be to "expand" your dataset which (Thx to @langtang for pointing that out) could be achieved via an inner_joinso that we get a dataset with two office and two margin columns:

library(dplyr)
library(ggplot2)

df1 <- inner_join(df, df, by = "district", multiple = "all")

ggplot(df1, aes(margin.x, margin.y)) +
  geom_point() +
  facet_grid(office.x ~ office.y)

stefan
  • 90,330
  • 6
  • 25
  • 51
1

Not directly an answer to your question, but maybe more what you're after (?). It looks as if you want to plot a correlation matrix. There are some solutions for that, here one with GGally.

library(tidyverse)

df %>% 
  pivot_wider(names_from = "office", values_from = "margin") %>%
  select(-district) %>%
  GGally::ggpairs()
#> Registered S3 method overwritten by 'GGally':
#>   method from   
#>   +.gg   ggplot2

Created on 2023-04-13 with reprex v2.0.2

tjebo
  • 21,977
  • 7
  • 58
  • 94