如何在同一面板上的同一 X 轴上绘制具有两个不同 y 轴范围的点?
How do I plot points with two different y-axis ranges on the same panel in the same X axis?
我正在尝试使用 ggplot 创建一个散点图,该散点图共享一个 X 轴但具有一个具有两个不同比例的 Y 轴。
Y轴底部有三个刻度,从0%到0.1%,然后是0.1%到1%,最后是固定间隔10%。
来自 here 的示例:
有没有办法在 R 中使用 ggplot 生成类似的东西?
我会修改轴吗?在同一个面板上叠加多个图?或者是其他东西?
一般不建议在 ggplot2 中使用不连续的轴,原因已在 this question. Hadley Wickham (creator of ggplot2) explains here:
中探讨
I'm not a big fan of this type of display
because I think it is visually distorting. I think it's much more
appropriate to show two plots - one of all the data, and one of just
the small values. That way you can see how much the large values
dominate the smaller ones.
但是,这确实是可能的!您必须创建一个自定义轴变换,这不适合胆小的人。
这是一个例子。假设我们的数据 y
处于对数正态分布。
set.seed(20)
dat <- data.frame(x = c(0, rnorm(50)), y = c(0, exp(rnorm(50, -2, 1.5))))
ggplot(dat, aes(x, y)) + geom_point()
底部附近挤满了很多点:假设我想将所有低于 1 的值放在对数刻度上,而高于 1 的值放在线性刻度上。因此,我创建了一个自定义转换,称为 combine_trans
,它结合了对数刻度和线性刻度(这不是 完全 你上面的示例图所做的,因为它似乎去0,但可能已经足够接近了)。
combine_trans <- function(breakpoint, tr1, tr2,
br1 = tr1$breaks,
br2 = tr2$breaks) {
# combine two transformations.
# can also be given functions to determine tick marks
trans_breakpoint <- tr1$transform(breakpoint)
trans <- function(x) {
# choose which transformation to apply
ifelse(x < breakpoint,
tr1$transform(x),
tr2$transform(x - breakpoint) - trans_breakpoint)
}
inv <- function(x) {
# inverse of both transformations
ifelse(x < trans_breakpoint,
tr1$inverse(x),
breakpoint + tr2$inverse(x + trans_breakpoint))
}
br <- function(x) {
# combine break choices from both scales
br1 <- br1(c(x[x < breakpoint], breakpoint))
br2 <- br2(c(breakpoint, max(x[x > breakpoint])))
br <- c(br1, br2)
br[br > 0]
}
# combine domains
dom <- c(max(tr1$domain[1], tr2$domain[1]), min(tr1$domain[2], tr2$domain[2]))
trans_new("combined", trans, inv, breaks = br, domain = dom)
}
# combine log10 transformation and identity transformation
combined <- combine_trans(1, log10_trans(), identity_trans())
ggplot(dat, aes(x, y)) +
geom_point() +
scale_y_continuous(trans = combined) +
geom_hline(yintercept = 1, lty = 2)
请注意,我用 geom_hline
手动添加了一条水平虚线,这至少有助于引起对不连续性的注意。
您可以看到另一个不连续变换的示例 here,它在轴中引入了一个简单的中断。
请注意,此代码很复杂,可能需要自定义。更重要的是,它仍然有些误导:一般来说,您应该将数据分成单独的图,或者将所有内容都放在对数刻度上。不过,值得一提的是,ggplot2 让您可以使用这些工具,即使您 "shoot yourself in the foot" 使用它们也是如此!
我正在尝试使用 ggplot 创建一个散点图,该散点图共享一个 X 轴但具有一个具有两个不同比例的 Y 轴。
Y轴底部有三个刻度,从0%到0.1%,然后是0.1%到1%,最后是固定间隔10%。
来自 here 的示例:
有没有办法在 R 中使用 ggplot 生成类似的东西? 我会修改轴吗?在同一个面板上叠加多个图?或者是其他东西?
一般不建议在 ggplot2 中使用不连续的轴,原因已在 this question. Hadley Wickham (creator of ggplot2) explains here:
中探讨I'm not a big fan of this type of display because I think it is visually distorting. I think it's much more appropriate to show two plots - one of all the data, and one of just the small values. That way you can see how much the large values dominate the smaller ones.
但是,这确实是可能的!您必须创建一个自定义轴变换,这不适合胆小的人。
这是一个例子。假设我们的数据 y
处于对数正态分布。
set.seed(20)
dat <- data.frame(x = c(0, rnorm(50)), y = c(0, exp(rnorm(50, -2, 1.5))))
ggplot(dat, aes(x, y)) + geom_point()
底部附近挤满了很多点:假设我想将所有低于 1 的值放在对数刻度上,而高于 1 的值放在线性刻度上。因此,我创建了一个自定义转换,称为 combine_trans
,它结合了对数刻度和线性刻度(这不是 完全 你上面的示例图所做的,因为它似乎去0,但可能已经足够接近了)。
combine_trans <- function(breakpoint, tr1, tr2,
br1 = tr1$breaks,
br2 = tr2$breaks) {
# combine two transformations.
# can also be given functions to determine tick marks
trans_breakpoint <- tr1$transform(breakpoint)
trans <- function(x) {
# choose which transformation to apply
ifelse(x < breakpoint,
tr1$transform(x),
tr2$transform(x - breakpoint) - trans_breakpoint)
}
inv <- function(x) {
# inverse of both transformations
ifelse(x < trans_breakpoint,
tr1$inverse(x),
breakpoint + tr2$inverse(x + trans_breakpoint))
}
br <- function(x) {
# combine break choices from both scales
br1 <- br1(c(x[x < breakpoint], breakpoint))
br2 <- br2(c(breakpoint, max(x[x > breakpoint])))
br <- c(br1, br2)
br[br > 0]
}
# combine domains
dom <- c(max(tr1$domain[1], tr2$domain[1]), min(tr1$domain[2], tr2$domain[2]))
trans_new("combined", trans, inv, breaks = br, domain = dom)
}
# combine log10 transformation and identity transformation
combined <- combine_trans(1, log10_trans(), identity_trans())
ggplot(dat, aes(x, y)) +
geom_point() +
scale_y_continuous(trans = combined) +
geom_hline(yintercept = 1, lty = 2)
请注意,我用 geom_hline
手动添加了一条水平虚线,这至少有助于引起对不连续性的注意。
您可以看到另一个不连续变换的示例 here,它在轴中引入了一个简单的中断。
请注意,此代码很复杂,可能需要自定义。更重要的是,它仍然有些误导:一般来说,您应该将数据分成单独的图,或者将所有内容都放在对数刻度上。不过,值得一提的是,ggplot2 让您可以使用这些工具,即使您 "shoot yourself in the foot" 使用它们也是如此!