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

Plotly.js颜色映射问题:如何按特定数据值范围设置颜色?

问题描述

开发基于JavaScript的Plotly.js热力图生成函数时,需要实现以下配色规则:

  • 0.1到3.0(及大于3的值):红色系渐变
  • -0.1到-3.0(及小于-3的值):蓝色系渐变
  • -0.1到0.1之间:白色

最初编写的代码中,错误地将colorscale的断点设置为实际z值,而Plotly的colorscale默认使用**归一化比例(0-1区间)**对应z值的极值范围,导致配色不符合预期。尝试过D3线性比例尺但0附近出现灰色,现寻求正确的修改方案。

原代码片段:

// Create heatmap data
let heatmap_data = [{
    z: total_L2FC,
    x: indiv_name_list,
    y: gene_list,
    type: 'heatmap',
    hovertemplate: 'Gene: %{y}<br>Individual: %{x}<br>log2FoldChange: %{z}<br>p-adj: %{customdata}<extra></extra>',
    customdata: total_padj,
    colorscale: [
        // defines colorscale gradient in painstaking fashion...        
        [100, '#970300'],
        [3, '#970300'],
        [3, '#AF0300'],
        [2.67, '#AF0300'],
        [2.67, '#B81F1C'],
        [2.33, '#B81F1C'],
        [2.33, '#C13B39'],
        [2,0, '#C13B39'],
        [2.0, '#CA5755'],
        [1.67, '#CA5755'],
        [1.67, '#D37371'],
        [1.33, '#D37371'],
        [1.33, '#DB8F8E'],
        [1.0, '#DB8F8E'],
        [1.0, '#E4ABAA'],
        [0.67, '#E4ABAA'],
        [0.67, '#EDC7C6'],
        [0.33, '#EDC7C6'],
        [0.33, '#F6E3E3'],
        [0.10, '#F6E3E3'],
        [0.10, '#FFFFFF'],
        [-0.10, '#FFFFFF'],
        [-0.10, '#E3E4F1'],
        [-0.33, '#E3E4F1'],
        [-0.33, '#C6C9E4'],
        [-0.67, '#C6C9E4'],
        [-0.67, '#AAAED6'],
        [-1.0, '#AAAED6'],
        [-1.0, '#8E93C8'],
        [-1.33, '#8E93C8'],
        [-1.33, '#7179BB'],
        [-1.67, '#7179BB'],
        [-1.67, '#555EAD'],
        [-2.0, '#555EAD'],
        [-2.0, '#39439F'],
        [-2.33, '#39439F'],
        [-2.33, '#1C2892'],
        [-2.67, '#1C2892'],
        [-2.67, '#000D84'],
        [-3.0, '#000D84'],
        [-3.0, '#000A63'],
        [-100, '#000A63']
    ],
    hoverongaps: false,
    xaxis: {
        tickangle: 45
    },
    yaxis: {
        autorange: true
    },
    colorbar: {
        title: {
            text: 'log<sub>2</sub>FC',
            font: {
                size: 14
            }
        }
    },
    // Use a function to set the color for each log2FoldChange value
    colors: total_L2FC.map(log2FoldChange => {
        // Assuming log2FoldChange values are within the range of -3.0 to 3.0
        if (log2FoldChange >= -3.0 && log2FoldChange <= 3.0) {
            const normalizedValue = (log2FoldChange + 3.0) / 6.0; // Normalize to the range [0, 1]
            return d3.interpolateTurbo(normalizedValue); // Use a color scale (e.g., turbo) to map the normalized value to a color
        } else {
            return 'gray'; // Default color for values outside the specified range
        }
    }),
    showscale: true,
}];
解决方案

核心修改思路

Plotly的colorscale使用0-1的归一化比例映射z值范围,因此需要先固定z值的极值范围,再将实际z值断点转换为对应比例,同时移除冲突的colors属性。

具体修改步骤

  1. 移除colors属性:该属性会直接为每个单元格指定颜色,完全覆盖colorscale的渐变逻辑,必须删除。
  2. 固定z值范围:设置zauto: false,zmin: -3,zmax: 3,强制Plotly将z值区间[-3, 3]映射到比例区间[0, 1],这样就能精准计算每个颜色断点的比例值。
  3. 重构colorscale:将实际z值断点转换为比例值,公式为(z_val + 3) / 6,确保:
    • 小于等于-3的值使用最深蓝色
    • -3到-0.1之间使用蓝色系渐变
    • -0.1到0.1之间固定为白色
    • 0.1到3之间使用红色系渐变
    • 大于等于3的值使用最深红色
  4. 优化颜色条刻度:设置colorbar.tickvals和ticktext,让颜色条显示实际z值而非比例,提升可读性。

修改后的完整代码

// Create heatmap data
let heatmap_data = [{
    z: total_L2FC,
    x: indiv_name_list,
    y: gene_list,
    type: 'heatmap',
    hovertemplate: 'Gene: %{y}<br>Individual: %{x}<br>log2FoldChange: %{z}<br>p-adj: %{customdata}<extra></extra>',
    customdata: total_padj,
    // 固定z值范围,关闭自动极值计算
    zauto: false,
    zmin: -3,
    zmax: 3,
    // 重构后的colorscale:比例值[0,1]对应z值[-3,3]
    colorscale: [
        // 蓝色系(z <= -3 到 z = -0.1)
        [0, '#000A63'],           // z = -3
        [( -2.67 + 3 ) / 6, '#000D84'], // z = -2.67
        [( -2.33 + 3 ) / 6, '#1C2892'], // z = -2.33
        [( -2.0 + 3 ) / 6, '#39439F'],  // z = -2.0
        [( -1.67 + 3 ) / 6, '#555EAD'], // z = -1.67
        [( -1.33 + 3 ) / 6, '#7179BB'], // z = -1.33
        [( -1.0 + 3 ) / 6, '#8E93C8'],  // z = -1.0
        [( -0.67 + 3 ) / 6, '#AAAED6'], // z = -0.67
        [( -0.33 + 3 ) / 6, '#C6C9E4'], // z = -0.33
        [( -0.1 + 3 ) / 6, '#E3E4F1'],  // z = -0.1
        // 白色区间(z = -0.1 到 z = 0.1)
        [( -0.1 + 3 ) / 6, '#FFFFFF'],
        [( 0.1 + 3 ) / 6, '#FFFFFF'],
        // 红色系(z = 0.1 到 z = 3)
        [( 0.1 + 3 ) / 6, '#F6E3E3'],   // z = 0.1
        [( 0.33 + 3 ) / 6, '#EDC7C6'],  // z = 0.33
        [( 0.67 + 3 ) / 6, '#E4ABAA'],  // z = 0.67
        [( 1.0 + 3 ) / 6, '#DB8F8E'],   // z = 1.0
        [( 1.33 + 3 ) / 6, '#D37371'],  // z = 1.33
        [( 1.67 + 3 ) / 6, '#CA5755'],  // z = 1.67
        [( 2.0 + 3 ) / 6, '#C13B39'],   // z = 2.0
        [( 2.33 + 3 ) / 6, '#B81F1C'],  // z = 2.33
        [( 2.67 + 3 ) / 6, '#AF0300'],  // z = 2.67
        [1, '#970300']                 // z = 3
    ],
    hoverongaps: false,
    xaxis: {
        tickangle: 45
    },
    yaxis: {
        autorange: true
    },
    colorbar: {
        title: {
            text: 'log<sub>2</sub>FC',
            font: {
                size: 14
            }
        },
        // 设置颜色条刻度为实际z值
        tickvals: [-3, -2, -1, -0.1, 0.1, 1, 2, 3],
        ticktext: ['≤-3', '-2', '-1', '-0.1', '0.1', '1', '2', '≥3']
    },
    showscale: true,
}];

关键说明

  • 超出[-3,3]的z值会自动使用colorscale的首尾颜色(最深蓝/最深红),无需额外处理。
  • 白色区间通过在-0.1和0.1对应的比例位置重复设置白色实现,确保中间区间颜色固定。
  • 颜色条的tickvals和ticktext可以根据需求调整,让用户更直观理解配色对应的z值范围。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 00:24:57