Consider this data:
# A tibble: 15 x 3
group variable value
<int> <fct> <int>
1 1 1 0
2 1 2 0
3 1 3 -2
4 2 1 1
5 2 2 -2
6 2 3 1
7 3 1 -1
8 3 2 -2
9 3 3 -2
10 4 1 0
11 4 2 -1
12 4 3 2
13 5 1 0
14 5 2 1
15 5 3 -2
library(tidyverse)
df %>%
ggplot() +
aes(x = group ,weight = value) +
geom_bar(aes(y = after_stat(proportions(count)), fill = variable),
stat = "count") +
coord_flip() +
geom_hline(yintercept = 0) +
geom_text(aes(y = after_stat(proportions(count)),
label = str_c(percent(after_stat(proportions(count))),
" | ", after_stat(count))),
stat = "count")
The code yields the plot with the text at y = group proportion of the whole dataset. What I would like is the text to be above the bars, i.e above the positive values. How can I achieve this with geom_bar()
?
Dummy data:
structure(list(group = c(1L, 1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L,
4L, 4L, 4L, 5L, 5L, 5L), variable = structure(c(1L, 2L, 3L, 1L,
2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L), levels = c("1",
"2", "3"), class = "factor"), value = c(0L, 0L, -2L, 1L, -2L,
1L, -1L, -2L, -2L, 0L, -1L, 2L, 0L, 1L, -2L)), row.names = c(NA,
-15L), class = c("tbl_df", "tbl", "data.frame"))
The only option I have found to achieve your desired result would be to aggregate the data for the labels outside of the ggplot()
pipeline.
library(tidyverse)
library(scales)
df_label <- df |>
summarise(
count = sum(value),
.by = c(group, variable)
) |>
mutate(
prop = proportions(count),
prop_pos = ifelse(count < 0, prop, 0)
) |>
summarise(
label = paste0(percent(sum(prop)), " | ", sum(count)),
y = sum(prop_pos),
.by = group
)
df %>%
ggplot() +
aes(x = group, weight = value) +
geom_bar(
aes(y = after_stat(proportions(count)), fill = variable),
stat = "count"
) +
coord_flip() +
geom_hline(yintercept = 0) +
geom_text(
data = df_label,
aes(
y = y,
label = label,
weight = NULL
),
hjust = -.1
) +
scale_y_continuous(limits = c(NA, 1))