简体   繁体   中英

Legend for combined graph

I am trying to reproduce this figure (without the Portugal highlight): 在此处输入图像描述

The data (and figure) can be found in this link: https://stat.link/uz49al .

I imported and reshaped the data into a long format, but then I got stuck on how it would be possible to rearrange the legend entries in the same order as in the original.

I would very much appreciate your help!

Thanks!

Here is where I got:

# load data
f5_5_data_before <-
  read_excel("uz49al.xlsx", sheet = "Figure1.20", range = "A32:E68")
names(f5_5_data_before)[1] <- "Country"
names(f5_5_data_before)[2] <- "Odds_ratio"
names(f5_5_data_before)[3] <- "SE"
names(f5_5_data_before)[4] <- "sig"
names(f5_5_data_before)[5] <- "non_sig"
f5_5_data_before$Country <- as.factor(f5_5_data_before$Country)

f5_5_data_before <- f5_5_data_before %>%
  mutate(
    category = case_when(
      is.na(sig) ~ "Non-significant",
      !is.na(sig) ~ "Significant"
    ),
    value = case_when(
      category == "Non-significant" ~ non_sig,
      category == "Significant" ~ sig
    )
  )
f5_5_data_before$group2 <- "Before accounting for reading performance"

f5_5_data_after <-
  read_excel("uz49al.xlsx", sheet = "Figure1.20", range = "A32:I68")
f5_5_data_after <- f5_5_data_after[, c(1, 6:9)]
names(f5_5_data_after)[1] <- "Country"
names(f5_5_data_after)[2] <- "Odds_ratio"
names(f5_5_data_after)[3] <- "SE"
names(f5_5_data_after)[4] <- "sig"
names(f5_5_data_after)[5] <- "non_sig"
f5_5_data_after$Country <- as.factor(f5_5_data_after$Country)

f5_5_data_after <- f5_5_data_after %>%
  mutate(
    category = case_when(
      is.na(sig) ~ "Non-significant",
      !is.na(sig) ~ "Significant"
    ),
    value = case_when(
      category == "Non-significant" ~ non_sig,
      category == "Significant" ~ sig
    )
  )
f5_5_data_after$group2 <- "After accounting for reading performance"

# appending in long format
f5_5_data <- rbind(f5_5_data_after, f5_5_data_before)

# shaded rectangle
rect1 <- data.frame(
  xmin = 14.5,
  xmax = 15.5,
  ymin = -Inf,
  ymax = Inf
)

# figure
f5_5 <- ggplot() +
  geom_col(data = f5_5_data %>% filter(group2 == "After accounting for reading performance"),
           aes(x = reorder(Country,-Odds_ratio),
               y = value,
               fill = category,
               colour = group2),
           width=0.5,
  ) +
  geom_point(
    data = f5_5_data %>% filter(group2 == "Before accounting for reading performance"),
    aes(x = Country,
        y = value,
        fill = category,
        colour = group2),
    shape = 23,
    size = 3,
  ) +
  geom_rect(
    data = rect1,
    aes(
      xmin = xmin,
      xmax = xmax,
      ymin = ymin,
      ymax = ymax
    ),
    alpha = 0.5,
    inherit.aes = FALSE
  ) +
  scale_y_continuous(breaks = pretty_breaks(),
                     limits = c(0, 25),
                     expand = c(0, 0)) +
  labs(x = NULL,
       y = "Odds ratio") +
theme(axis.text.x = element_text(angle = 90))
print(f5_5)

This yields the following output: 在此处输入图像描述

As you can see, the legend looks substantially different and essentially I got stuck.

One option to achieve your desired result would be via the ggnewscale package which allows for multiple scales for the same aesthetic. Doing so we could map category on the fill aes in both the geom_col and the geom_point but have two different legends:

Note: I simplified your data wrangling code a bit.

library(readxl)
library(dplyr)
library(ggplot2)
library(ggnewscale)

url <- "https://stat.link/uz49al"
download.file(url, destfile = "uz49al.xlsx")

dat <- read_excel("uz49al.xlsx", sheet = "Figure1.20", range = "A32:I68")
dat <- list(
  before = setNames(dat[, 1:5], c("Country", "Odds_ratio", "SE", "sig", "non_sig")),
  after = setNames(dat[, c(1, 6:9)], c("Country", "Odds_ratio", "SE", "sig", "non_sig"))
) %>%
  bind_rows(.id = "group2") 

dat <- dat %>%
  mutate(
    category = if_else(is.na(sig), "nonsig", "sig"),
    value = if_else(is.na(sig), non_sig, sig)
  ) %>%
  select(-sig, -non_sig)

group2_labels <- c(after = "After accounting for reading performance", before = "Before accounting for reading performance")

rect1 <- data.frame(xmin = 14.5, xmax = 15.5,  ymin = -Inf, ymax = Inf)

ggplot(dat, aes(x = reorder(Country,-Odds_ratio), y = value)) +
  geom_col(data = ~filter(.x, group2 == "after"), aes(fill = category), width = 0.5) +
  scale_fill_manual(labels = NULL, values = c(sig = "darkblue", nonsig = "steelblue"), 
                    name = group2_labels[["after"]], guide = guide_legend(title.position = "right")) +
  new_scale_fill() +
  geom_point(data = ~filter(.x, group2 == "before"), aes(fill = category), size = 3, shape = 23, color = "lightblue") +
  geom_rect(data = rect1, aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax),
            alpha = 0.5, inherit.aes = FALSE) +
  scale_fill_manual(labels = NULL, values = c(nonsig = "white", sig = "lightblue"), breaks = c("sig", "nonsig"),
                    name = group2_labels[["before"]], guide = guide_legend(title.position = "right")) +
  scale_y_continuous(breaks = scales::pretty_breaks(), limits = c(0, 25), expand = c(0, 0)) +
  labs(x = NULL, y = "Odds ratio") +
  theme(axis.text.x = element_text(angle = 90, hjust = 1),
        legend.position = "top")

在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM