Tom
Tom

Reputation: 237

How to represent bipolar survey question in ggplot2 with multiple axes labels

I have data from a survey from a question of the format

| Statement A | Agree strongly w/ A| ... | Agree strongly w/ B | Statement B |
| A1          |         o          | ... |          o          | B1          |

I would like to display the means of each statement with a bar chart that has labels on either side of the bar - one on the left for statement A and one on the right for statement B, like so:

graph sketch
(source: tomvladeck.com)

I'd like to have y axis lines where you see the line under the labels "Statement A" and "Statement B", and y axis labels where you see the boxed "A1", "A2", and "B1", "B2". With ggplot when using scale_y_discrete you can only have one line (as far as I know) and can move it to the right side with position = "right", but afaik, you can't have two axis lines (even if they are the same scale).

This isn't having multiple y scales, which I know isn't natively supported by ggplot2. Technically it's having one discrete y scale, but with two sets of labels, but I don't know how to implement this in ggplot2 other than using lots of annotates. Any help here? Is this possible to do in natural ggplot?

Here is a minimal reprex:

example_df <- 
  data.frame(
    statement_a = c("I like to take risks", 
                    "I work to provide for my family"),
    statement_b = c("I am more risk averse",
                    "I work to provide for myself"),
    value = c(-1.5, .5)
  )

plot_1 <- 
  ggplot(example_df, 
         aes(x = statement_a, y = value)) + 
  geom_col() + 
  coord_flip() + 
  scale_x_discrete(name = "")

plot_2 <- 
    ggplot(example_df, 
         aes(x = statement_b, y = value)) + 
  geom_col() + 
  coord_flip() + 
  scale_x_discrete(name = "", position = "top")

Plot A looks like this: Plot A
(source: tomvladeck.com)

Plot B looks like this: Plot B
(source: tomvladeck.com)

And the idea is to show both of the axis lines (the one on the left in A, and the one on the right in B)

Upvotes: 0

Views: 311

Answers (1)

Mist
Mist

Reputation: 1948

ggplot does not support multiple y axes (unless they are both numeric and one is a scale of the other). There are numerous posts about this that you can search up for yourself. Here's a work-around that might do the trick for you.

example_df <- 
  data.frame(
    statement_a = c("I like to take risks", 
                    "I work to provide for my family"),
    statement_b = c("I am more risk averse",
                    "I work to provide for myself"),
    value = c(-1.5, .5)
  )

row_count <- nrow(example_df)
max_value <- max(abs(example_df$value))

example_df$y <- 1:row_count

library(ggplot2)

ggplot(example_df) +
  geom_rect(aes(xmin = rep(0, row_count), 
                xmax = value, 
                ymin = y-0.3, ymax = y+0.3)) +
  geom_text(aes(x = -max_value-0.2,
                y = y,
                label = statement_a),
            hjust = 1) +
  geom_text(aes(x = max_value-0.2,
                y = y,
                label = statement_b),
            hjust = 0) +
  xlim(c(-max_value-10,max_value+10)) +
  theme_void()

enter image description here

Upvotes: 1

Related Questions