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 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)
Unpopular opinion: if you need to add labels to make your plot understood, you may be using the wrong plot type. Ask yourself if the actual values of the categories are really important for your purpose or if the relative comparison is already enough? In the latter case you may not need any labels at all; in the former case a tabular representation of the figures serves the purpose much better.
Now to your problem at hand. You have several options:
geom_text(aes(label = scales::percent(round(per,2))), position = position_stack(reverse = TRUE, vjust = .5), angle = 90)
)plotly
and add tooltips instead of the labels (remove the geom_text
and use plotly::ggplotly(<yourplot>)
instead and you get tooltips.
geom_text(aes(label = scales::percent(round(per,2)), size = pmin(10, per*100)/.pt), position = position_stack(reverse = TRUE, vjust = .5)) + scale_size_identity()
but that looks a little silly to me. – Jon Spring Commented Nov 20, 2024 at 7:08