You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Highcharts热力图多色阶设置、元素灰化及缺失值处理(R语言)

实现带数据区分的热力图(Highcharter 优先方案)

针对需求中区分不可靠数据、灰化缺失值的要求,我们可以通过将矩阵转换为长格式数据,结合Highcharter的自定义配置来实现:

完整代码实现

library(highcharter)
library(tidyverse)

# 生成可复现的测试数据
set.seed(123)
mat <- matrix(data = rnorm(4*3, 1, .2), nrow = 4)
rownames(mat) <- c("left arm", "right arm", "left leg", "right leg")
colnames(mat) <- c("a1", "a2", "a3")
mat["left leg", "a1"] <- NA  # 设置a1左腿数据缺失

# 标记不可靠数据(a2、a3的手臂数据)
unreliable_info_mat <- matrix(FALSE, nrow = 4, ncol = 3)
rownames(unreliable_info_mat) <- rownames(mat)
colnames(unreliable_info_mat) <- colnames(mat)
unreliable_info_mat[c("left arm", "right arm"), c("a2", "a3")] <- TRUE

# 转换为长格式数据,便于逐个点配置
heat_data <- mat %>%
  as.data.frame() %>%
  rownames_to_column("body_part") %>%
  pivot_longer(cols = -body_part, names_to = "animal", values_to = "length") %>%
  mutate(unreliable = as.vector(unreliable_info_mat))

# 定义颜色处理函数:降低颜色饱和度
desaturate_color <- function(col, amount = 0.5) {
  col_rgb <- col2rgb(col)
  gray_val <- mean(col_rgb)
  rgb(
    red = round(col_rgb[1]*(1-amount) + gray_val*amount),
    green = round(col_rgb[2]*(1-amount) + gray_val*amount),
    blue = round(col_rgb[3]*(1-amount) + gray_val*amount),
    maxColorValue = 255
  )
}

# 绘制热力图并配置自定义样式
hchart(heat_data, "heatmap", hcaes(x = animal, y = body_part, value = length)) %>%
  # 配置色阶与缺失值颜色
  hc_colorAxis(
    min = min(heat_data$length, na.rm = TRUE),
    max = max(heat_data$length, na.rm = TRUE),
    stops = list(
      list(0, "#4575b4"),
      list(0.5, "#ffffbf"),
      list(1, "#d73027")
    ),
    nullColor = "#cccccc"  # 缺失值设为灰色
  ) %>%
  # 动态修改不可靠数据的颜色(降低饱和度)
  hc_plotOptions(
    heatmap = list(
      point = list(
        events = list(
          load = JS("function() {
            const points = this.series[0].points;
            const colorAxis = this.colorAxis[0];
            points.forEach(point => {
              if (point.options.unreliable) {
                // 计算原始色阶颜色并降低饱和度
                const normVal = (point.y - colorAxis.min) / (colorAxis.max - colorAxis.min);
                const originalColor = colorAxis.toColor(normVal);
                const rgb = Highcharts.color(originalColor).rgb();
                const gray = (rgb[0] + rgb[1] + rgb[2]) / 3;
                const desaturated = `rgb(${Math.round(rgb[0]*0.5 + gray*0.5)}, ${Math.round(rgb[1]*0.5 + gray*0.5)}, ${Math.round(rgb[2]*0.5 + gray*0.5)})`;
                point.update({color: desaturated});
              }
            });
          }")
        )
      )
    )
  ) %>%
  # 自定义tooltip显示数据可靠性
  hc_tooltip(
    formatter = JS("function() {
      const reliability = this.point.unreliable ? '(数据不可靠)' : '';
      const lengthText = this.point.value ? this.point.value.toFixed(2) : '缺失';
      return `<b>${this.y} - ${this.x}</b><br/>长度: ${lengthText} ${reliability}`;
    }")
  ) %>%
  hc_title(text = "动物肢体长度热力图") %>%
  hc_xAxis(title = list(text = "动物")) %>%
  hc_yAxis(title = list(text = "肢体部位"))

关键配置说明

  • 缺失值处理:通过colorAxis的nullColor直接将NA值设为灰色
  • 不可靠数据区分:利用JavaScript事件动态获取每个点的原始颜色,降低饱和度后更新样式
  • tooltip优化:显示数据是否可靠,缺失值标注清晰

Plotly 备选方案

如果需要用Plotly实现,可直接为每个数据点分配自定义颜色:

library(plotly)
library(tidyverse)

# 复用前面生成的heat_data数据
# 为每个点分配颜色
heat_data <- heat_data %>%
  mutate(
    color = case_when(
      is.na(length) ~ "#cccccc",
      unreliable ~ desaturate_color(
        colorRamp(c("#4575b4", "#ffffbf", "#d73027"))(
          (length - min(length, na.rm=T))/(max(length, na.rm=T)-min(length, na.rm=T))
        )
      ),
      TRUE ~ colorRamp(c("#4575b4", "#ffffbf", "#d73027"))(
        (length - min(length, na.rm=T))/(max(length, na.rm=T)-min(length, na.rm=T))
      )
    )
  )

# 绘制热力图
plot_ly(
  data = heat_data,
  x = ~animal,
  y = ~body_part,
  z = ~length,
  type = "heatmap",
  colors = colorRamp(c("#4575b4", "#ffffbf", "#d73027")),
  showscale = TRUE,
  marker = list(color = ~color),  # 覆盖自定义颜色
  text = ~case_when(
    is.na(length) ~ "数据缺失",
    unreliable ~ paste0("长度: ", round(length, 2), "<br/>数据不可靠"),
    TRUE ~ paste0("长度: ", round(length, 2))
  ),
  hoverinfo = "text"
) %>%
  layout(
    title = "动物肢体长度热力图",
    xaxis = list(title = "动物"),
    yaxis = list(title = "肢体部位")
  )

内容的提问来源于stack exchange,提问作者Noskario

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 05:37:34