ggplot2: добавить метку на гистограмму, если position = fill

Я хотел бы добавить %-числа на заполненный гистограмму. Вот график с метками в неправильных местах:

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

Вот кадр данных:

x0 <- expand.grid(grp    = c("G1","G2")
                 , treat = c("T1","T2")
                 , out   = c("out1","out2","out3","out4")
)
set.seed(1234)
x0$n <- round(runif(16,0,1)*100,0)
head(x0)
  grp treat  out  n
1  G1    T1 out1 11
2  G2    T1 out1 62
3  G1    T2 out1 61
4  G2    T2 out1 62
5  G1    T1 out2 86
6  G2    T1 out2 64

Теперь я добавляю сумму в grp/treat к кадру данных (используя sql, извините!):

x0 <- sqldf(paste("SELECT a.*, (SELECT SUM(n)"
                  ,"            FROM x0 b"
                  ,"            WHERE a.grp = b.grp"
                  ,"                  AND a.treat = b.treat"
                  ,"           ) tot"
                  ," FROM x0 a"
                  ," ORDER BY a.grp,a.treat,a.out"
                  )
            )
x0$p <- with(x0, n/tot)
x0$p2 <- with(x0, paste(formatC(p*100, digits=2
              , format="fg"),"%",sep=""))
head(x0)
  grp treat  out  n tot          p    p2
1  G1    T1 out1 11 192 0.05729167  5.7%
2  G1    T1 out2 86 192 0.44791667   45%
3  G1    T1 out3 67 192 0.34895833   35%
4  G1    T1 out4 28 192 0.14583333   15%
5  G1    T2 out1 61 160 0.38125000   38%
6  G1    T2 out2  1 160 0.00625000 0.62%

И вот как я понимаю сюжет:

ggplot(x0, aes(grp, weight=n)) +
         geom_bar(aes(fill = out), position = "fill") +
         facet_grid(.~treat) +
         scale_y_continuous(labels=percent) +
         geom_text(aes(label=p2, y=p))

Я мог бы добавить новую переменную в фрейм данных с кумулятивным процентом, но мне интересно, есть ли более простой способ добавить метки.


person giordano    schedule 25.05.2016    source источник
comment
Этот вопрос/ответ показывает решения, которые я видели чаще всего. Использование position = "stack" в geom_text или создание новой переменной для положения по оси Y.   -  person aosmith    schedule 25.05.2016
comment
@aosmith Спасибо. Добавление position = "stack" дает то же самое. Я просмотрел другие SO-записи по этой проблеме (например, вашу ссылку). Основное отличие в том, что я использую опцию position = "fill" в geom_bar().   -  person giordano    schedule 26.05.2016
comment
Вы добавили position = "stack" к geom_text (не geom_bar)? Этот вариант отлично работает для меня, если я добавлю его в ваш код. Вы можете обнаружить, что вам нужно что-то сделать с очень маленькими процентами. Что-то вроде label = ifelse(p < .05, NA, p2) может быть достаточно.   -  person aosmith    schedule 26.05.2016
comment
Я ошибочно поместил его в aes() из geom_text. Теперь это работает. Большое спасибо. Если вы напишите свой ответ в поле ответа, я могу проголосовать за него.   -  person giordano    schedule 26.05.2016
comment
Интересно: это дает правильное решение только в том случае, если out отсортировано по возрастанию.   -  person giordano    schedule 26.05.2016
comment
Это звучит правильно, поскольку я считаю, что position = "stack" зависит от порядка набора данных в новейших версиях ggplot2 (см. здесь).   -  person aosmith    schedule 26.05.2016


Ответы (1)


Чтобы не создавать значения позиций самостоятельно, вы можете использовать position = "stack" в geom_text, как в этот вопрос. Как вы отметили в комментариях, набор данных должен быть упорядочен по переменной fill, чтобы получить стеки в правильном порядке, чтобы соответствовать стекам столбцов.

ggplot(x0, aes(grp, weight = n)) +
    geom_bar(aes(fill = out), position = "fill") +
    facet_grid(.~treat) +
    scale_y_continuous(labels=percent) +
    geom_text(aes(label = p2, y=p), position = "stack")

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

В конечном итоге вам может понадобиться удалить метки ниже определенного размера, чтобы удалить перекрытие, показанное на графике выше. Что-то вроде geom_text(aes(label = ifelse(p < .05, NA, p2), y = p), position = "stack") удалит метки для очень маленьких значений.

person aosmith    schedule 26.05.2016