Есть ли способ добавить цвет solid после порога с помощью scale_color_viridis_ c из ggplot? Или наслоить легенды / цветовые полосы с помощью ggnewscale? - PullRequest
0 голосов
/ 05 мая 2020

Я пытаюсь создать график точности набора моделей, которые различаются комбинацией двух параметров. Точность не превышает 0,98 для любой модели, а большинство моделей имеют точность от 0,94 до 0,98 (кстати, это просто практика, а не настоящие исследования). Я обнаружил, что использование scale_color_viridis_c() с limits = c(.96, .98) и values = c(.25, 1) дает хороший градиент, который хорошо визуализирует распределение точности, но в этом случае у меня не может быть color_bar go до 1 - он заканчивается на 0,98.

Мой первый подход заключался в установке limits = c(0.96, 1) и 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?

Это только для эстетики c причин, и я мог бы легко выполнить sh эту задачу с помощью программного обеспечения для редактирования изображений, даже MSPaint, но я хотел бы иметь возможность делать все это в R на основе исключительно моих данных, без искусственного редактирования.

Заранее спасибо!

Дэвид

график с фиктивными данными

Ответы [ 3 ]

0 голосов
/ 06 мая 2020

Я не совсем уверен, что понял ваш вопрос, но, исходя из вашего примера и того, что вы хотите ("объединить" обе шкалы), будет ли это нормально? Это не требует ggnewscale, к моему большому разочарованию ?️

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.

Создано 06.05.2020 пакетом REPEX (v0.3.0)

0 голосов
/ 07 мая 2020

Я выяснил, как решить мою проблему, или, по крайней мере, обходной путь, который работает для меня достаточно хорошо - ключом были напрямую получены значения цвета из viridis(), как вы бы с rainbow(). Я пробовал это раньше, и это не сработало, потому что у меня не было загружено library(viridis) или указано его как viridis::viridis(), поэтому я ошибочно пришел к выводу, что нет ничего похожего на viridis().

Но как оказалось out, вы можете, поэтому вот мой код:

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. (т.е. все ниже 0,96) от "grey80" до "grey45" - таким образом я обнаружил, что это более однозначно визуально.

Вот как это выглядит: imgurlink, потому что я пока не могу добавлять картинки

Тем не менее, спасибо за ваши предложения, они пригодятся в других ситуациях! :)

0 голосов
/ 06 мая 2020

Это, вероятно, не самый «программный c» способ достичь того, чего вы хотите, так как вам придется жестко закодировать второй набор ограничений, но вы можете попасть в поведение вне пределов масштаб. Вы можете сделать это, установив аргумент oob с функцией, созданной вами. В этом случае мы обернем функцию squish() из пакета scale, чтобы любые значения, выходящие за пределы, стали ближайшим пределом.

#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

...