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()
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()
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"))
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"))
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)
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)
Created on 2021-09-22 by the reprex package (v2.0.1)
Related Topics
Numbers as Column Names of Data Frames
Union of Intersecting Vectors in a List in R
Convert Latitude and Longitude Coordinates to Country Name in R
Check If String Contains Only Numbers or Only Characters (R)
How to Get the Cumulative Sum by Group in R
Set a Functions Environment to That of the Calling Environment (Parent.Frame) from Within Function
Empty Factors in "By" Data.Table
Remove Part of a String in Dataframe Column (R)
How to Display Emojis in Ggplot2 Using Emo Package in R
How to Get Multiple Ggplot2 Scale_Fill_Gradientn with Same Scale
Add Axis Tick-Marks on Top and to the Right to a Ggplot
Element-Wise Concatenation of String Vectors
Implementation of Standard Recycling Rules
Can 'Ddply' (Or Similar) Do a Sliding Window
How to Pass Multiple Arguments to a Function as a Single Vector