如何在 ggplot 中创建更好的渐变?
How to create better gradients in ggplot?
我正在尝试为热图创建百分比梯度比例。我有一些极端的例子 - 像这样的百分比向量。
x = c(100, 1, 2, 1.4, 0.5, -2, -90, 0.3, 2.3)
这意味着当我附加渐变时——无论是连续渐变还是合并渐变——几乎不可能区分较小的百分比值。有没有一种方法可以影响梯度以区分例如1% 和 2% 更明显?
您可以选择在 scale_fill_gradientn
范围内接近的颜色,或者,如果您想要一个通用的解决方案而无需任何摆弄(并且不介意 non-isometric 范围),您可以实现的最佳分离是简单地使用 rank
作为转换。
为了清楚地说明这一点,让我们使用您提供的示例制作一个光栅:
df <- expand.grid(x = 1:10, y = 1:10)
z <- c(100, 1, 2, 1.4, 0.5, -2, -90, 0.3, 2.3)
set.seed(69)
df$z <- sample(z, 100, replace = TRUE)
library(ggplot2)
ggplot(df, aes(x, y, fill = z)) +
geom_raster() +
scale_fill_viridis_c()
尽管我们有 9 个不同的级别,但我们只能看到 3 个不同的填充。
将此与以下内容进行比较:
ggplot(df, aes(x, y, fill = rank(z))) +
geom_raster() +
scale_fill_viridis_c(breaks = quantile(rank(df$z)),
labels = quantile(df$z),
name = "z")
这给出了一个平滑的渐变条但是奇怪的标签。你可以做相反的事情(有正常的标签但是有一个跳跃的颜色条)像这样:
scale_fill_viridis_opt <- function(x)
{
x <- sort(unique(x))
x <- (x[-1] + x[-length(x)])/2
y <- (x - min(x))/diff(range(x))
scale_fill_gradientn(values = y, colours = viridis::viridis(length(x)))
}
ggplot(df, aes(x, y, fill = z)) +
geom_raster() +
scale_fill_viridis_opt(df$z)
或者,如果您想尝试通过转换来防止这些问题,您可以尝试带符号的 n 次根,您可以在其中调整 n 以适合您的数据。您的标签和颜色之间的间距很好,但标签的物理意义较小。在这里,我们通过有符号的立方根得到合理的平衡:
signed_nth_root <- function(x, n = 2) {
sign(x) * abs(x)^(1/n)
}
ggplot(df, aes(x, y, fill = signed_nth_root(z, 3))) +
geom_raster() +
scale_fill_viridis_c()
由 reprex package (v0.3.0)
于 2020-08-04 创建
我正在尝试为热图创建百分比梯度比例。我有一些极端的例子 - 像这样的百分比向量。
x = c(100, 1, 2, 1.4, 0.5, -2, -90, 0.3, 2.3)
这意味着当我附加渐变时——无论是连续渐变还是合并渐变——几乎不可能区分较小的百分比值。有没有一种方法可以影响梯度以区分例如1% 和 2% 更明显?
您可以选择在 scale_fill_gradientn
范围内接近的颜色,或者,如果您想要一个通用的解决方案而无需任何摆弄(并且不介意 non-isometric 范围),您可以实现的最佳分离是简单地使用 rank
作为转换。
为了清楚地说明这一点,让我们使用您提供的示例制作一个光栅:
df <- expand.grid(x = 1:10, y = 1:10)
z <- c(100, 1, 2, 1.4, 0.5, -2, -90, 0.3, 2.3)
set.seed(69)
df$z <- sample(z, 100, replace = TRUE)
library(ggplot2)
ggplot(df, aes(x, y, fill = z)) +
geom_raster() +
scale_fill_viridis_c()
尽管我们有 9 个不同的级别,但我们只能看到 3 个不同的填充。
将此与以下内容进行比较:
ggplot(df, aes(x, y, fill = rank(z))) +
geom_raster() +
scale_fill_viridis_c(breaks = quantile(rank(df$z)),
labels = quantile(df$z),
name = "z")
这给出了一个平滑的渐变条但是奇怪的标签。你可以做相反的事情(有正常的标签但是有一个跳跃的颜色条)像这样:
scale_fill_viridis_opt <- function(x)
{
x <- sort(unique(x))
x <- (x[-1] + x[-length(x)])/2
y <- (x - min(x))/diff(range(x))
scale_fill_gradientn(values = y, colours = viridis::viridis(length(x)))
}
ggplot(df, aes(x, y, fill = z)) +
geom_raster() +
scale_fill_viridis_opt(df$z)
或者,如果您想尝试通过转换来防止这些问题,您可以尝试带符号的 n 次根,您可以在其中调整 n 以适合您的数据。您的标签和颜色之间的间距很好,但标签的物理意义较小。在这里,我们通过有符号的立方根得到合理的平衡:
signed_nth_root <- function(x, n = 2) {
sign(x) * abs(x)^(1/n)
}
ggplot(df, aes(x, y, fill = signed_nth_root(z, 3))) +
geom_raster() +
scale_fill_viridis_c()
由 reprex package (v0.3.0)
于 2020-08-04 创建