Как изменить порядок факторов на основе подмножества (аспектов) другой переменной, используя forcats?

forcats виньетка утверждает, что

Целью пакета forcats является предоставление набора полезных инструментов, которые решают общие проблемы с факторами

И действительно, одним из инструментов является переупорядочение факторов с помощью другой переменной, что является очень распространенным случаем использования при построении данных. Я пытался использовать forcats чтобы достичь этого, но в случае граненого заговора. То есть я хочу переупорядочить фактор с помощью другой переменной, но используя только подмножество данных. Вот представитель:

library(tidyverse)

ggplot2::diamonds %>% 
    group_by(cut, clarity) %>% 
    summarise(value = mean(table, na.rm = TRUE)) %>%
    ggplot(aes(x = clarity, y = value, color = clarity)) + 
    geom_segment(aes(xend = clarity, y = min(value), yend = value), 
                 size = 1.5, alpha = 0.5) + 
    geom_point(size = 3) + 
    facet_grid(rows = "cut", scales = "free") +
    coord_flip() +
    theme(legend.position = "none")

Этот код производит сюжет, близкий к тому, что я хочу:

Но я хочу, чтобы ось ясности была отсортирована по значению, чтобы я мог быстро определить, какая ясность имеет наибольшее значение. Но тогда каждый аспект подразумевал бы другой порядок. Поэтому я бы хотел упорядочить график по значениям в пределах определенного фасета.

Прямое использование forcats Конечно, в этом случае не работает, потому что он будет переупорядочивать фактор на основе всех значений, а не только значений конкретного фасета. Давай сделаем это:

# Inserting this line right before the ggplot call
mutate(clarity = forcats::fct_reorder(clarity, value)) %>%

Затем он производит этот сюжет.

Конечно, он переупорядочил коэффициент на основе целых данных, но что если я хочу, чтобы график упорядочился по значениям "идеального" среза?, Как я могу сделать это с forcats?

Мое текущее решение будет следующим:

ggdf <- ggplot2::diamonds %>% 
    group_by(cut, clarity) %>% 
    summarise(value = mean(table, na.rm = TRUE))

# The trick would be to create an auxiliary factor using only
# the subset of the data I want, and then use the levels
# to reorder the factor in the entire dataset.
#
# Note that I use good-old reorder, and not the forcats version
# which I could have, but better this way to emphasize that
# so far I haven't found the advantage of using forcats 
reordered_factor <- reorder(ggdf$clarity[ggdf$cut == "Ideal"], 
                            ggdf$value[ggdf$cut == "Ideal"])

ggdf$clarity <- factor(ggdf$clarity, levels = levels(reordered_factor))

ggdf %>%
    ggplot(aes(x = clarity, y = value, color = clarity)) + 
    geom_segment(aes(xend = clarity, y = min(value), yend = value), 
                 size = 1.5, alpha = 0.5) + 
    geom_point(size = 3) + 
    facet_grid(rows = "cut", scales = "free") +
    coord_flip() +
    theme(legend.position = "none")

Который производит то, что я хочу.

Но мне интересно, есть ли более элегантный / умный способ сделать это, используя forcats,

1 ответ

Решение

Если вы хотите изменить порядок clarity по значениям конкретного аспекта вы должны сказать forcats::fct_reorder() сделать это, например,

mutate(clarity = forcats::fct_reorder(
    clarity, filter(., cut == "Ideal") %>% pull(value)))

который использует только значения для "идеального" фасета для переупорядочения.

Таким образом,

ggplot2::diamonds %>% 
  group_by(cut, clarity) %>% 
  summarise(value = mean(table, na.rm = TRUE)) %>%
  mutate(clarity = forcats::fct_reorder(
    clarity, filter(., cut == "Ideal") %>% pull(value))) %>%
  ggplot(aes(x = clarity, y = value, color = clarity)) + 
  geom_segment(aes(xend = clarity, y = min(value), yend = value), 
               size = 1.5, alpha = 0.5) + 
  geom_point(size = 3) + 
  facet_grid(rows = "cut", scales = "free") +
  coord_flip() +
  theme(legend.position = "none")

создает

ht tps://stackru.com/images/5e36a6f45f2ec35a95f9b10deb7632c9180d4d40.png

как просили.

Другие вопросы по тегам