Percentage on Y Lab in a Faceted Ggplot Barchart

percentage on y lab in a faceted ggplot barchart?

Try this:

# first make a dataframe with frequencies
df <- as.data.frame(with(test, table(test1,test2)))
# or with count() from plyr package as Hadley suggested
df <- count(test, vars=c('test1', 'test2'))
# next: compute percentages per group
df <- ddply(df, .(test1), transform, p = Freq/sum(Freq))
# and plot
ggplot(df, aes(test2, p))+geom_bar()+facet_grid(~test1)

alt text

You could also add + scale_y_continuous(formatter = "percent") to the plot for ggplot2 version 0.8.9, or + scale_y_continuous(labels = percent_format()) for version 0.9.0.

Label percentage in faceted filled barplot in ggplot2

I managed to do it, but it's not pretty.

I still think the best way is to pre-process the data before plotting.

mtcars %>% 
ggplot(aes(x = factor(gear) %>% droplevels(), fill = factor(am))) +
facet_grid(
cols = vars(cyl), scales = "free_x", space = "free_x", margins = TRUE
) +
geom_bar(position = "fill") +
geom_text(
aes(label = unlist(tapply(..count.., list(..x.., ..PANEL..),
function(a) paste(round(100*a/sum(a), 2), '%'))),

y = ..count.. ), stat = "count",
position = position_fill(vjust = .5)
)

The general idea is that you have to do the tapply on the counts based on ..x.. and ..PANEL.. (in that order), which generates vectors of counts for each bar. You then generate the labels per bar from that vector by getting the percentage, rounding or whatever you need.
Finally, you have to unlist the tapply results so that ggplot takes it like a given vector of labels.

This outputs the following plot :

Sample Image

R: Faceted bar chart with percentages labels independent for each plot

This method for the time being works. However the PANEL variable isn't documented and according to Hadley shouldn't be used.
It seems the "correct" way it to aggregate the data and then plotting, there are many examples of this in SO.

ggplot(df, aes(x = factor_variable, y = (..count..)/ sapply(PANEL, FUN=function(x) sum(count[PANEL == x])))) +
geom_bar(fill = "deepskyblue3", width=.5) +
stat_bin(geom = "text",
aes(label = paste(round((..count..)/ sapply(PANEL, FUN=function(x) sum(count[PANEL == x])) * 100), "%")),
vjust = -1, color = "grey30", size = 6) +
facet_grid(. ~ second_factor_variable)

Sample Image

How to add percentages to bar chart facets in ggplot2 in R?

You can always transform your data to calculate what you want prior to plotting it. I added some tweaks as well (labels at the top of the bar, string wrapping on the x-axis, axis limits and labels).

library(dplyr)
library(ggplot2)
library(stringr)

plot_data <- df %>%
group_by(URBRURAL, DEGREE) %>%
tally %>%
mutate(percent = n/sum(n))

ggplot(plot_data, aes(x = DEGREE, y = percent)) +
geom_bar(stat = "identity") +
geom_text(aes(label = percent(percent)), vjust = -0.5) +
labs(title = "Degree by Urban/Rural", y = "Percent", x = "DEGREE") +
scale_y_continuous(labels = percent, limits = c(0,1)) +
scale_x_discrete(labels = function(x) str_wrap(x, 10)) +
facet_wrap(~URBRURAL)

R Sample Image 30

Percentage labels for a stacked ggplot barplot with groups and facets

The easiest way would be to transform your data beforehand so that the fractions can be used directly.

library(tidyverse)
library(scales)

# Assume df is as in example code
df <- df %>% group_by(Village, livestock) %>%
mutate(frac = Freq / sum(Freq))

ggplot(df, aes(livestock, frac, fill = dose)) +
geom_col() +
geom_text(
aes(label = percent(frac)),
position = position_fill(0.5)
) +
facet_wrap(~ Village)

Sample Image

If you insist on not pre-transforming the data, you can write yourself a little helper function.

bygroup <- function(x, group, fun = sum, ...) {
splitted <- split(x, group)
funned <- lapply(splitted, fun, ...)
funned <- mapply(function(x, y) {
rep(x, length(y))
}, x = funned, y = splitted)
unsplit(funned, group)
}

Which you can then use by setting the group to x and the (undocumented) PANEL column.

library(ggplot2)
library(scales)

# Assume df is as in example code
ggplot(df, aes(livestock, Freq, fill = dose)) +
geom_col(position = "fill") +
geom_text(
aes(
label = percent(after_stat(y / bygroup(y, interaction(x, PANEL))))
),
position = position_fill(0.5)
) +
facet_wrap(~ Village)

Sample Image

Adjusting percentage decimals for a bar plot with facet_grid()

There is an accuracy option in scales::percent:

p1 <- ggplot(mtcars, aes(x= cyl)) + 
geom_bar(aes(fill = vs), stat = "count") +
geom_text(aes(label = scales::percent(..prop..,accuracy=2)),
stat = "count", vjust = -0.5) +
theme_classic() + ylab("Count") + facet_grid(vs ~ .) + ylim(0, 15)

Sample Image

Sum percentages for each facet - respect fill

This is a bit of a hack, but you can reference ..x.. within the geom_bar call. The only problem is that ggplot considers this numeric and so I have coerced to factor and given nice labels within a call to scale_fill_brewer

ggplot(test, aes(x= test2, group = test1)) + 
geom_bar(aes(y = ..density.., fill = factor(..x..))) +
facet_grid(~test1) +
scale_fill_brewer(name = 'test2', breaks = 1:6,
labels = levels(test$test2), palette = 'Set3')

Sample Image

compare with not coercing ..x.. to a factor

ggplot(test, aes(x= test2, group = test1)) + 
geom_bar(aes(y = ..density.., fill = ..x..)) +
facet_grid(~test1)

Sample Image



Related Topics



Leave a reply



Submit