ggplot2:将条形图(geom_bar)的基线移动到最小数据值

时间:2016-10-28 04:47:53

标签: r ggplot2 geom-bar

我尝试使用geom_bar生成条形图。我的酒吧有负值和正值:

set.seed(1)
df <- data.frame(y=log(c(runif(6,0,1),runif(6,1,10))),se=runif(12,0.05,0.1),name=factor(rep(c("a","a","b","b","c","c"),2),levels=c("a","b","c")),side=factor(rep(1:2,6),levels=1:2),group=factor(c(rep("x",6),rep("y",6)),levels=c("x","y")),stringsAsFactors=F)

此绘图命令将正向条形图面朝上,将负向条形图面朝下:

library(ggplot2)
dodge <- position_dodge(width=0.9)
limits <- aes(ymax=y+se,ymin=y-se)
ggplot(df,aes(x=name,y=y,group=interaction(side,name),col=group,fill=group))+facet_wrap(~group)+geom_bar(width=0.6,position=position_dodge(width=1),stat="identity")+
geom_bar(position=dodge,stat="identity")+geom_errorbar(limits,position=dodge,width=0.25)

enter image description here

我的问题是如何将基线设置为所有条形的最小值而不是0,并且红条会朝上?

3 个答案:

答案 0 :(得分:1)

您可以从每个值中减去min(df$y),以便将数据移动到零基线,然后将y轴重新标记为点的实际值。这样做的代码如下,但我不推荐这个。从非零基线发出条形似乎令人困惑,因为条形的长度不再编码y值的大小。

ggplot(df, aes(x=name,y=y - min(y),group=interaction(side, name), col=group, fill=group)) + 
  facet_wrap(~group) +
  geom_bar(position=dodge, stat="identity", width=0.8) +
  geom_errorbar(aes(ymin=y-se-min(y), ymax=y+se-min(y)), 
                position=dodge, width=0.25, colour="black") +
  scale_y_continuous(breaks=0:4, labels=round(0:4 + min(df$y), 1)) +
  geom_hline(aes(yintercept=0))

enter image description here

另一种选择是使用geom_linerange,这避免了必须移动y值并重新标记y轴。但是,这与上面的条形图有相同的扭曲:

ggplot(df, aes(x=name, group=interaction(side, name), col=group, fill=group)) + 
  facet_wrap(~group) +
  geom_linerange(aes(ymin=min(y), ymax=y, x=name, xend=name), position=dodge, size=10) +
  geom_errorbar(aes(ymin=y-se, ymax=y+se), position=dodge, width=0.25, colour="black") +
  geom_hline(aes(yintercept=min(y)))

enter image description here

相反,在我看来,点数比这里的酒吧更直观,更自然:

ggplot(df, aes(x=name,y=y,group=interaction(side, name), col=group, fill=group)) + 
  facet_wrap(~group) +
  geom_hline(yintercept=0, lwd=0.4, colour="grey50") +
  geom_errorbar(limits, position=dodge, width=0.25) +
  geom_point(position=dodge)

enter image description here

答案 1 :(得分:1)

这个简单的黑客也有效:

m <- min(df$y) # find min
df$y <- df$y - m
ggplot(df,aes(x=name,y=y,group=interaction(side,name),col=group,fill=group))+
  facet_wrap(~group)+
  geom_bar(width=0.6,position=position_dodge(width=1),stat="identity")+
  geom_bar(position=dodge,stat="identity")+
  geom_errorbar(limits,position=dodge,width=0.25) +
  scale_y_continuous(breaks=seq(min(df$y), max(df$y), length=5),labels=as.character(round(seq(m, max(df$y+m), length=5),2))) # relabel

enter image description here

答案 2 :(得分:0)

我遇到了同样的问题,发现您还可以使用geom_crossbar轻松地做到这一点。

只要颜色和填充相同,您就不会在横杆(以y美学设置)中看到中断,因此它们看起来就像横条。

library(ggplot2)

dodge <- position_dodge(width=0.9)
limits <- aes(ymax = y+se, ymin = y-se)
df$ymin <- min(df$y)

ggplot(df, aes(x = name, ymax = y, y = y, ymin = ymin, group = interaction(side,name), col = group, fill = group)) + 
facet_wrap(~group) + 
geom_crossbar(width=0.6,position=position_dodge(width=1),stat="identity") +
geom_errorbar(limits, color = 'black', position = dodge, width=0.25)

ggplot output