R/ggplot2:从散点图中折叠或删除 y 轴段
R/ggplot2: Collapse or remove segment of y-axis from scatter-plot
我正在尝试使用 ggplot2 在 R 中制作散点图,其中 y 轴的中间被折叠或删除,因为那里没有数据。我是在下面的 photoshop 中完成的,但是有没有办法用 ggplot 创建类似的图?
这是具有连续尺度的数据:
但我正在尝试做这样的事情:
代码如下:
ggplot(data=distance_data) +
geom_point(
aes(
x = mdistance,
y = maxZ,
shape = factor(subj),
color = factor(side),
size = (cSA)
)
) +
scale_size_continuous(range = c(4, 10)) +
theme(
axis.text.x = element_text(colour = "black", size = 15),
axis.text.y = element_text(colour = "black", size = 15),
axis.title.x = element_text(colour = "black", size= 20, vjust = 0),
axis.title.y = element_text(colour = "black", size= 20),
legend.position = "none"
) +
ylab("Z-score") +
xlab("Distance")
您可以通过定义一个坐标变换来做到这一点。一个标准的例子是对数坐标,它可以在 ggplot
中通过使用 scale_y_log10()
.
来实现
但是您也可以通过向 scale_y_continuous()
提供 trans
参数来定义自定义转换函数(对于 scale_x_continuous()
也是如此)。为此,您使用 scales
包中的函数 trans_new()
。它以转换函数及其反函数作为参数。
我首先讨论了针对 OP 示例的特殊解决方案,然后还展示了如何将其推广。
OP 的例子
OP 想要缩小 -2 和 2 之间的区间。下面定义了一个将这个区间缩小 4 倍的函数(及其反函数):
library(scales)
trans <- function(x) {
ifelse(x > 2, x - 1.5, ifelse(x < -2, x + 1.5, x/4))
}
inv <- function(x) {
ifelse(x > 0.5, x + 1.5, ifelse(x < -0.5, x - 1.5, x*4))
}
my_trans <- trans_new("my_trans", trans, inv)
这定义了转换。为了查看实际效果,我定义了一些样本数据:
x_val <- 0:250
y_val <- c(-6:-2, 2:6)
set.seed(1234)
data <- data.frame(x = sample(x_val, 30, replace = TRUE),
y = sample(y_val, 30, replace = TRUE))
我先画出来不加变换:
p <- ggplot(data, aes(x, y)) + geom_point()
p + scale_y_continuous(breaks = seq(-6, 6, by = 2))
现在我使用 scale_y_continuous()
进行转换:
p + scale_y_continuous(trans = my_trans,
breaks = seq(-6, 6, by = 2))
如果你想要另一个变换,你必须再次改变trans()
和inv()
和运行trans_new()
的定义。您必须确保 inv()
确实是 inv()
的倒数。我检查如下:
x <- runif(100, -100, 100)
identical(x, trans(inv(x)))
## [1] TRUE
一般解决方案
下面的函数定义了一个转换,您可以在其中选择要压缩的区域的下端和上端,以及要使用的因子。它直接returns里面的trans
对象就可以使用scale_y_continuous
:
library(scales)
squish_trans <- function(from, to, factor) {
trans <- function(x) {
if (any(is.na(x))) return(x)
# get indices for the relevant regions
isq <- x > from & x < to
ito <- x >= to
# apply transformation
x[isq] <- from + (x[isq] - from)/factor
x[ito] <- from + (to - from)/factor + (x[ito] - to)
return(x)
}
inv <- function(x) {
if (any(is.na(x))) return(x)
# get indices for the relevant regions
isq <- x > from & x < from + (to - from)/factor
ito <- x >= from + (to - from)/factor
# apply transformation
x[isq] <- from + (x[isq] - from) * factor
x[ito] <- to + (x[ito] - (from + (to - from)/factor))
return(x)
}
# return the transformation
return(trans_new("squished", trans, inv))
}
trans()
和 inv()
中的第一行处理使用 x = c(NA, NA)
调用转换的情况。 (我最初写这个问题时ggplot2
的版本似乎没有发生这种情况。不幸的是,我不知道这个startet是哪个版本。)
现在可以使用此功能方便地重做第一部分的情节:
p + scale_y_continuous(trans = squish_trans(-2, 2, 4),
breaks = seq(-6, 6, by = 2))
以下示例显示您可以在任意位置压缩比例尺,这也适用于除点以外的其他几何对象:
df <- data.frame(class = LETTERS[1:4],
val = c(1, 2, 101, 102))
ggplot(df, aes(x = class, y = val)) + geom_bar(stat = "identity") +
scale_y_continuous(trans = squish_trans(3, 100, 50),
breaks = c(0, 1, 2, 3, 50, 100, 101, 102))
让我最后强调一下评论中已经提到的其他内容:这种情节可能会产生误导,应谨慎使用!
我正在尝试使用 ggplot2 在 R 中制作散点图,其中 y 轴的中间被折叠或删除,因为那里没有数据。我是在下面的 photoshop 中完成的,但是有没有办法用 ggplot 创建类似的图?
这是具有连续尺度的数据:
但我正在尝试做这样的事情:
代码如下:
ggplot(data=distance_data) +
geom_point(
aes(
x = mdistance,
y = maxZ,
shape = factor(subj),
color = factor(side),
size = (cSA)
)
) +
scale_size_continuous(range = c(4, 10)) +
theme(
axis.text.x = element_text(colour = "black", size = 15),
axis.text.y = element_text(colour = "black", size = 15),
axis.title.x = element_text(colour = "black", size= 20, vjust = 0),
axis.title.y = element_text(colour = "black", size= 20),
legend.position = "none"
) +
ylab("Z-score") +
xlab("Distance")
您可以通过定义一个坐标变换来做到这一点。一个标准的例子是对数坐标,它可以在 ggplot
中通过使用 scale_y_log10()
.
但是您也可以通过向 scale_y_continuous()
提供 trans
参数来定义自定义转换函数(对于 scale_x_continuous()
也是如此)。为此,您使用 scales
包中的函数 trans_new()
。它以转换函数及其反函数作为参数。
我首先讨论了针对 OP 示例的特殊解决方案,然后还展示了如何将其推广。
OP 的例子
OP 想要缩小 -2 和 2 之间的区间。下面定义了一个将这个区间缩小 4 倍的函数(及其反函数):
library(scales)
trans <- function(x) {
ifelse(x > 2, x - 1.5, ifelse(x < -2, x + 1.5, x/4))
}
inv <- function(x) {
ifelse(x > 0.5, x + 1.5, ifelse(x < -0.5, x - 1.5, x*4))
}
my_trans <- trans_new("my_trans", trans, inv)
这定义了转换。为了查看实际效果,我定义了一些样本数据:
x_val <- 0:250
y_val <- c(-6:-2, 2:6)
set.seed(1234)
data <- data.frame(x = sample(x_val, 30, replace = TRUE),
y = sample(y_val, 30, replace = TRUE))
我先画出来不加变换:
p <- ggplot(data, aes(x, y)) + geom_point()
p + scale_y_continuous(breaks = seq(-6, 6, by = 2))
现在我使用 scale_y_continuous()
进行转换:
p + scale_y_continuous(trans = my_trans,
breaks = seq(-6, 6, by = 2))
如果你想要另一个变换,你必须再次改变trans()
和inv()
和运行trans_new()
的定义。您必须确保 inv()
确实是 inv()
的倒数。我检查如下:
x <- runif(100, -100, 100)
identical(x, trans(inv(x)))
## [1] TRUE
一般解决方案
下面的函数定义了一个转换,您可以在其中选择要压缩的区域的下端和上端,以及要使用的因子。它直接returns里面的trans
对象就可以使用scale_y_continuous
:
library(scales)
squish_trans <- function(from, to, factor) {
trans <- function(x) {
if (any(is.na(x))) return(x)
# get indices for the relevant regions
isq <- x > from & x < to
ito <- x >= to
# apply transformation
x[isq] <- from + (x[isq] - from)/factor
x[ito] <- from + (to - from)/factor + (x[ito] - to)
return(x)
}
inv <- function(x) {
if (any(is.na(x))) return(x)
# get indices for the relevant regions
isq <- x > from & x < from + (to - from)/factor
ito <- x >= from + (to - from)/factor
# apply transformation
x[isq] <- from + (x[isq] - from) * factor
x[ito] <- to + (x[ito] - (from + (to - from)/factor))
return(x)
}
# return the transformation
return(trans_new("squished", trans, inv))
}
trans()
和 inv()
中的第一行处理使用 x = c(NA, NA)
调用转换的情况。 (我最初写这个问题时ggplot2
的版本似乎没有发生这种情况。不幸的是,我不知道这个startet是哪个版本。)
现在可以使用此功能方便地重做第一部分的情节:
p + scale_y_continuous(trans = squish_trans(-2, 2, 4),
breaks = seq(-6, 6, by = 2))
以下示例显示您可以在任意位置压缩比例尺,这也适用于除点以外的其他几何对象:
df <- data.frame(class = LETTERS[1:4],
val = c(1, 2, 101, 102))
ggplot(df, aes(x = class, y = val)) + geom_bar(stat = "identity") +
scale_y_continuous(trans = squish_trans(3, 100, 50),
breaks = c(0, 1, 2, 3, 50, 100, 101, 102))
让我最后强调一下评论中已经提到的其他内容:这种情节可能会产生误导,应谨慎使用!