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

如何在Plotly中制作含空值的平滑热力图并优化空值显示

Plotly热力图空值区域平滑过渡实现方案

Plotly原生的zsmooth对空值区域的处理是硬切割,没法直接实现你要的border-radius式平滑过渡,但可以通过插值填充空值+渐变透明度的组合技巧来模拟自然过渡效果,以下是具体实现:

方法一:插值+透明度渐变

先对空值区域做邻近插值,再给原空值区域设置随距离衰减的透明度,让彩色区域自然过渡到白色背景。

修改后的代码

var originalData = [
  [1, 20, null], 
  [20, null, 60], 
  [30, 60, 1]
];

// 对空值进行邻近插值填充
function interpolateNulls(matrix) {
  const rows = matrix.length;
  const cols = matrix[0].length;
  const interpolated = JSON.parse(JSON.stringify(matrix));
  
  for (let i = 0; i < rows; i++) {
    for (let j = 0; j < cols; j++) {
      if (interpolated[i][j] === null) {
        let neighbors = [];
        // 取上下左右四个方向的有效值
        if (i > 0 && interpolated[i-1][j] !== null) neighbors.push(interpolated[i-1][j]);
        if (i < rows-1 && interpolated[i+1][j] !== null) neighbors.push(interpolated[i+1][j]);
        if (j > 0 && interpolated[i][j-1] !== null) neighbors.push(interpolated[i][j-1]);
        if (j < cols-1 && interpolated[i][j+1] !== null) neighbors.push(interpolated[i][j+1]);
        
        // 取邻居平均值填充空值
        interpolated[i][j] = neighbors.length > 0 
          ? neighbors.reduce((a, b) => a + b, 0) / neighbors.length 
          : 0;
      }
    }
  }
  return interpolated;
}

// 生成透明度矩阵:原空值区域透明度随到最近非空值的距离衰减
function createOpacityMatrix(originalMatrix) {
  const rows = originalMatrix.length;
  const cols = originalMatrix[0].length;
  const opacityMatrix = Array(rows).fill().map(() => Array(cols).fill(1));
  
  for (let i = 0; i < rows; i++) {
    for (let j = 0; j < cols; j++) {
      if (originalMatrix[i][j] === null) {
        let minDistance = Infinity;
        // 计算到最近非空单元格的欧氏距离
        for (let x = 0; x < rows; x++) {
          for (let y = 0; y < cols; y++) {
            if (originalMatrix[x][y] !== null) {
              const distance = Math.sqrt(Math.pow(x - i, 2) + Math.pow(y - j, 2));
              minDistance = Math.min(minDistance, distance);
            }
          }
        }
        // 线性衰减透明度,系数可根据需求调整
        opacityMatrix[i][j] = Math.max(0, 1 - minDistance * 0.5);
      }
    }
  }
  return opacityMatrix;
}

const interpolatedZ = interpolateNulls(originalData);
const opacity = createOpacityMatrix(originalData);

var data = [
  {
    z: interpolatedZ,
    type: 'heatmap',
    zsmooth: 'best',
    colorscale: 'Jet',
    opacity: opacity,
    showscale: true
  }
];

// 设置画布背景为白色,让透明区域显示白色
var layout = {
  plot_bgcolor: 'white',
  paper_bgcolor: 'white'
};

Plotly.plot('myDiv', data, layout, {showSendToCloud: true});

方法二:叠加圆形遮罩(可选)

如果想要更接近圆角(border-radius)的视觉效果,可以在原空值区域叠加半透明白色圆形遮罩,进一步柔化边缘:

补充代码(基于方法一)

// 生成空值位置的圆形遮罩
function createMaskShapes(originalMatrix) {
  const shapes = [];
  const cellHalfSize = 0.5; // 单元格半宽,根据实际布局调整
  
  originalMatrix.forEach((row, i) => {
    row.forEach((val, j) => {
      if (val === null) {
        shapes.push({
          type: 'circle',
          x0: j - cellHalfSize,
          x1: j + cellHalfSize,
          y0: i - cellHalfSize,
          y1: i + cellHalfSize,
          fillcolor: 'white',
          opacity: 0.7, // 遮罩透明度,可调整
          line: {width: 0}
        });
      }
    });
  });
  return shapes;
}

// 更新layout添加遮罩
layout.shapes = createMaskShapes(originalData);

Plotly.plot('myDiv', data, layout, {showSendToCloud: true});

优化提示

  • 插值方式:可以把邻近插值改成双线性插值,让数值过渡更平滑。
  • 透明度衰减:调整衰减系数(1 - minDistance * 0.5中的0.5)可以控制过渡区域的宽窄。
  • 遮罩参数:修改圆形遮罩的opacity和大小,可模拟不同程度的圆角效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 15:10:40