ggplot2 - 带有堆栈和闪避的条形图
Posted
技术标签:
【中文标题】ggplot2 - 带有堆栈和闪避的条形图【英文标题】:ggplot2 - bar plot with both stack and dodge 【发布时间】:2012-09-24 19:15:46 【问题描述】:我正在尝试使用ggplot2
创建一个条形图,其中我按一个变量堆叠并通过另一个变量躲避。
这是一个示例数据集:
df=data.frame(
year=rep(c("2010","2011"),each=4),
treatment=rep(c("Impact","Control")),
type=rep(c("Phylum1","Phylum2"),each=2),
total=sample(1:100,8))
我想创建一个条形图,其中x=treatment
、y=total
,堆叠变量为type
,躲避变量为year
。当然,我可以做一个或另一个:
ggplot(df,aes(y=total,x=treatment,fill=type))+geom_bar(position="dodge",stat="identity")
ggplot(df,aes(y=total,x=treatment,fill=year))+geom_bar(position="dodge",stat="identity")
但不是两者都有!感谢任何可以提供建议的人。
【问题讨论】:
你只能做一个或另一个,不能同时做。在这里查看我的相关答案:***.com/questions/12592041/… 【参考方案1】:这是使用刻面而不是躲避的替代方法:
ggplot(df, aes(x = year, y = total, fill = type)) +
geom_bar(position = "stack", stat = "identity") +
facet_wrap( ~ treatment)
根据 Tyler 的建议更改:+ theme(panel.margin = grid::unit(-1.25, "lines"))
【讨论】:
两者兼得的好选择。 +1 嗯,有趣的想法。我想它必须这样做!感谢@Maiasaura 和 Matt Parker 添加+ theme(panel.margin = unit(-1.25, "lines"))
可以让他们看起来更像是在同一个视野中,但仍然不完全是 OP 所追求的。不错的最佳选择。 +1
@TylerRinker 不错 - 甚至不知道这样的事情是可能的!给关注的人一个提示:我必须使用grid::unit
来获取此信息,而无需直接加载grid
。【参考方案2】:
您可以获得的最接近的方法是在 dodged
条周围绘制边框以突出显示堆叠的 type
值。
ggplot(df, aes(treatment, total, fill = year)) +
geom_bar(stat="identity", position="dodge", color="black")
【讨论】:
嗯,边框似乎与数据不一致。例如,set.seed(8)
在运行代码之前查看值。
如果你真的想变得花哨,我敢打赌你可以使用geom_rect
来填充某些部分,但是你使用的是 ggplot 来绘制而不是绘图。【参考方案3】:
您可以使用interaction(year, treatment)
作为x 轴变量来替代dodge
。
library(dplyr)
library(ggplot2)
df=data.frame(
year=rep(c("2010","2011"),each=4),
treatment=rep(c("Impact","Control")),
type=rep(c("Phylum1","Phylum2"),each=2),
total=sample(1:100,8)) %>%
mutate(x_label = factor(str_replace(interaction(year, treatment), '\\.', ' / '),
ordered=TRUE))
ggplot(df, aes(x=x_label, y=total, fill=type)) +
geom_bar(stat='identity') +
labs(x='Year / Treatment')
由reprex package (v0.2.0) 于 2018 年 4 月 26 日创建。
【讨论】:
交互似乎只用于创建标签?那为什么不直接paste0(year, "/", treatment)
呢?【参考方案4】:
它可以完成,但是它很棘手/繁琐,您基本上必须将条形图分层。
这是我的代码:
library(tidyverse)
df=data.frame(
year=rep(c(2010,2011),each=4),
treatment=rep(c("Impact","Control")),
type=rep(c("Phylum1","Phylum2"),each=2),
total=sample(1:100,8))
# separate the by the variable which we are dodging by so
# we have two data frames impact and control
impact <- df %>% filter(treatment == "Impact") %>%
mutate(pos = sum(total, na.rm=T))
control <- df %>% filter(treatment == "Control") %>%
mutate(pos = sum(total, na.rm=T))
# calculate the position for the annotation element
impact_an <- impact %>% group_by(year) %>%
summarise(
pos = sum(total) + 12
, treatment = first(treatment)
)
control_an <- control %>% group_by(year) %>%
summarise(
pos = sum(total) + 12
, treatment = first(treatment)
)
# define the width of the bars, we need this set so that
# we can use it to position the second layer geom_bar
barwidth = 0.30
ggplot() +
geom_bar(
data = impact
, aes(x = year, y = total, fill = type)
, position = "stack"
, stat = "identity"
, width = barwidth
) +
annotate(
"text"
, x = impact_an$year
,y = impact_an$pos
, angle = 90
, label = impact_an$treatment
) +
geom_bar(
data = control
# here we are offsetting the position of the second layer bar
# by adding the barwidth plus 0.1 to push it to the right
, aes(x = year + barwidth + 0.1, y = total, fill = type)
, position = "stack"
, stat = "identity"
, width = barwidth
) +
annotate(
"text"
, x = control_an$year + (barwidth * 1) + 0.1
,y = control_an$pos
, angle = 90
, label = control_an$treatment
) +
scale_x_discrete(limits = c(2010, 2011))
这并不能很好地扩展,但是您可以通过一些方法对其进行编码以使其适合您的情况,归功于我最初从以下帖子中学到的这种方法:https://community.rstudio.com/t/ggplot-position-dodge-with-position-stack/16425
【讨论】:
我尝试了类似的方法,但不是手动计算条形位置,您实际上可以将每一层放在一组单独的离散 x 轴值中,例如 2010-a(用于影响)、2010-b (用于控制),2010-gap(作为空白),然后覆盖轴标签。这样你只需要稍微操作你的数据,然后在每个自己的 x 值上绘制每一层。【参考方案5】:你可以玩一些 alpha:
df %>%
group_by(year, treatment) %>%
mutate(cum_tot = cumsum(total)) %>%
ggplot(aes(treatment, cum_tot, fill =year)) +
geom_col(data = . %>% filter( type=="Phylum1"), position = position_dodge(width = 0.9), alpha = 1) +
geom_col(data = . %>% filter( type=="Phylum2"), position = position_dodge(width = 0.9), alpha = 0.4) +
geom_tile(aes(y=NA_integer_, alpha = factor(type))) +
scale_alpha_manual(values = c(1,0.4))
现在您可以添加theme(panel.background = element_rect(fill ="yellow"))
一些背景填充来混合颜色:
最后你必须使用 inkscape 修复图例。
【讨论】:
以上是关于ggplot2 - 带有堆栈和闪避的条形图的主要内容,如果未能解决你的问题,请参考以下文章