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)
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 :
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)
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)
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)
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)
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)
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')
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)
Related Topics
How to Fix Corrupted Dates in R
What Are the Differences Between Community Detection Algorithms in Igraph
Ggplot2 Plot Without Axes, Legends, etc
Remove Grid, Background Color, and Top and Right Borders from Ggplot2
How to Remove Columns from a Data.Frame
Remove All Line Breaks (Enter Symbols) from the String Using R
R on Windows: Character Encoding Hell
Efficient Row-Wise Operations on a Data.Table
Add Line Break to Axis Labels and Ticks in Ggplot
How to Fix the Aspect Ratio in Ggplot
Setting Document Title in Rmarkdown from Parameters
Rmarkdown: How to Change the Font Color
Geom_Text How to Position the Text on Bar as I Want
Sort a Data.Table Fast by Ascending/Descending Order
Text Clustering with Levenshtein Distances