将 ggplot 省略号限制为 realistic/possible 值
Constrict ggplot ellips to realistic/possible values
使用 ggplot 绘制椭圆时,是否可以将椭圆限制为实际可能的值?
例如,以下可重现的代码和数据绘制了两个物种的 Ele 与 Var。 Var 是正变量,不能为负。尽管如此,负值包含在生成的椭圆中。是否可以在 x 轴上将椭圆限制为 0(使用 ggplot)?
更具体地说,我描绘了一个平坦的边缘,椭圆体在 x 轴上被截断为 0。
library(ggplot2)
set.seed(123)
df <- data.frame(Species = rep(c("BHS", "MTG"), each = 100),
Ele = c(sample(1500:3000, 100), sample(2500:3500, 100)),
Var = abs(rnorm(200)))
ggplot(df, aes(Var, Ele, color = Species)) +
geom_point() +
stat_ellipse(aes(fill = Species), geom="polygon",level=0.95,alpha=0.2)
您可以编辑默认统计数据以将点数限制为特定值。在这里,我们将基本统计数据更改为 trim x 小于 0 的值变为 0
StatClipEllipse <- ggproto("StatClipEllipse", Stat,
required_aes = c("x", "y"),
compute_group = function(data, scales, type = "t", level = 0.95,
segments = 51, na.rm = FALSE) {
xx <- ggplot2:::calculate_ellipse(data = data, vars = c("x", "y"), type = type,
level = level, segments = segments)
xx %>% mutate(x=pmax(x, 0))
}
)
然后我们必须将它包装在一个与 stat_ellipe
相同的 ggplot stat 中,除了它使用我们的自定义 Stat 对象
stat_clip_ellipse <- function(mapping = NULL, data = NULL,
geom = "path", position = "identity",
...,
type = "t",
level = 0.95,
segments = 51,
na.rm = FALSE,
show.legend = NA,
inherit.aes = TRUE) {
layer(
data = data,
mapping = mapping,
stat = StatClipEllipse,
geom = geom,
position = position,
show.legend = show.legend,
inherit.aes = inherit.aes,
params = list(
type = type,
level = level,
segments = segments,
na.rm = na.rm,
...
)
)
}
然后你可以用它来制作你的情节
ggplot(df, aes(Var, Ele, color = Species)) +
geom_point() +
stat_clip_ellipse(aes(fill = Species), geom="polygon",level=0.95,alpha=0.2)
这是受 source code for stat_ellipse 的启发。
根据我上面的评论,我创建了一个不那么误导的可视化选项。这忽略了 y
均匀分布的问题,因为与严重偏斜的 x
变量相比,这是一个稍微不那么令人震惊的问题。
这两个选项都使用 ggforce
package,它是 ggplot2
的扩展,但为了以防万一,我还包含了我使用的特定函数的源代码。
library(ggforce)
library(scales)
# power_trans <- function (n)
# {
# scales::trans_new(name = paste0("power of ", fractions(n)), transform = function(x) {
# x^n
# }, inverse = function(x) {
# x^(1/n)
# }, breaks = scales::extended_breaks(), format = scales::format_format(),
# domain = c(0, Inf))
# }
选项 1:
ggplot(df, aes(Var, Ele, color = Species)) +
geom_point() +
stat_ellipse(aes(fill = Species), geom="polygon",level=0.95,alpha=0.2) +
scale_x_sqrt(limits = c(-0.1,3.5),
breaks = c(0.0001,1:4),
labels = 0:4,
expand = c(0.00,0))
此选项沿平方根变换拉伸 x 轴,散布聚集在零附近的点。然后它在这个新 space 上计算一个椭圆。
- 优点:看起来还是椭圆。
- 缺点:为了让它更好地发挥并在 x 轴上标记
Var=0
点,您必须使用 expand = c(0,0)
,它会精确地限制限制,因此需要一点更多地摆弄手动 limits/breaks/labels,包括选择一个非常小的值 (0.0001) 表示为 0.
- 缺点:x 值不是沿轴线性分布,这在阅读图形时需要更多的认知负荷。
选项 2:
ggplot(df, aes(sqrt(Var), Ele, color = Species)) +
geom_point() +
stat_ellipse() +
coord_trans(x = ggforce::power_trans(2)) +
scale_x_continuous(breaks = sqrt(0:4), labels = 0:4,
name = "Var")
此选项绘制预转换的 sqrt(Var)
(注意 aes(...)
)。然后它根据这个新的近似正常值计算椭圆。然后它拉伸 x 轴,使 Var
的值再次线性 spaced,这会在同一变换中扭曲椭圆。
- 优点:好看
- 优点:Var 的值在 x 轴上很容易解释。
- 优点:可以很容易地看到"egg"的点和宽平端在Var=0附近的密度。
- 优点:尖端向您显示这些值的密度有多低。
- 缺点:看起来不熟悉,需要解释和额外的认知负担来解释。
使用 ggplot 绘制椭圆时,是否可以将椭圆限制为实际可能的值?
例如,以下可重现的代码和数据绘制了两个物种的 Ele 与 Var。 Var 是正变量,不能为负。尽管如此,负值包含在生成的椭圆中。是否可以在 x 轴上将椭圆限制为 0(使用 ggplot)?
更具体地说,我描绘了一个平坦的边缘,椭圆体在 x 轴上被截断为 0。
library(ggplot2)
set.seed(123)
df <- data.frame(Species = rep(c("BHS", "MTG"), each = 100),
Ele = c(sample(1500:3000, 100), sample(2500:3500, 100)),
Var = abs(rnorm(200)))
ggplot(df, aes(Var, Ele, color = Species)) +
geom_point() +
stat_ellipse(aes(fill = Species), geom="polygon",level=0.95,alpha=0.2)
您可以编辑默认统计数据以将点数限制为特定值。在这里,我们将基本统计数据更改为 trim x 小于 0 的值变为 0
StatClipEllipse <- ggproto("StatClipEllipse", Stat,
required_aes = c("x", "y"),
compute_group = function(data, scales, type = "t", level = 0.95,
segments = 51, na.rm = FALSE) {
xx <- ggplot2:::calculate_ellipse(data = data, vars = c("x", "y"), type = type,
level = level, segments = segments)
xx %>% mutate(x=pmax(x, 0))
}
)
然后我们必须将它包装在一个与 stat_ellipe
相同的 ggplot stat 中,除了它使用我们的自定义 Stat 对象
stat_clip_ellipse <- function(mapping = NULL, data = NULL,
geom = "path", position = "identity",
...,
type = "t",
level = 0.95,
segments = 51,
na.rm = FALSE,
show.legend = NA,
inherit.aes = TRUE) {
layer(
data = data,
mapping = mapping,
stat = StatClipEllipse,
geom = geom,
position = position,
show.legend = show.legend,
inherit.aes = inherit.aes,
params = list(
type = type,
level = level,
segments = segments,
na.rm = na.rm,
...
)
)
}
然后你可以用它来制作你的情节
ggplot(df, aes(Var, Ele, color = Species)) +
geom_point() +
stat_clip_ellipse(aes(fill = Species), geom="polygon",level=0.95,alpha=0.2)
这是受 source code for stat_ellipse 的启发。
根据我上面的评论,我创建了一个不那么误导的可视化选项。这忽略了 y
均匀分布的问题,因为与严重偏斜的 x
变量相比,这是一个稍微不那么令人震惊的问题。
这两个选项都使用 ggforce
package,它是 ggplot2
的扩展,但为了以防万一,我还包含了我使用的特定函数的源代码。
library(ggforce)
library(scales)
# power_trans <- function (n)
# {
# scales::trans_new(name = paste0("power of ", fractions(n)), transform = function(x) {
# x^n
# }, inverse = function(x) {
# x^(1/n)
# }, breaks = scales::extended_breaks(), format = scales::format_format(),
# domain = c(0, Inf))
# }
选项 1:
ggplot(df, aes(Var, Ele, color = Species)) +
geom_point() +
stat_ellipse(aes(fill = Species), geom="polygon",level=0.95,alpha=0.2) +
scale_x_sqrt(limits = c(-0.1,3.5),
breaks = c(0.0001,1:4),
labels = 0:4,
expand = c(0.00,0))
此选项沿平方根变换拉伸 x 轴,散布聚集在零附近的点。然后它在这个新 space 上计算一个椭圆。
- 优点:看起来还是椭圆。
- 缺点:为了让它更好地发挥并在 x 轴上标记
Var=0
点,您必须使用expand = c(0,0)
,它会精确地限制限制,因此需要一点更多地摆弄手动 limits/breaks/labels,包括选择一个非常小的值 (0.0001) 表示为 0. - 缺点:x 值不是沿轴线性分布,这在阅读图形时需要更多的认知负荷。
选项 2:
ggplot(df, aes(sqrt(Var), Ele, color = Species)) +
geom_point() +
stat_ellipse() +
coord_trans(x = ggforce::power_trans(2)) +
scale_x_continuous(breaks = sqrt(0:4), labels = 0:4,
name = "Var")
此选项绘制预转换的 sqrt(Var)
(注意 aes(...)
)。然后它根据这个新的近似正常值计算椭圆。然后它拉伸 x 轴,使 Var
的值再次线性 spaced,这会在同一变换中扭曲椭圆。
- 优点:好看
- 优点:Var 的值在 x 轴上很容易解释。
- 优点:可以很容易地看到"egg"的点和宽平端在Var=0附近的密度。
- 优点:尖端向您显示这些值的密度有多低。
- 缺点:看起来不熟悉,需要解释和额外的认知负担来解释。