Faceted Piechart with Ggplot2

faceted piechart with ggplot

One way is to calculate the percentage/ratio beforehand and then use it to get the position of the text label. See also how to put percentage label in ggplot when geom_text is not suitable?

# Your data
y = data.frame(category=c(1,1,1,1,2,2,2,2), value=c(2,2,1,1,2,2,2,1))

# get counts and melt it
data.m = melt(table(y))
names(data.m)[3] = "count"

# calculate percentage:
m1 = ddply(data.m, .(category), summarize, ratio=count/sum(count))

#order data frame (needed to comply with percentage column):
m2 = data.m[order(data.m$category),]

# combine them:
mydf = data.frame(m2,ratio=m1$ratio)

# get positions of percentage labels:
mydf = ddply(mydf, .(category), transform, position = cumsum(count) - 0.5*count)

# create bar plot
pie = ggplot(mydf, aes(x = factor(1), y = count, fill = as.factor(value))) +
geom_bar(stat = "identity", width = 1) +
facet_wrap(~category)

# make a pie
pie = pie + coord_polar(theta = "y")

# add labels
pie + geom_text(aes(label = sprintf("%1.2f%%", 100*ratio), y = position))

Sample Image

R - pie chart in facet

Something like will work. You just have to change how your data is formatted and use ggplot2 which is in the tidyverse.

library(tidyverse)

df1 <- expand_grid(pie = 1:4, labels = c("monthly", "daily", "weekly"))
df2 <- tibble(slices = c(39, 7, 13,
40, 5, 12,
15, 27, 47,
58, 47, 2))

# join the data
df <- bind_cols(df1, df2) %>%
group_by(pie) %>%
mutate(pct = slices/sum(slices)*100) # pct for the pie - adds to 100

# graph
ggplot(df, aes(x="", y=pct, fill=labels)) + # pct used here so slices add to 100
geom_bar(stat="identity", width=1) +
coord_polar("y", start=0) +
geom_text(aes(label = slices), position = position_stack(vjust=0.5)) +
facet_wrap(~pie, ncol = 2) +
theme_void() +
theme(legend.position = "bottom")

Sample Image

Using an edited version of your data

> df
# A tibble: 12 x 4
# Groups: pie [4]
pie labels slices pct
<int> <chr> <dbl> <dbl>
1 1 monthly 39 66
2 1 daily 7 12
3 1 weekly 13 22
4 2 monthly 40 70
5 2 daily 5 9
6 2 weekly 12 21
7 3 monthly 15 17
8 3 daily 27 30
9 3 weekly 47 53
10 4 monthly 58 54
11 4 daily 47 44
12 4 weekly 2 2

faceted piechart with ggplot2

I think you just want position = 'fill':

ggplot(mtcars,aes(x = factor(1),fill=factor(cyl))) + 
facet_wrap(~gear) +
geom_bar(width = 1,position = "fill") +
coord_polar(theta="y")

For future reference, from the Details section of geom_bar:

By default, multiple x's occuring in the same place will be stacked a
top one another by position_stack. If you want them to be dodged from
side-to-side, see position_dodge. Finally, position_fill shows
relative propotions at each x by stacking the bars and then stretching
or squashing to the same height.

How to make faceted pie charts for a dataframe of percentages in R?

After commentators suggestion, aes(x=1) in the ggplot() line solves the issue and makes normal circle parallel pies:

ggplot(melted_df, aes(x=1, y=Share, fill=Source)) +
geom_col(width=1,position="fill", color = "black")+
coord_polar("y", start=0) +
geom_text(aes(x = 1.7, label = paste0(round(Share*100), "%")), size=2,
position = position_stack(vjust = 0.5))+
labs(x = NULL, y = NULL, fill = NULL, title = "Energy Mix")+
theme_classic() + theme(axis.line = element_blank(),
axis.text = element_blank(),
axis.ticks = element_blank(),
plot.title = element_text(hjust = 0.5, color = "#666666"))+
facet_wrap(~Year)

How to enhance faceted pie charts labels in R?

Pie charts are basically stacked bar charts - thus you can apply the same rules. Comments in the code.

library(ggplot2)
Year<-c("2016","2016","2016","2017","2017","2017","2018","2018","2018")
Source<-c("coal","hydro","solar","coal","hydro","solar","coal","hydro","solar")
Share<-c(0.5,0.25,0.25,0.4,0.15,0.45,0.7,0.1,0.2)

## don't do that cbind stuff
df<-data.frame(Year,Source,Share)

ggplot(df, aes(x=1, y=Share, fill=Source)) +
## geom_col is geom_bar(stat = "identity")(bit shorter)
## use color = black for the outline
geom_col(width=1,position="fill", color = "black")+
coord_polar("y", start=0) +
## the "radial" position is defined by x = play around with the values
## the position along the circumference is defined by y, akin to
## centering labels in stacked bar charts - you can center the
## label with the position argument
geom_text(aes(x = 1.7, label = paste0(round(Share*100), "%")), size=2,
position = position_stack(vjust = 0.5))+
labs(x = NULL, y = NULL, fill = NULL, title = "Energy Mix")+
theme_classic() + theme(axis.line = element_blank(),
axis.text = element_blank(),
axis.ticks = element_blank(),
plot.title = element_text(hjust = 0.5, color = "#666666"))+
facet_wrap(~Year)

Sample Image

Created on 2021-12-19 by the reprex package (v2.0.1)

ggplot, facet, piechart: placing text in the middle of pie chart slices

NEW ANSWER: With the introduction of ggplot2 v2.2.0, position_stack() can be used to position the labels without the need to calculate a position variable first. The following code will give you the same result as the old answer:

ggplot(data = dat, aes(x = "", y = Cnt, fill = Volume)) + 
geom_bar(stat = "identity") +
geom_text(aes(label = Cnt), position = position_stack(vjust = 0.5)) +
coord_polar(theta = "y") +
facet_grid(Channel ~ ., scales = "free")

To remove "hollow" center, adapt the code to:

ggplot(data = dat, aes(x = 0, y = Cnt, fill = Volume)) + 
geom_bar(stat = "identity") +
geom_text(aes(label = Cnt), position = position_stack(vjust = 0.5)) +
scale_x_continuous(expand = c(0,0)) +
coord_polar(theta = "y") +
facet_grid(Channel ~ ., scales = "free")

OLD ANSWER: The solution to this problem is creating a position variable, which can be done quite easily with base R or with the data.table, plyr or dplyr packages:

Step 1: Creating the position variable for each Channel

# with base R
dat$pos <- with(dat, ave(Cnt, Channel, FUN = function(x) cumsum(x) - 0.5*x))

# with the data.table package
library(data.table)
setDT(dat)
dat <- dat[, pos:=cumsum(Cnt)-0.5*Cnt, by="Channel"]

# with the plyr package
library(plyr)
dat <- ddply(dat, .(Channel), transform, pos=cumsum(Cnt)-0.5*Cnt)

# with the dplyr package
library(dplyr)
dat <- dat %>% group_by(Channel) %>% mutate(pos=cumsum(Cnt)-0.5*Cnt)

Step 2: Creating the facetted plot

library(ggplot2)
ggplot(data = dat) +
geom_bar(aes(x = "", y = Cnt, fill = Volume), stat = "identity") +
geom_text(aes(x = "", y = pos, label = Cnt)) +
coord_polar(theta = "y") +
facet_grid(Channel ~ ., scales = "free")

The result:

Sample Image

how to plot faceted pie chart in ggplot

ggplot(data = test, aes(x = "", y = Count, fill = Area)) + 
geom_bar(stat = "identity") +
geom_text(aes(label = Count), position = position_stack(vjust = 0.5)) +
coord_polar(theta = "y") +
facet_grid(Equipment ~ ., scales = "free")

Sample Image



Related Topics



Leave a reply



Submit