1

我正在尝试为一组模型的准确性创建一个图,这些模型的两个参数组合不同。任何模型的准确度都不会超过 0.98,并且大多数模型的准确度在 0.94 到 0.98 之间(顺便说一句,这只是实践,没有真正的研究)。我发现使用scale_color_viridis_c()withlimits = c(.96, .98)values = c(.25, 1)产生一个很好的渐变,可以很好地可视化精度分布,但是这样我不能让 color_bar 上升到 1 - 它以 0.98 结束。

我的第一种方法是设置limits = c(0.96, 1)and values = c(.125, 0.5),但这会导致高于 0.98 的每个值都注册为 NA,与低于 0.96 的值相同。然后我尝试将第一个图与与第一个相同的第二个图分层,但将数据点着色为精度 > 0.98 黑色(即没有)并“填充”上部的 NA(即 0.98 到 1)第一个带有黑色的 color_bar,并且所有内容都较低透明。

我创建了一个示例:

library(ggplot2)
library(ggnewscale)

set.seed(123)

# variable 1
v1 <- numeric()
for (i in 1:50) {
  v1 <- c(v1, rep(i, 56))
}

# variable 2
v2 <- rep(seq(50, 600, 10), 50)

# creating preliminary df
df <- data.frame(v1 = v1, v2 = v2)

# creating mock accuracy data
acc <- apply(df, 1, function(x) {
  temp_acc <- runif(1, 1, 10) * x[1]^0.6 / x[2]^0.65 * -1
})
acc <- (-1 * (acc / (10 * min(acc)))) - runif(1, -0.01, 0.01) + 0.99
acc <- acc - (max(acc) - 0.98) - 0.0005

#create complete df
df$acc <- acc

#plotting
g <- ggplot(data =  df, aes(x  = v1, y = v2, color = acc)) +
  geom_point() + scale_color_viridis_c(values = c(.125, 0.5), na.value = "grey80",
                                       breaks = seq(0.96, 1, 0.005), limits = c(0.96, 1),
                                       guide = guide_colorbar(barheight = 10)) +
  new_scale_color() +
  geom_point(aes(color = acc), alpha = 0.2) +
  scale_color_gradientn(colors = "black",
                        values = c(0.5, 1), na.value = NA,
                        breaks = seq(0.96, 1, 0.005), limits = c(0.96, 1),
                        guide = guide_colorbar(barheight = 10))
g

这几乎完全符合我的要求 - 情节部分很完美,但我希望将两个 color_bars 合并为一个。有没有办法做到这一点?或者从不同的角度来处理它:有没有办法为连续色标设置两个阈值,并让高于/低于这些阈值的数据通过组合的 color_bar 以不同的颜色着色?

这只是出于美观的原因,我可以使用图像编辑软件甚至 MSPaint 轻松完成这项任务,但我希望能够仅根据我的数据在 R 中完成这一切,而不是人工编辑。

提前致谢!

大卫

用模拟数据绘制

4

3 回答 3

1

我想出了如何解决我的问题,或者至少是一种对我来说足够好的解决方法——关键是viridis()直接从rainbow(). 我之前尝试过,但没有成功,因为我没有library(viridis)加载或指定它,viridis::viridis()所以我错误地得出结论,没有类似viridis().

但事实证明,你可以,所以这是我的代码:

library(ggplot2)
library(ggnewscale)
library(viridis)

set.seed(123)

# variable 1
v1 <- numeric()
for (i in 1:50) {
  v1 <- c(v1, rep(i, 56))
}

# variable 2
v2 <- rep(seq(50, 600, 10), 50)

# creating preliminary df
df <- data.frame(v1 = v1, v2 = v2)

# creating mock accuracy data
acc <- apply(df, 1, function(x) {
  temp_acc <- runif(1, 1, 10) * x[1]^0.6 / x[2]^0.65 * -1
})
acc <- (-1 * (acc / (10 * min(acc)))) - runif(1, -0.01, 0.01) + 0.99
acc <- acc - (max(acc) - 0.98) - 0.0005

# create complete df
df$acc <- acc

# grabbing the scale colors from viridis() and appending grey80,
# yielding a color vector that has the continuous viridis color of the length I need it,
# and then switches to a solid color of my choice
color_vector <- c(viridis(length(acc)), rep("grey80", times = length(acc)))

# plotting
g <- ggplot(data =  df, aes(x  = v1, y = v2, color = acc)) +
  geom_point() + scale_color_gradientn(colors = color_vector,
                                       values = c(0.2, 1), na.value = "grey45",
                                       guide = guide_colorbar(barheight = 15),
                                       breaks = seq(0.95, 1, 0.005),limits = c(0.95, 1))
g

我实际上将高于 0.98 的(不存在的)值更改为以"grey80"而不是"black"表示,并且将 NA.values(即低于 0.96 的所有值)从"grey80"更改为"grey45" - 我发现它更直观那样明确。

这是它的外观: imgurlink 因为我还不能添加图片

尽管如此,感谢您的建议,它们将在其他情况下派上用场!:)

于 2020-05-07T07:36:56.507 回答
0

我不确定我是否理解你的问题,但根据你的例子和你想要的(“融合”两个尺度)这可以吗?没必要ggnewscale,太让我失望了️</p>

library(ggplot2)

set.seed(123)

# variable 1
v1 <- numeric()
for (i in 1:50) {
  v1 <- c(v1, rep(i, 56))
}

# variable 2
v2 <- rep(seq(50, 600, 10), 50)

# creating preliminary df
df <- data.frame(v1 = v1, v2 = v2)

# creating mock accuracy data
acc <- apply(df, 1, function(x) {
  temp_acc <- runif(1, 1, 10) * x[1]^0.6 / x[2]^0.65 * -1
})
acc <- (-1 * (acc / (10 * min(acc)))) - runif(1, -0.01, 0.01) + 0.99
acc <- acc - (max(acc) - 0.98) - 0.0005

#create complete df
df$acc <- acc

#plotting
ggplot(data =  df, aes(x  = v1, y = v2, color = acc)) +
  geom_point(aes(alpha = acc >= .965)) + 
  scale_alpha_discrete(range = c(0.2, 1), guide = "none") +
  scale_color_viridis_c(values = c(.125, 0.5), na.value = "black",
                        breaks = seq(0.96, 1, 0.005), 
                        limits = c(0.96, 1),
                        guide = guide_colorbar(barheight = 10)) 
#> Warning: Using alpha for a discrete variable is not advised.

reprex 包(v0.3.0)于 2020-05-06 创建

于 2020-05-06T18:02:35.640 回答
0

这可能不是实现您想要的最“程序化”的方式,因为您必须对第二组限制进行硬编码,但您可以进入规模的越界行为。您可以通过oob使用自己创建的函数设置参数来做到这一点。在这种情况下,我们将封装squish()scales 包中的函数,以使任何超出限制的值都成为最近的限制。

#plotting
g <- ggplot(data =  df, aes(x  = v1, y = v2, color = acc)) +
  geom_point() + 
  scale_color_viridis_c(
    values = c(.125, 0.5), na.value = "grey80",
    breaks = seq(0.96, 1, 0.005), limits = c(0.96, 1),
    guide = guide_colorbar(barheight = 10),
    oob = function(x, ...){scales::squish(x, c(0.965, 0.98))}
  )
g

于 2020-05-05T22:16:02.057 回答