Центрирование меток на столбцах с использованием ggplot2 и перемещение меток в верхнюю часть полосы ошибок в R

С приведенным ниже кодом

library(ggplot2)
load(url("http://murraylax.org/datasets/cps2016.RData"))

ggplot(df, aes(industry, usualhrs, fill=as.factor(sex))) +
  stat_summary(geom = "bar", fun = mean, position = "dodge", width=0.7) +
  stat_summary(geom = "errorbar", fun.data = mean_se, position = "dodge", width=0.7) + 
  stat_summary(aes(label = round(..y..,0)), fun = mean, geom = "text", size = 3, vjust = -1) +  
  xlab("Industry") + ylab("Usual Hourly Earnings") +  
  scale_x_discrete(labels = function(x) str_wrap(x, width = 12)) +
  theme(legend.position = "bottom") + 
  labs(fill = "Gender")  +
  theme_bw() 

Я создаю этот гистограмму (с планками ошибок):

Вывод

Метки центрированы по оси x, но я хотел бы, чтобы метки были центрированы на каждой полосе. Например, в первых двух тактах я хотел бы иметь 27 в центре такта «Женский» и 46 в центре такта «Мужской». Я также хотел бы переместить метки в верхнюю часть планок погрешностей.


person Thiago    schedule 22.05.2020    source источник


Ответы (1)


Добавьте position = position_dodge(width = 1)) к вызову stat_summary(aes(label...)) вне aes, чтобы переместить метки над соответствующими полосами.

Чтобы переместить метки выше планок погрешностей, я использовал geom_text с позицией y чуть выше планок погрешностей, что требовало предварительного вычисления положения планки погрешностей с помощью dplyr::summarize.

library(dplyr)
df %>% 
  group_by(industry, sex) %>% 
  summarise(usualhrs_mean = mean(usualhrs, na.rm = TRUE),
            count = n(),
            usualhrs_se = sd(usualhrs, na.rm = TRUE)/sqrt(count)) %>% 
  ggplot(aes(x = industry, y = usualhrs_mean, fill = as.factor(sex))) +
  geom_bar(stat = "identity", position = position_dodge(width = 1)) +
  geom_errorbar(aes(ymin = usualhrs_mean - usualhrs_se,
                    ymax = usualhrs_mean + usualhrs_se), 
                position = position_dodge(width = 1)) +
  geom_text(aes(label=round(..y.., 0), y = (usualhrs_mean + usualhrs_se + 0.1)), vjust = -1.5, position = position_dodge(width = 1)) +
  scale_x_discrete(
    labels = function(x)
      str_wrap(x, width = 12)
  ) +
  coord_cartesian(ylim = c(0, 55)) +
  theme(legend.position = "bottom") +
  labs(fill = "Gender",
       y = "Usual Hourly Earnings")  +
  theme_bw() 

введите здесь описание изображения

person Greg    schedule 22.05.2020
comment
Я получил следующую ошибку с вашим кодом, @Greg: Ошибка: n() следует вызывать только в контексте данных - person Thiago; 22.05.2020
comment
@Thiago - я подозреваю, что это конфликт пакета с чем-то еще, что вы загрузили. Попробуйте указать dplyr::summarize, dplyr::n и т. д. - person Greg; 22.05.2020
comment
как сохранить расстояние между полосами таким же, как на исходном графике, используя ваш код? Я имею в виду: два столбца на категорию (по оси x) вместе и столбцы между категориями дальше друг от друга? - person Thiago; 22.05.2020
comment
@Thiago измените width в position = position_dodge() на 0,7. - person Greg; 22.05.2020