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
相关产品推荐
相关产品推荐

