如何在R的Plotly热力图中用colorscale指定缺失数据颜色
Plotly热力图NA值灰色显示优化方案
需求与问题
使用R的plotly绘制热力图时,需要实现:
- 缺失值(NA)单元格显示为灰色
- 所有有效数据(含负数)使用自定义配色板
当前通过替换NA为极小值+设置colorscale的方式,导致最小有效数据也被显示为灰色,需修复该问题。
可复现代码
library(tidyverse) library(plotly) df <- structure(list(pop1 = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 5L, 5L, 6L), levels = c("MCap-KUR", "MCap-LAY", "MCap-LIS", "MCap-MAR", "MCap-MAU", "MCap-ORG", "MCap-PH" ), class = "factor"), pop2 = structure(c(6L, 5L, 4L, 3L, 2L, 1L, 5L, 4L, 3L, 2L, 1L, 4L, 3L, 2L, 1L, 3L, 2L, 1L, 2L, 1L, 1L ), levels = c("MCap-PH", "MCap-ORG", "MCap-MAU", "MCap-MAR", "MCap-LIS", "MCap-LAY", "MCap-KUR"), class = "factor"), val = c(0.0595442225256261, 0.0321423361492723, NA, 0.0350934030053142, 0.0345727091303639, 0.0721309262141394, 0.00633228225335393, NA, 0.0267124927202649, 0.0148571426201043, 0.0414373761542232, NA, 0.0178640375765284, NA, 0.0208313289311733, NA, NA, NA, 0.0150516521752213, 0.0762165451237571, 0.0521814425563684)), row.names = c(NA, -21L), class = c("tbl_df", "tbl", "data.frame")) colorscale <- list( list(0, "darkgrey"), list(1e-05, "darkgrey"), list(1e-05, "#000004FF"), list(0.1, "#170C3AFF"), list(0.2, "#420A68FF"), list(0.3, "#6B186EFF"), list(0.4, "#932667FF"), list(0.5, "#BB3754FF"), list(0.6, "#DD513AFF"), list(0.7, "#F3771AFF"), list(0.8, "#FCA50AFF"), list(0.9, "#F6D645FF"), list(1, "#FCFFA4FF") ) df <- df %>% mutate( newval = replace_na(val, min(val, na.rm = T)*1e-5), disp = as.character(val) ) df %>% plot_ly() %>% add_trace( type = "heatmap", x = ~pop1, y = ~pop2, z = ~newval, zmin = ~min(val, na.rm = TRUE), zmax = ~max(val, na.rm = TRUE), colorscale = colorscale, customdata = ~disp, hovertemplate = "%{customdata}" )
最优解决方案:原生参数na.color
Plotly热力图原生支持na.color参数,无需修改NA值,直接指定缺失值的颜色,是最简洁且可靠的方案:
代码实现
# 计算有效数据的极值 data_min <- min(df$val, na.rm = TRUE) data_max <- max(df$val, na.rm = TRUE) # 直接使用原始数据绘制 df %>% plot_ly() %>% add_trace( type = "heatmap", x = ~pop1, y = ~pop2, z = ~val, # 保留原始NA值 zmin = data_min, zmax = data_max, # 自定义配色板(示例为inferno色系) colorscale = list( list(0, "#000004FF"), list(0.1, "#170C3AFF"), list(0.2, "#420A68FF"), list(0.3, "#6B186EFF"), list(0.4, "#932667FF"), list(0.5, "#BB3754FF"), list(0.6, "#DD513AFF"), list(0.7, "#F3771AFF"), list(0.8, "#FCA50AFF"), list(0.9, "#F6D645FF"), list(1, "#FCFFA4FF") ), na.color = "darkgrey", # 直接设置NA值的显示颜色 customdata = ~as.character(val), hovertemplate = "%{customdata}" )
方案优势
- 无需修改原始数据:保留NA值,逻辑更清晰
- 完美兼容正负数据:有效数据完全映射到自定义配色区间,最小有效值不会被误标为灰色
- 代码简洁高效:利用原生参数,避免复杂的数值替换和colorscale计算
替代方案:自定义数值映射(兼容旧版Plotly)
如果使用的Plotly版本不支持na.color,可通过将NA映射到有效数据范围外的数值实现:
# 计算有效数据极值 data_min <- min(df$val, na.rm = TRUE) data_max <- max(df$val, na.rm = TRUE) # 设置NA映射值:远小于有效数据最小值(兼容负数) na_val <- data_min - abs(data_min) * 10 # 调整colorscale:将NA值区间设为灰色,有效数据区间用自定义配色 colorscale <- list( list(0, "darkgrey"), list((na_val - data_min)/(data_max - data_min), "darkgrey"), list((na_val - data_min)/(data_max - data_min), "#000004FF"), list(0.1, "#170C3AFF"), list(0.2, "#420A68FF"), list(0.3, "#6B186EFF"), list(0.4, "#932667FF"), list(0.5, "#BB3754FF"), list(0.6, "#DD513AFF"), list(0.7, "#F3771AFF"), list(0.8, "#FCA50AFF"), list(0.9, "#F6D645FF"), list(1, "#FCFFA4FF") ) # 替换NA并绘图 df <- df %>% mutate( newval = replace_na(val, na_val), disp = as.character(val) ) df %>% plot_ly() %>% add_trace( type = "heatmap", x = ~pop1, y = ~pop2, z = ~newval, zmin = data_min, zmax = data_max, colorscale = colorscale, customdata = ~disp, hovertemplate = "%{customdata}" )
内容的提问来源于stack exchange,提问作者Luther Blissett
相关产品推荐
相关产品推荐

