i have a data frame in R called df and looks like this:
df
# A tibble: 15 × 3
# Groups: var1 [3]
var1 var2 per
<chr> <fct> <dbl>
1 My own "Very \n Dissatisfied" 0.00751
2 My own "Dissatisfied" 0.0641
3 My own "Neutral" 0.353
4 My own "Satisfied" 0.384
5 My own "Very \n Satisfied" 0.192
6 No "Very \n Dissatisfied" 0.0445
7 No "Dissatisfied" 0.135
8 No "Neutral" 0.417
9 No "Satisfied" 0.273
10 No "Very \n Satisfied" 0.130
11 Yes "Very \n Dissatisfied" 0.0233
12 Yes "Dissatisfied" 0.0639
13 Yes "Neutral" 0.280
14 Yes "Satisfied" 0.340
15 Yes "Very \n Satisfied" 0.293
i want to plot it like the picture below but i want inside each plot to automatically adjust the percentages in the middle of each bar. But here are overlapping .
ggplot(df,aes(x=var1,y=per,fill=var2))+
geom_col(position = position_fill(reverse = TRUE))+
theme(axis.title.y=element_blank(),axis.title.x=element_blank())+
coord_flip()+
scale_fill_brewer(palette ="RdYlGn",direction = 1,type="div")+
theme(axis.text.y=element_text(size=12, angle=0,hjust=0,vjust=0))+
theme(axis.text.x=element_text(size=12, angle=0,hjust=0,vjust=0)) +
theme(legend.text=element_text(size = 15),
legend.title = element_blank() )+
scale_y_continuous(labels = scales::percent)+
geom_text(aes(label = scales::percent(round(per,2))), position = position_stack(reverse = TRUE, vjust = .5))
How can i do it in R ?
Data
structure(list(var1 = c("My own", "My own", "My own", "My own",
"My own", "No", "No", "No", "No", "No", "Yes", "Yes", "Yes",
"Yes", "Yes"), var2 = structure(c(1L, 2L, 3L, 4L, 5L, 1L, 2L,
3L, 4L, 5L, 1L, 2L, 3L, 4L, 5L), levels = c("Very \n Dissatisfied",
"Dissatisfied", "Neutral", "Satisfied", "Very \n Satisfied"), class = "factor"),
per = c(0.00751285092922104, 0.0640569395017794, 0.352708580466588,
0.383550810597074, 0.192170818505338, 0.0445205479452055,
0.134703196347032, 0.417237442922374, 0.273401826484018,
0.13013698630137, 0.0233160621761658, 0.0639032815198618,
0.27979274611399, 0.340241796200345, 0.292746113989637)), class = c("grouped_df",
"tbl_df", "tbl", "data.frame"), row.names = c(NA, -15L), groups = structure(list(
var1 = c("My own", "No", "Yes"), .rows = structure(list(1:5,
6:10, 11:15), ptype = integer(0), class = c("vctrs_list_of",
"vctrs_vctr", "list"))), class = c("tbl_df", "tbl", "data.frame"
), row.names = c(NA, -3L), .drop = TRUE))
I think it is better to move overplotting labels to different heights. I don't know a quick way of using position_dodge
nicely, so I suggest a more manual approach.
library(ggplot2)
library(dplyr)
df <- df |> group_by(var1) |> mutate(cper = cumsum(per) - per/2)
ggplot(df,aes(x=var1,y=per,fill=var2, group = var2))+
geom_col(position = position_fill(reverse = TRUE))+
theme(axis.title.y=element_blank(),axis.title.x=element_blank())+
coord_flip()+
scale_fill_brewer(palette ="RdYlGn",direction = 1,type="div")+
theme(axis.text.y=element_text(size=12, angle=0,hjust=0,vjust=0))+
theme(axis.text.x=element_text(size=12, angle=0,hjust=0,vjust=0)) +
theme(legend.text=element_text(size = 15),
legend.title = element_blank() )+
scale_y_continuous(labels = scales::percent)+
geom_text(data = df[df$var2 != "Very \n Dissatisfied",],
aes(y = cper, label = scales::percent(round(per,2)))) +
geom_label(data = df[df$var2 == "Very \n Dissatisfied",],
aes(y = cper, label = scales::percent(round(per,2))),
nudge_x = 0.15, show.legend = FALSE)