提问人:djq 提问时间:8/26/2011 最后编辑:Gregor Thomasdjq 更新时间:8/23/2022 访问量:127552
使用 ggplot2,我可以在轴上插入中断吗?
Using ggplot2, can I insert a break in the axis?
问:
我想制作一个条形图,其中一个值比所有其他值大得多。有没有办法有一个不连续的 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 年后,需要修改上述代码以使用 3.1.1 版本才能创建相同的图表:ggplot2
library(ggplot2)
ggplot(df) +
aes(x = b, y = a) +
geom_col() +
coord_flip()
答:
不,不使用 ggplot。请参阅 http://groups.google.com/group/ggplot2/browse_thread/thread/8d2acbfc59d2f247 线程中的讨论,其中 Hadley 解释了为什么这是不可能的,但给出了一个建议的替代方案(分面图,一个包含所有数据,一个在特定区域放大)。
正如其他地方所指出的,这不是一件可以很好地处理的事情,因为断裂的轴通常被认为是有问题的。ggplot2
其他策略通常被认为是解决这个问题的更好方法。布莱恩提到了一些(刻面,两个专注于不同值集的图)。人们经常忽略的另一个选择,特别是对于条形图,是制作表格:
从实际值来看,500 并没有掩盖其他值的差异!出于某种原因,表格没有得到足够的尊重,因为数据是一种可视化技术。您可能会反对您的数据有很多很多类别,这在表中变得笨拙。如果是这样,您的条形图很可能也会有太多的条形。
而且我不是一直在争论桌子。但是,如果您要制作条形相对较少的条形图,它们绝对是需要考虑的事情。如果你正在制作包含大量条形的条形图,你可能需要重新考虑这一点。
最后,包中还有一个实现断轴的函数。但是,根据我收集的信息,您必须自己手动指定轴标签和位置。axis.break
plotrix
评论
我怀疑 R 中有什么现成的东西,但您可以将数据显示为一系列 3D 部分立方体。500 只有 5*10*10,所以它可以很好地扩展。确切的值可以是标签。
这可能只有在出于某种原因必须具有图形表示时才应使用。
不是使用 ggplot,而是使用 plotrix,您可以轻松做到这一点:
library(plotrix)
gap.barplot(df$a, gap=c(5,495),horiz=T)
评论
gap.barplot(y=df$a, gap=c(5,495),horiz=T, xaxlab=df$b, ylim=c(0,12), ytics=df$a, yaxlab=df$a)
不,很遗憾不是
人们担心的是,允许不连续的轴会导致观众的欺骗。但是,在某些情况下,没有不连续的轴会导致失真。
例如,如果轴被截断,但通常位于某个区间内(例如 [0,1]),则受众可能不会注意到截断并对数据做出扭曲的结论。在这种情况下,显式不连续轴将更合适和透明。
比较:
一种策略是更改轴以绘制对数刻度。这样一来,您就可以将指数级更高的值减少 10 倍
评论
八年后,该软件包提供了一个扩展,该扩展是 Hadley Wickham 建议的实现,即显示两个情节(如 Brian Diggs 的回答中所述)。ggforce
facet_zoom()
缩放分面
library(ggforce)
ggplot(df) +
aes(x = b, y = a) +
geom_col() +
facet_zoom(ylim = c(0, 10))
不幸的是,当前版本的 0.2.2 会抛出错误,因此只能显示垂直条。ggforce
coord_flip()
缩放的 facet 显示小值的变化,但仍包含大的(现在已裁剪的)条形图。该参数控制在缩放的分面中显示哪些值: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))
两块地
我认为展示两个情节更合适——其中一个 数据,并且只是小值之一。
此代码创建两个绘图
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)
两个方面
这是在蔡斯的评论中提出的,布莱恩·迪格斯(Brian Diggs)在他的回答中也提出了这一点,他解释了哈德利的建议
多面图,一个包含所有数据,一个在特定区域放大
但到目前为止,还没有为这种方法提供代码。
由于没有简单的方法可以单独缩放分面(例如,参见相关问题),因此需要对数据进行操作:
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()
facet_zoom()
Jörg Steinkamp 使用 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
)
评论
截至 2022-06-01,我们有了外观优雅的包装,它似乎回答了 OP 的问题。虽然我没有在自己的数据上尝试过它,但它看起来与许多或所有其他功能兼容。还提供差异缩放,可能对 OP 和类似用途有用。ggbreak
ggplot2
library(ggplot2)
library(ggbreak)
set.seed(2019-01-19)
d <- data.frame(x = 1:20,
y = c(rnorm(5) + 4, rnorm(5) + 20, rnorm(5) + 5, rnorm(5) + 22))
p1 <- ggplot(d, aes(y, x)) + geom_col(orientation="y") +
theme_minimal()
p1 + scale_x_break(c(7, 17), scales = 1.5) + scale_x_break(c(18, 21), scales=2)
一个选项是使用 scale_y_cut() 或 scale_x_cut() 函数使用 ggbreak 包。此功能可以将对象切割成多个部分,并可以指定放大或缩小哪个部分。这是一个可重现的示例,左图为正常图,右图使用函数:ggplot
df <- data.frame(a = c(1,2,3,500), b = c('a1', 'a2','a3', 'a4'))
library(ggplot2)
library(ggbreak)
library(patchwork)
p1 <- ggplot(df) +
aes(x = b, y = a) +
geom_col()
p2 <- ggplot(df) +
aes(x = b, y = a) +
geom_col() +
scale_y_cut(breaks=c(4, 30), which=c(1, 3), scales=c(0.5, 3))
p1 + p2
创建于 2022-08-22 with reprex v2.0.2
从示例中可以看出,某些部分被放大和缩小。这可以通过使用不同的参数来更改。
使用的参数:
- 休息:
数值或数值向量,要划分的点
- 哪:
整数,子图到刻度的位置,从左开始 从右或从上到下。
- 尺度:
子图的数字、相对宽度或高度。
要更改子图之间的间距,可以使用参数 。space
有关一些额外的信息和示例,请查看本教程。
评论
log
facet_wrap()
scales = "free_x"