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

Plotnine绘制热图遇TypeError:连续值传入离散刻度的解决办法

问题解决:plotnine中连续值传入离散刻度的错误处理

问题描述

使用Polars处理数据时,需要为每个team2条目绘制独立热图,并保持统一调色板以确保跨图颜色可对比。通过mizani.cmap_pal基于全局value的极值归一化,已为每个value生成对应十六进制颜色并存入color列。但循环绘图时,构建value到color的字典并使用plotnine.scale_fill_manual设置填充色,触发错误:

TypeError: Continuous value supplied to discrete scale

数据结构

team1team2typevaluecolor
team1_1team2_118115.850278#443b84
team1_1team2_22624.241389#470e61
team1_2team2_2133.278333#440256
team1_1team2_33094.118333#46327e
team1_3team2_31335.186111#481467
...............
team1_2team2_11867.937778#482576
team1_2team2_4220.0#440154
team1_4team2_2301.199444#440154
team1_1team2_5150.0#440154
team1_1team2_3118.345278#450559

生成color列的代码

from mizani.palettes import cmap_pal

palette = cmap_pal("viridis")
palette_values = (df["value"] - df["value"].min()) / (
            df["value"].max() - df["value"].min()
        )
df = df.with_columns(color=pl.Series(palette(palette_values)))

原绘图循环代码

for t2 in df["team2"].unique():
  df1 = df.filter(pl.col("team2") == t2)
  color_dict = {
    key: value
    for key, value in zip(df1["value"], df1["color"])
  }
  plt = (
    pn.ggplot(
      data=df1.to_pandas(),
      mapping=pn.aes(
        x="team1",
        y="type",
        label="value",
        fill="value",
      ),
    )
    + pn.geom_tile(show_legend=False)
    + pn.scale_fill_manual(color_dict)
    + pn.geom_text(show_legend=False, size=9, format_string="{:.2f}")
  )

错误原因

scale_fill_manual是为离散变量设计的刻度映射工具,而代码中fill绑定的是连续型的value列,导致连续值被传入离散刻度逻辑,触发类型错误。此外,浮点数作为字典键还可能存在精度匹配问题(如两个近似相等的value因浮点精度差异无法匹配对应颜色)。

解决方案

方案一:直接映射预计算的color列

既然已提前为每行计算好对应颜色,可直接将fill映射到color列,无需再通过scale_fill_manual转译:

for t2 in df["team2"].unique():
  df1 = df.filter(pl.col("team2") == t2)
  plt = (
    pn.ggplot(
      data=df1.to_pandas(),
      mapping=pn.aes(
        x="team1",
        y="type",
        label="value",
        fill="color",  # 改为绑定color列
      ),
    )
    + pn.geom_tile(show_legend=False)
    + pn.geom_text(show_legend=False, size=9, format_string="{:.2f}")
  )
  plt.savefig(f"heatmap_team2_{t2}.png")  # 按需保存或展示

方案二:复用全局极值的连续刻度映射

若希望保留fill与value的绑定逻辑,可直接使用连续刻度工具scale_fill_cmap,并传入全局value的极值以确保跨图颜色统一:

# 提前计算全局value的极值
global_min = df["value"].min()
global_max = df["value"].max()

for t2 in df["team2"].unique():
  df1 = df.filter(pl.col("team2") == t2)
  plt = (
    pn.ggplot(
      data=df1.to_pandas(),
      mapping=pn.aes(
        x="team1",
        y="type",
        label="value",
        fill="value",
      ),
    )
    + pn.geom_tile(show_legend=False)
    + pn.scale_fill_cmap(
      palette="viridis",
      limits=(global_min, global_max),  # 强制使用全局极值计算颜色
      na_value="#ffffff"  # 可选:设置缺失值颜色
    )
    + pn.geom_text(show_legend=False, size=9, format_string="{:.2f}")
  )
  plt.savefig(f"heatmap_team2_{t2}.png")

方案对比

  • 方案一适合已预计算颜色的场景,逻辑直接,无需额外处理颜色映射。
  • 方案二更贴合plotnine的连续刻度设计,无需维护额外的color列,自动处理颜色归一化,推荐使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 17:44:53