Adding Percentage Labels on Pie Chart in R

Adding percentage labels on pie chart in R

I agree with @hrbrmstr a waffle chart would be better. But to answer the original question... your problem comes from the order in which the wedges are drawn, which will default to alphabetical. As you calculate where to place the labels based on the ordering in your data frame, this works out wrong.

As a general principle of readability, do all the fancy calculations of labels and positions they go before the actual code drawing the graphic.

library(dplyr)
library(ggplot2)
library(ggmap) # for theme_nothing
df <- data.frame(value = c(52, 239, 9),
Group = c("Positive", "Negative", "Neutral")) %>%
# factor levels need to be the opposite order of the cumulative sum of the values
mutate(Group = factor(Group, levels = c("Neutral", "Negative", "Positive")),
cumulative = cumsum(value),
midpoint = cumulative - value / 2,
label = paste0(Group, " ", round(value / sum(value) * 100, 1), "%"))

ggplot(df, aes(x = 1, weight = value, fill = Group)) +
geom_bar(width = 1, position = "stack") +
coord_polar(theta = "y") +
geom_text(aes(x = 1.3, y = midpoint, label = label)) +
theme_nothing()

Sample Image

Percentage labels in pie chart with ggplot

Using mtcars as example data. Maybe this what your are looking for:

library(ggplot2)

ggplot(mtcars, aes(x = "", fill = factor(cyl))) +
geom_bar(stat= "count", width = 1, color = "white") +
geom_text(aes(label = scales::percent(..count.. / sum(..count..))), stat = "count", position = position_stack(vjust = .5)) +
coord_polar("y", start = 0, direction = -1) +
scale_fill_manual(values = c("#00BA38", "#619CFF", "#F8766D")) +
theme_void()

Sample Image

Created on 2020-05-25 by the reprex package (v0.3.0)

Add percentage (%) for a PieChart

per <- c(0.1,0.2,0.3,0.4)
labels <- c("a","b","c","d")
pie(per,labels = paste0(labels," (",round(per,digits = 3)*100,"%)"),
border="white",col = c("red","green","blue","yellow"))

Sample Image

How can I move the percentage labels outside of the pie chart in ggplot2?

It's a little bit of a hack, but you can specify the x-coordinate as slightly to the right of your normal barplot and then coord_polar will put it slightly outside when wrapping the bar graph into a pie chart. The default x-coordinate is 1, so using 1.5 places them right on the edge of the chart and 1.6 just barely outside the chart. All the code is basically the same, but note the new x=1.6 addition to the aes() call of geom_text().

ggplot(data = df, aes(x="", y=proportion, fill=HPV)) +
geom_col(color = "black") +
coord_polar("y", start=0) +
geom_text(aes(x=1.6, label=paste0(round(proportion*100), "%")),
position = position_stack(vjust=0.5)) +
theme(panel.background = element_blank(),
axis.line = element_blank(),
axis.text = element_blank(),
axis.ticks = element_blank(),
axis.title = element_blank(),
plot.title = element_text(hjust = 0.5, size = 18)) +
ggtitle("Subtypes of HPV in GDC TCGA cervical cancer (CESC)") +
scale_fill_manual(values = c("#F46698","#F36DDB","#DD6DF3","#AC6DF3","#7355FC","#5562FC","#5562FC","#55B5FC","#55C7FC","#55E8FC","#56EDEB","#93F9EF","#61F9BF","#5BEC75","#58D64B","#91D64B","#B4D64B","#D6D64B","#FFDB57"))

Pie chart with labels slightly outside pie

how can I add percentage symbol into a pie chart?

You can use the adorn_pct_formatting() function from the janitor package to format your values as percentages. The function will alter every numeric column so you'll need to isolate your percentage column prior to applying adorn_pct_formatting(). It also multiplies your values by 100 for you so you'd need to remove your formatting as well by dividing it out first. I'd recommend creating a new variable that is specifically formatted to be the label in your plot.

# library tidyverse
# library janitor

df <- df %>% # overwrites your original data object
mutate(label = percentage/100) %>% # creates the label column
select(process, label) %>% # isolates the label column for percent formatting
adorn_pct_formatting() %>% # applies the formatting to your numeric columns
bind_cols(list(lab.ypos = df$lab.ypos, # appends your other numeric columns
percentage = df$percentage))

head(df)
process label lab.ypos percentage
1 CCCCC 1.9% 0.9345794 1.8691589
2 CCCC 0.9% 2.3364486 0.9345794
3 CCC 5.0% 5.3271028 5.0467290
4 CC 1.7% 8.6915888 1.6822430
5 C 0.7% 9.9065421 0.7476636
6 BBBBBB 15.7% 18.1308411 15.7009346

You can see that you now have a new column that is specifically formatted as a label for your plot. Now you can run your original ggplot code while only replacing the label argument as follows:

ggplot(df, aes(x="", y=percentage, fill=process))+
geom_bar(stat="identity", width=1)+
coord_polar("y", start=0)+
geom_text(aes(y = lab.ypos, label = label), color = "white")

As for label placement, there is no easy way to automatically dodge the position in a dynamic way without loading another package. I'd recommend using the geom_label_repel() function from the ggrepel package rather than geom_text().

library(ggrepel)

ggplot(df, aes(x="", y=percentage, fill=process))+
geom_bar(stat="identity", width=1)+
coord_polar("y", start=0)+
geom_label_repel(aes(label = label, y = lab.ypos), nudge_x = .5)

Without the nudge_x argument, the labels will remain inside the bounds of the pie chart. You can alter the value of nudge_x to change how far the labels are "nudged" outside of the chart.

Adding values and percentages to pie chart

This is super-straightforward with the ggstatsplot package function ggpiestats (https://cran.r-project.org/web/packages/ggstatsplot/vignettes/ggpiestats.html):

# data
simuldata <- data.frame(Category = LETTERS[1:3],
value = c(196, 149, 127))

# plot
ggstatsplot::ggpiestats(data = simuldata,
main = Category,
counts = value)

Sample Image

Created on 2018-10-11 by the reprex package (v0.2.1)

Pie chart in ggplot2 and percentages

Use just sum to count both genders. Example: percent(1000 / sum(df$value)) will return "4%".

library(tidyverse)
library(scales)
#>
#> Attaching package: 'scales'
#> The following object is masked from 'package:purrr':
#>
#> discard
#> The following object is masked from 'package:readr':
#>
#> col_factor

df <- data.frame(
group = c("Male", "Female"),
value = c(15000, 10000)
)
df
#> group value
#> 1 Male 15000
#> 2 Female 10000

ggplot(df, aes(x = "", y = value, fill = group)) +
geom_bar(width = 1, stat = "identity") +
coord_polar("y", start = 0) +
scale_fill_brewer("Blues") +
theme_void() +
geom_text(aes(
y = value / 2 + c(0, cumsum(value)[-length(value)]),
label = percent(value / sum(value))
), size = 5)

Sample Image

Created on 2021-09-22 by the reprex package (v2.0.1)



Related Topics



Leave a reply



Submit