我想制作一个条形图,其中一个值比所有其他值大得多。有不连续的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中引入中断。另一种选择是使用对数刻度,这将使图形更易于阅读。

我意识到这将使在对数刻度上更容易阅读,但是我不想以这种方式显示信息,因为在转换时隐藏的小值之间会有很大的差异。

关于facet_wrap()与scales =“ free_x”
的组合怎么办?
也可以通过自定义转换来解决此问题...一会儿我会写一个答案

#1 楼

正如其他地方所指出的那样,ggplot2不能很好地处理此问题,因为通常认为断轴是有问题的。

其他策略通常被认为是对此问题的更好解决方案。布赖恩(Brian)提到了一些(构面,两张图关注不同的值集)。人们经常忽略的另一个选择,尤其是对于条形图,是制作一张桌子:



看看实际值,500并不能掩盖差异在其他价值观!由于某种原因,表作为一种可视化技术没有得到足够的重视。您可能会反对您的数据具有许多类别,这些类别在表中变得笨拙。如果是这样,您的条形图也可能会包含太多条形图,以至于也无法理解。

我并不是一直在争辩表格。但是,如果您要制作条形图相对较少的条形图,则绝对是要考虑的事情。而且,如果要用大量的条形图制作条形图,则无论如何都可能需要重新考虑。

最后,axis.break软件包中还有plotrix函数,该函数实现断轴。但是,根据我的收集,您必须手动指定轴标签并自行定位。

评论


乔兰,我对于使用这种情节确实有百感交集。您是正确的-表格可能是显示此内容的最佳方法。

– djq
2011年8月25日在18:13

@celenius-我不是要宣扬布道,也不是想骂你。我只是觉得桌子没有得到太多的爱,有时我对此感到厌烦。 ;)

– joran
2011年8月25日在18:15

@joran,我同意对于此特定数据,表格是最佳表示形式(如果只给出如何最好地表示的话,我会建议这样做)。在我的回答中,我过于专注于确切的问题,以至于无法回答应该提出的更广泛的问题。

–布赖恩·迪格斯(Brian Diggs)
11年8月25日在19:03

#2 楼

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

#3 楼

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

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


#4 楼

八年后,ggforce软件包提供了facet_zoom()扩展名,该扩展名是Hadley Wickham建议显示两个图的建议的实现(如Brian Diggs的回答所述)。 >
library(ggforce)
ggplot(df) + 
  aes(x = b, y = a) +
  geom_col() +
  facet_zoom(ylim = c(0, 10))




不幸的是,当前版本0.2.2的ggforce引发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建议


我认为更适合显示两个图-一个是所有
数据,另一个是较小的值。


此代码创建了两个图

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)




两个方面

在蔡斯(Chase)和布莱恩·迪格斯(Brian Diggs)的回答中,他解释了哈德利关于使用多面图的建议,其中一面包含所有数据,一面放大了特定区域


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

由于没有简单的方法可以分别缩放构面(例如,请参阅相关问题),因此需要操纵:

q4312 078q



评论


facet_zoom(),geom_col()和coord_flip()的错误已报告到github.com/thomasp85/ggforce/issues/143。

– Uwe
19年5月6日在9:19

谢谢,我真的很喜欢ggforce facet zoom功能!您是否知道是否可以放大两个范围,在图的每一侧一个?还是只有一条垂直线(仅包含y轴),并且在任一侧都有一个图,并且在两个不同的y值范围内绘制图?

– charlesdarwin
19年11月10日在20:57

#5 楼

不,不幸的是,

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

例如,如果轴被截断了,但通常位于某个间隔内(例如[0,1]),则听众可能不会注意到截断并得出关于数据的错误结论。在这种情况下,显式的不连续轴会更合适且更透明。

比较:



#6 楼

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

仅当出于某种原因必须使用图形表示时,才应使用此功能。

#7 楼

JörgSteinkamp使用facet_grid提供了一个聪明的ggplot解决方案。简化后,它是这样的:
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
)



评论


有没有一种方法可以控制左右面板的比例?

–蔡Cai
12月14日下午16:13

#8 楼

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

评论


对于某些图形来说,这是一个不错的选择,但对于从0开始的条形图,它不能很好地工作。

–格雷戈·托马斯(Gregor Thomas)
19年8月29日在15:48