【问题标题】:Using ggplot2, can I insert a break in the axis?使用ggplot2,我可以在轴上插入一个中断吗?
【发布时间】:2011-11-03 21:55:17
【问题描述】:

我想制作一个条形图,其中一个值远大于所有其他值。有没有办法让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

有没有办法让我的轴从 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()

【问题讨论】:

  • 我不认为你可以在 ggplot2 中引入中断。另一种方法是使用log 比例尺,这将使图表更易于阅读。
  • 我意识到它会使在对数刻度上更容易阅读,但我不想以这种方式显示信息,因为小值之间存在显着差异,当他们被改变了。
  • facet_wrap()scales = "free_x" 的组合怎么样
  • 也可以通过自定义转换来解决这个问题......我有时间会写一个答案

标签: r ggplot2 r-faq


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    正如其他地方所指出的,这不是ggplot2 可以很好地处理的事情,因为损坏的轴通常被认为是有问题的。

    其他策略通常被认为是解决此问题的更好方法。 Brian 提到了一些(分面,两个侧重于不同值集的图)。人们经常忽略的另一种选择(尤其是对于条形图)是制作一个表格

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

    我并不是一直在为桌子争论。但是,如果您制作的条形图相对较少,它们绝对是需要考虑的因素。如果您要制作包含大量条形的条形图,那么您可能需要重新考虑这一点。

    最后,plotrix 包中还有一个 axis.break 函数,它实现了断轴。但是,据我所知,您必须自己手动指定轴标签和位置。

    【讨论】:

    • Joran,我确实对使用这种类型的情节感到复杂。你是对的 - 表格可能是展示这一点的最佳方式。
    • @celenius - 我不是故意说教或者好像在骂你。我只是觉得桌子没有得到太多的爱,有时我会为此而烦恼。 ;)
    • @joran,我同意对于这个特定数据,表格是最佳表示(如果只是给出如何最好地表示它的问题,我会推荐什么)。在我的回答中,我过于狭隘地专注于确切的问题,以至于无法回答应该问的更广泛的问题。
    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

      不使用 ggplot,但使用 plotrix 您可以轻松做到这一点:

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

      【讨论】:

        【解决方案5】:

        不,很遗憾没有

        担心的是允许不连续的轴会导致观众的欺骗。但是,在某些情况下,没有不连续的轴会导致失真。

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

        比较:

        【讨论】:

          【解决方案6】:

          一种策略是更改轴以绘制对数刻度。通过这种方式,您可以将指数级更高的价值降低 10 倍

          【讨论】:

          • 对于某些图表来说是一个不错的选择,但对于从 0 开始的条形图来说效果不佳。
          【解决方案7】:

          八年后,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))
          

          很遗憾,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))
          

          两个地块

          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)
          

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

          两个方面

          这是由 in a comment by Chasehis answer 中的 Brian Diggs 提出的,他解释了 Hadley 的使用建议

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

          但到目前为止,还没有为这种方法提供任何代码。

          由于没有简单的方法来单独缩放构面(例如,参见 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")
          

          【讨论】:

          • facet_zoom()geom_col()coord_flip() 的错误已报告给github.com/thomasp85/ggforce/issues/143
          • 谢谢,我真的很喜欢 ggforce 平面缩放功能!你知道是否可以放大两个范围,一个在图的每一侧?或者只是有一条只有 y 轴的垂直线,并且在任一侧都有一个绘图,绘图在两个不同的 y 值范围内?
          【解决方案8】:

          clever ggplot solution 由 Jörg Steinkamp 提供,使用 facet_grid。简单来说,是这样的:

          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
          )
          

          【讨论】:

          • 有没有办法控制左右面板的比例?
          • @MiaoCai - 控制比例的一种方法是使用“grid”包,根据stackoverflow.com/a/49225527/3799203的详细示例
          • 这是一个不错的解决方案,但它假定跳过的部分中没有数据点
          【解决方案9】:
          library(data.table)
          dt <- data.table(a = c(1,2,3,500), b = c('a1', 'a2','a3', 'a4'))
          dt[,ggplot(.SD)+
                aes(x = b, y = a) +
                geom_col(data = subset(.SD,TRUE)[,subset:="all"])+
                geom_col(data = subset(.SD ,a <= 10)[,subset:= "small"]) +
               coord_flip() + 
               facet_wrap(~ subset, scales = "free_x")]
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-07-24
            • 2019-12-24
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多