Вопрос: Размещение меток между полосками в ggplot2


Используя diamonds набор данных в ggplot2 пакета, я могу создать следующую диаграмму.

library(ggplot2)
library(dplyr)

diamond.summary <- 
  diamonds %>%
  mutate(carat = ifelse(runif(nrow(.)) < 0.05, NA_real_, carat)) %>%
  group_by(carat_quintile = ntile(carat, 5)) %>%
  summarise(avg_price = mean(price))

diamond.summary %>%
  filter(!is.na(carat_quintile)) %>%
  ggplot(aes(carat_quintile, avg_price)) + 
  geom_bar(stat = "identity", 
           color = "black",
           width = 1) + 
  scale_x_continuous("Carat percentile",
                     breaks = 1:6 - 0.5,
                     labels = seq(0,100, by = 20)) + 
  scale_y_continuous(expand = c(0,0),
                     limits = c(0, 1.1* max(diamond.summary$avg_price)))

enter image description here

Пока что так просто. Тем не менее, я также хотел бы отобразить среднюю цену недостающих записей вместе с графиком. Аналогично следующему: enter image description here

diamond.summary %>%
  mutate(Facet = is.na(carat_quintile),
         carat_quintile_noNA = ifelse(Facet, "Unknown", carat_quintile)) %>%
  ggplot(aes(x = carat_quintile_noNA, y = avg_price, fill = Facet)) + 
  geom_bar(stat = "identity") + 
  facet_grid(~Facet, scales = "free_x", space = "free_x") + 
  scale_x_discrete(breaks = (0:6) - 0.5)

Однако, когда я пытаюсь выполнить тот же трюк, используя scale_x_continuous, Я получаю ошибку Discrete value supplied to continuous scale, Когда я пытаюсь использовать scale_x_discrete(breaks = c(0:6 + 0.5)) например, галочки оси и метки исчезают.

Мой вопрос: как я могу получить одну и ту же гранскую диаграмму выше с отметками на первой панели, размещенной на первом графике в этом сообщении? Совет по дизайну диаграммы может быть приемлемым решением, но я не думаю, что все такие проблемы разрешимы с редизайном.


4


источник


Ответы:


Трюк состоит в том, чтобы преобразовать ваш коэффициент в числовое, присвоив магическое число неизвестной величине. ( ggplot2 не будет отображать полосы с истинным NA значения.) Затем используйте scale_x_continuous

diamond.summary %>%
  mutate(Facet = is.na(carat_quintile),
         carat_quintile_noNA = ifelse(Facet, "Unknown", carat_quintile),
         ## 
         ## 99 is a magic number.  For our plot, it just has
         ## to be larger than 5. The value 6 would be a natural
         ## choice, but this means that the x tick marks would 
         ## overflow ino the 'unknown' facet.  You could choose
         ## choose 7 to avoid this, but any large number works.  
         ## I used 99 to make it clear that it's magic.
         numeric = ifelse(Facet, 99, carat_quintile)) %>%

  ggplot(aes(x = numeric, y = avg_price, fill = Facet)) + 
  geom_bar(stat = "identity", width = 1) + 
  facet_grid(~Facet, scales = "free_x", space = "free_x") + 
  scale_x_continuous(breaks = c(0:5 + 0.5, 99),
                     labels = c(paste0(c(0:5) * 20, "%"), "Unknown"))

enter image description here


4



Одним из решений является подход немного по-другому и брусья  вместо тиков, используя position_nudge,

library(ggplot2)
library(dplyr)

diamond.summary <- 
  diamonds %>%
  mutate(carat = ifelse(runif(nrow(.)) < 0.05, NA_real_, carat)) %>%
  group_by(carat_quintile = ntile(carat, 5)) %>%
  summarise(avg_price = mean(price))

# nudge bars to the left
diamond.summary %>%
  filter(!is.na(carat_quintile)) %>%
  ggplot(aes(carat_quintile, avg_price)) + 
  geom_bar(stat = "identity", 
           color = "black",
           width = 1,
           position=position_nudge((x=-1))) + 
  scale_x_continuous("Carat percentile",
                     breaks = 1:6 - 0.5,
                     labels = seq(0,100, by = 20)) + 
  scale_y_continuous(expand = c(0,0),
                     limits = c(0, 1.1* max(diamond.summary$avg_price)))

nudge bars left

# nudge bars to the right
diamond.summary %>%
  filter(!is.na(carat_quintile)) %>%
  ggplot(aes(carat_quintile, avg_price)) + 
  geom_bar(stat = "identity", 
           color = "black",
           width = 1,
           position=position_nudge((x=1))) + 
  scale_x_continuous("Carat percentile",
                     breaks = 1:6 - 0.5,
                     labels = seq(0,100, by = 20)) + 
  scale_y_continuous(expand = c(0,0),
                     limits = c(0, 1.1* max(diamond.summary$avg_price)))

nudge bars right


0