Цветовое кодирование сюжетно-текстовых аннотаций по вектору или градиенту

У меня есть целочисленные данные, которые я хочу построить, используя R's plotly как heatmap с элементами цвета heatmap, закодированными по размеру целочисленных данных. Я также хочу аннотировать каждый элемент текстовой аннотацией целого числа, а также раскрасить этот текст по размеру целочисленных данных.

Вот данные:

library(dplyr)

pal <- grDevices::colorRamp(c("black","gray"))
set.seed(1)
df <- rbind(data.frame(col = "a",
                 group = paste0("g",1:20),
                 n = as.integer(runif (20, 1, 20))) %>%
  dplyr::mutate(text.col = rgb(pal((n - min(n))/diff(range(n))),max=255)),
  data.frame(col = "b",
             group = paste0("g",1:20),
             n = as.integer(runif (20, 1, 40))) %>%
    dplyr::mutate(text.col = rgb(pal((n - min(n))/diff(range(n))),max=255)))
df$group <- factor(df$group, levels = paste0("g",1:20))

Таким образом, мой heatmap будет иметь 20 строк, соответствующих df$group, и 2 столбца, соответствующих df$col. Как видите, я указываю цвет каждого элемента в df.

Вот data.frame, указывающий цветовой диапазон цвета фона heatmap для каждого df$col:

colors.df <- data.frame(col = c("a", "b"),
                        fill.low = c("#a6c4ba", "#f2edda"),
                        fill.high = c("#4e8a75", "#b49823"),
                        stringsAsFactors = F)

А вот и мой plotly код:

lapply(c("a","b"), function(l){
  col.df <- dplyr::filter(df, col == l)
  n.text <- as.character(col.df$n)
  plotly::plot_ly(ygap = 1, z = col.df$n, x = col.df$col, y =col.df$group,
                  colors = grDevices::colorRamp(c(dplyr::filter(colors.df,col == l)$fill.low, dplyr::filter(colors.df,col == l)$fill.high)), type = "heatmap") %>%
    plotly::hide_colorbar() %>%
    plotly::add_annotations(font = list(color = col.df$text.col, size = 8),text = n.text,x = col.df$col,y = col.df$group,showarrow = F)
}) %>% plotly::subplot(shareX = T, shareY = T, nrows = 1, margin = 0.001, widths = c(0.5, 0.5))

Который дает: Цветовое кодирование сюжетно-текстовых аннотаций по вектору или градиенту

Как видите, переход col.df$text.col к fontlist в plotly::add_annotations не выполняется, и все текстовые аннотации окрашены в один и тот же цвет.

Есть идеи, как раскрасить их в соответствии с col.df$text.col?

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
24
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Интерпретация Plotly вашего кода привела к тому, что все возможные цвета были перечислены для каждой из 40 аннотаций.

Так откуда я это знаю? Первое, что я сделал, это отправил график объекту, например так:

lapply(c("a","b"), function(l){
  col.df <- dplyr::filter(df, col == l)
  n.text <- as.character(col.df$n)
  plotly::plot_ly(data = col.df, ygap = 1, 
                  z = ~n, x = ~col, y = ~group,
                  colors = grDevices::colorRamp(
                    c(dplyr::filter(colors.df, col == l)$fill.low, 
                      dplyr::filter(colors.df, col == l)$fill.high)), 
                  type = "heatmap") %>%
    plotly::hide_colorbar() %>%
    plotly::add_annotations(font = list(color = ~text.col, size = 8),
                            text = n.text, x = ~col,
                            y = ~group, showarrow = F)
  }) %>% 
  plotly::subplot(shareX = T, shareY = T, nrows = 1, 
                  margin = 0.001, widths = c(0.5, 0.5)) -> a

Я хотел просмотреть объект графика на панели исходного кода. Однако этот сюжет не был законченным построением, поэтому я сделал это следующим.

a <- plotly_build(a)  # embed the JSON data and layout

Затем я снова посмотрел на объект.

Вы можете увидеть список значений цвета на этом изображении. Итак, давайте поможем Plotly определиться с одним цветом, так как сегодня он кажется довольно нерешительным.

lapply(1:40,
       function(k){
         base = a$x$layout$annotations[[k]] # find the annotation
         # find the color that should be there
         col = filter(df, col == base$x, group == base$y) %>%  
           select(text.col) %>% unlist()
         # change the plotly object
         a$x$layout$annotations[[k]]$font$color <<- col
       })
a # take another look at that graph

Это то, что вы хотели, но это действительно трудно читать!

Я выделил текст жирным шрифтом, чтобы посмотреть, улучшится ли разборчивость.

lapply(1:40,
       function(j){
         base = a$x$layout$annotations[[j]]
         t = base$text
         a$x$layout$annotations[[j]]$text <<- paste0('<b>', t, '</b>')
       })

a # any better?

Это немного помогло. Я оставлю это для вас, чтобы понять. Если у вас есть какие-либо вопросы, дайте мне знать.

Другие вопросы по теме