带有组和面的堆叠 ggplot 条形图的百分比标签
Percentage labels for a stacked ggplot barplot with groups and facets
我正在尝试将百分比标签添加到堆叠和多面条形图 (position='fill')。我希望每个条显示的百分比相加。
我正在使用这样的数据集:
## recreate dataset
Village<-c(rep('Vil1',10),rep('Vil2',10))
livestock<-c('p','p','p','c','c','s','s','s','g','g',
'p','p','c','c','s','s','s','s','g','g')
dose<-c(3,2,1,2,1,3,2,1,2,1,
2,1,2,1,4,3,2,1,2,1)
Freq<-c(4,5,5,2,3,4,1,1,6,8,
1,3,2,2,1,1,3,2,1,1)
df<-data.frame(Village,livestock,dose,Freq)
我成功地绘制了它并添加了标签,每个 X 变量(牲畜)的总和为 100%:
## create dose categories (factors)
df$dose<-as.character(df$dose)
df$dose[as.numeric(df$dose)>3]<-'>3'
df$dose<-factor(df$dose,levels=c('1','2','3','>3'))
## percentage barplot
ggplot(data = df, aes(x=livestock, y=Freq, fill=dose)) +
geom_bar(position='fill', stat='identity') +
labs(title="Given doses of different drugs in last 6months (livestock)",
subtitle='n=89',x="Livestock",y="Percentage",
fill = "Nr. of\ndoses") +
theme(axis.text.x = element_text(angle = 45, hjust=1))+
scale_y_continuous(labels=percent)+
facet_wrap(~Village)+
geom_text(aes(label = percent(..y../tapply(..y..,..x..,sum)[..x..])),
stat = "identity",position = position_fill(vjust=0.5))
有谁知道如何更改 ggplot 中的标签代码,以便每个条形图的百分比加起来达到 100%?也许与 ..group.. 有关?
我尝试了类似的方法: 我不能让它对我的数据起作用。
最简单的方法是预先转换数据,以便可以直接使用分数。
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)
如果坚持不对数据进行预转换,可以自己写一个小辅助函数
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)
}
然后您可以通过将组设置为 x
和(未记录的)PANEL
列来使用。
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)
只是添加到@teunbrand 的解决方案中:
我按照@teunbrand 的建议计算了分数,并且效果很好。但是,我开始收到非常奇怪且持续存在的警告消息:
Warning messages:
1: Unknown or uninitialised column: `times`.
2: Unknown or uninitialised column: `times`.
3: Unknown or uninitialised column: `times`.
4: Unknown or uninitialised column: `times`.
5: Unknown or uninitialised column: `Var1`.
我在这里阅读了这个问题,这似乎是一个已知错误:Persistent "Unknown or uninitialised column" warnings
我可以通过取消分组并将 tibble 重新转换为数据框来消除警告。
df <- as.data.frame(df %>% group_by(Village, livestock) %>%
mutate(frac = Freq / sum(Freq)) %>% ungroup())
我正在尝试将百分比标签添加到堆叠和多面条形图 (position='fill')。我希望每个条显示的百分比相加。
我正在使用这样的数据集:
## recreate dataset
Village<-c(rep('Vil1',10),rep('Vil2',10))
livestock<-c('p','p','p','c','c','s','s','s','g','g',
'p','p','c','c','s','s','s','s','g','g')
dose<-c(3,2,1,2,1,3,2,1,2,1,
2,1,2,1,4,3,2,1,2,1)
Freq<-c(4,5,5,2,3,4,1,1,6,8,
1,3,2,2,1,1,3,2,1,1)
df<-data.frame(Village,livestock,dose,Freq)
我成功地绘制了它并添加了标签,每个 X 变量(牲畜)的总和为 100%:
## create dose categories (factors)
df$dose<-as.character(df$dose)
df$dose[as.numeric(df$dose)>3]<-'>3'
df$dose<-factor(df$dose,levels=c('1','2','3','>3'))
## percentage barplot
ggplot(data = df, aes(x=livestock, y=Freq, fill=dose)) +
geom_bar(position='fill', stat='identity') +
labs(title="Given doses of different drugs in last 6months (livestock)",
subtitle='n=89',x="Livestock",y="Percentage",
fill = "Nr. of\ndoses") +
theme(axis.text.x = element_text(angle = 45, hjust=1))+
scale_y_continuous(labels=percent)+
facet_wrap(~Village)+
geom_text(aes(label = percent(..y../tapply(..y..,..x..,sum)[..x..])),
stat = "identity",position = position_fill(vjust=0.5))
有谁知道如何更改 ggplot 中的标签代码,以便每个条形图的百分比加起来达到 100%?也许与 ..group.. 有关?
我尝试了类似的方法:
最简单的方法是预先转换数据,以便可以直接使用分数。
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)
如果坚持不对数据进行预转换,可以自己写一个小辅助函数
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)
}
然后您可以通过将组设置为 x
和(未记录的)PANEL
列来使用。
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)
只是添加到@teunbrand 的解决方案中: 我按照@teunbrand 的建议计算了分数,并且效果很好。但是,我开始收到非常奇怪且持续存在的警告消息:
Warning messages:
1: Unknown or uninitialised column: `times`.
2: Unknown or uninitialised column: `times`.
3: Unknown or uninitialised column: `times`.
4: Unknown or uninitialised column: `times`.
5: Unknown or uninitialised column: `Var1`.
我在这里阅读了这个问题,这似乎是一个已知错误:Persistent "Unknown or uninitialised column" warnings
我可以通过取消分组并将 tibble 重新转换为数据框来消除警告。
df <- as.data.frame(df %>% group_by(Village, livestock) %>%
mutate(frac = Freq / sum(Freq)) %>% ungroup())