使用ggplot2,我可以在轴上插入一个断点吗?

时间:2011-08-25 17:33:48

标签: r ggplot2

我想制作一个条形图,其中一个值比所有其他值大得多。有没有一种不连续的y轴方法?我的数据如下:

df <- data.frame(a = c(1,2,3,500), b = c('a1', 'a2','a3', 'a4'))

p <- ggplot(data = df, aes(x = b, y = a)) + geom_bar() 
p <- p + opts(axis.text.x=theme_text(angle= 90, hjust=1))  + coord_flip()
p

enter image description here

有没有办法可以让我的轴从1到10,然后是490 - 500?我想不出任何其他绘制数据的方式(除了转换它,我不想做)

[编辑2019-05-06]:

8年后,上面的代码需要修改为与ggplot2的3.1.1版一起使用才能创建相同的图表:

library(ggplot2)
ggplot(df) + 
  aes(x = b, y = a) +
  geom_col() +
  coord_flip()

8 个答案:

答案 0 :(得分:44)

如其他地方所述,这不是ggplot2能够很好地处理的事情,因为断轴通常被认为是有问题的。

其他策略通常被认为是解决此问题的更好方法。布莱恩提到了一些(分面,两个关注不同价值观的情节)。人们经常忽略的另一个选择,特别是对于条形图,是制作

enter image description here

查看实际值,500不会掩盖其他值的差异!出于某种原因,表格作为可视化技术的数据并没有得到足够的尊重。您可能会反对您的数据有很多很多类别,这些类别在表格中变得难以处理。如果是这样,你的条形图可能会有太多的条形图也是合理的。

我并不是在争论表所有的时间。但如果您制作的酒吧条形图比较少,那么它们绝对值得考虑。如果你正在制作大量酒吧的条形图,你可能需要重新考虑一下。

最后,axis.break包中还有plotrix函数实现了断轴。但是,根据我收集的内容,您必须手动指定轴标签和位置。

答案 1 :(得分:26)

不,不使用ggplot。请参阅http://groups.google.com/group/ggplot2/browse_thread/thread/8d2acbfc59d2f247主题中的讨论,其中Hadley解释了为什么它不可能,但提供了建议的替代方案(分面图,一个包含所有数据,一个在特定区域放大)。

答案 2 :(得分:21)

不使用ggplot,但使用plotrix,您可以轻松地执行此操作:

library(plotrix)
gap.barplot(df$a, gap=c(5,495),horiz=T)

答案 3 :(得分:15)

不,不幸的是

恐惧是允许不连续的轴会导致观众的欺骗。但是,有些情况下不具有不连续轴会导致失真。

例如,如果轴被截断,但通常位于某个区间内(例如[0,1]),则观众可能不会注意到截断并对数据做出扭曲的结论。在这种情况下,显式的不连续轴将更合适和透明。

比较

Example of good use of continuous vs discontinuous axis

答案 4 :(得分:1)

我怀疑R中有什么现成的,但您可以将数据显示为一系列3D部分立方体。 500仅为5 * 10 * 10,因此它可以很好地扩展。确切的值可以是标签。

这可能只应在必须出于某种原因的图形表示时使用。

答案 5 :(得分:1)

八年后,ggforce软件包提供了facet_zoom()扩展名,它是Hadley Wickham's suggestion的一种实现,以显示两个图(如Brian Diggs' answer中所述)。

缩放小面

library(ggforce)
ggplot(df) + 
  aes(x = b, y = a) +
  geom_col() +
  facet_zoom(ylim = c(0, 10))

enter image description here

不幸的是,当前ggforce的0.2.2版本引发了coord_flip()的错误,因此只能显示竖线。

缩放的构面显示较小值的变化,但仍包含较大的-现在已裁剪-a4条。 zoom.data参数控制哪些值显示在缩放的构面中:

library(ggforce)
ggplot(df) + 
  aes(x = b, y = a) +
  geom_col() +
  facet_zoom(ylim = c(0, 10), zoom.data = ifelse(a <= 10, NA, FALSE))

enter image description here

两个地块

Hadley Wickham suggested

  

我认为更适合显示两个情节-其中之一   数据,只是其中一个较小的值。

此代码创建了两个图

library(ggplot2)
g1 <- ggplot(df) + 
  aes(x = b, y = a) +
  geom_col() +
  coord_flip()
g2 <- ggplot(df) + 
  aes(x = b, y = a) +
  geom_col() +
  coord_flip() +
  ylim(NA, 10)

可以通过以下方式组合成一个图

cowplot::plot_grid(g1, g2) # or ggpubr::ggarrange(g1, g2)

enter image description here

gridExtra::grid.arrange(g1, g2) # or egg::ggarrange(g1, g2)

enter image description here

两个方面

in a comment by Chasehis answer的布莱恩·迪格斯(Brian Diggs)都提出了这个建议,他解释了哈德利的使用建议。

  

多面图,一个包含所有数据,一个放大到特定区域

但到目前为止,此方法尚未提供任何代码。

由于没有简单的方法可以分别缩放构面(例如,参见related question),因此需要对数据进行操作:

library(dplyr)
library(ggplot2)
ggplot() + 
  aes(x = b, y = a) +
  geom_col(data = df %>% mutate(subset = "all")) +
  geom_col(data = df %>% filter(a <= 10) %>% mutate(subset = "small")) +
  coord_flip() + 
  facet_wrap(~ subset, scales = "free_x")

enter image description here

答案 6 :(得分:1)

JörgSteinkamp使用facet_grid提供了clever ggplot solution。简化了,是这样的:

library("tidyverse")
df <- data.frame(myLetter=LETTERS[1:4], myValue=runif(12) + rep(c(4,0,0),2))  # cluster a few values well above 1
df$myFacet <- df$myValue > 3
(ggplot(df, aes(y=myLetter, x=myValue)) 
  + geom_point() 
  + facet_grid(. ~ myFacet, scales="free", space="free")
  + scale_x_continuous(breaks = seq(0, 5, .25)) # this gives both facets equal interval spacing.
  + theme(strip.text.x = element_blank()) # get rid of the facet labels
)

enter image description here

答案 7 :(得分:0)

一种策略是更改轴以绘制对数刻度。这样,您就可以将较高的指数值减少10倍