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

如何让datashader绘制分类数据时将NA值设为灰色及关联问题问询

修复后完整代码
import numpy as np
import pandas as pd
import holoviews as hv
hv.extension('bokeh')
import datashader as ds
from datashader.colors import Sets1to3
from holoviews.operation.datashader import datashade,spread

raw_data = [('Alice', 60, 'London', 5) ,
           ('Bob', 14, 'Delhi' , 7) ,
           ('Charlie', 66, np.NaN, 11) ,
           ('Dave', np.NaN,'Delhi' , 15) ,
           ('Eveline', 33, 'Delhi' , 4) ,
           ('Fred', 32, 'New York', np.NaN ),
           ('George', 95, 'Paris', 11)
            ]
# 创建DataFrame
df = pd.DataFrame(raw_data, columns=['Name', 'Age', 'City', 'Experience'])
df['City']=pd.Categorical(df['City'])

x='Age'
y='Experience'
color='City'

# ---------------------- 核心问题修复:处理NA分类 ----------------------
# 将NaN转为明确的分类值,加入分类列表
df[color] = df[color].cat.add_categories('NA').fillna('NA')
cats = df[color].cat.categories

# 构造显式颜色映射,NA设为灰色
color_key = {}
color_idx = 0
for cat in cats:
    if cat == 'NA':
        color_key[cat] = '#808080'
    else:
        color_key[cat] = Sets1to3[color_idx]
        color_idx += 1

# ---------------------- 图例构造 ----------------------
for cat in cats:
    print(cat,((df[color]==cat)&(df[x].notnull())&(df[y].notnull())).sum())
color_points = hv.NdOverlay({n: hv.Points([0,0], label=str(n)).opts(color=c,size=0) for n,c in color_key.items()})

# ---------------------- 绘图 ----------------------
points=hv.Points(df, [x, y],label="%s vs %s" % (x, y),)
# 1. 传入显式color_key保证配色匹配 2. 用ds.any()聚合消除密度影响,保证点尺寸统一
datashaded=datashade(
    points,
    aggregator=ds.by(color, ds.any()),
    color_key=color_key
).opts(width=800, height=480)

# spread参数固定,保证点大小一致
(spread(datashaded,px=4, shape='square')*color_points).opts(legend_position='right')

问题解决说明

核心问题:NA点设为灰色

datashader默认不会将分类列的NaN识别为独立分类,会默认匹配色阶最后一个颜色。修复逻辑为:

  • 先调用cat.add_categories将'NA'加入分类列表,再用fillna把所有NaN替换为该分类值
  • 构造颜色映射时单独为'NA'分类指定灰色值

次要问题:散点尺寸不统一

原来的聚合方式默认是按点数量计数,重叠点的颜色强度会变化,看起来尺寸不一致。修复方法为在ds.by中传入ds.any()作为聚合函数,只要对应位置有该分类的点就显示固定颜色,不会受点密度影响,配合spread的固定px参数即可保证所有点尺寸统一。


疑问解答

  1. datashader分类配色逻辑:如果没有传入显式color_key参数,会按分类列的.cat.categories顺序依次匹配传入的色阶值,所以分类顺序变化后配色就会错位。你只需要像上述代码一样构造字典格式的color_key显式传入datashade方法,就可以保证图例和绘图的配色永远匹配,不受分类顺序影响。
  2. 使用Points元素完全合理。Holoviews中Scatter用于存在明确自变量、因变量关系的场景,Points就是专为两个无因果关系的变量的散点分布设计的,符合你的使用需求。

你提到的所有问题相关性较强,不需要单独拆分提问。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 20:39:02