首页 > 解决方案 > 绘制分类数据时如何告诉数据着色器对 NA 值使用灰色

问题描述

我有非常大的数据集,我无法直接使用全息视图进行绘制。我想用分类数据制作散点图。不幸的是,我的数据非常稀疏,许多点都将 NA 作为类别。我想让这些点变灰。有什么方法可以让数据着色器知道我想做什么?

我向您展示我现在的做法(正如https://holoviews.org/user_guide/Large_Data.html中或多或少提出的那样)。我给你举个例子:

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)
            ]
# Create a DataFrame object
df = pd.DataFrame(raw_data, columns=['Name', 'Age', 'City', 'Experience'])
df['City']=pd.Categorical(df['City'])



x='Age'
y='Experience'
color='City'
cats=df[color].cat.categories





# Make dummy-points (currently the only way to make a legend: https://holoviews.org/user_guide/Large_Data.html)
for cat in cats:
    #Just to make clear how many points of a given category we have
    print(cat,((df[color]==cat)&(df[x].notnull())&(df[y].notnull())).sum())
color_key=[(name,color) for name, color in zip(cats,Sets1to3)]
color_points = hv.NdOverlay({n: hv.Points([0,0], label=str(n)).opts(color=c,size=0) for n,c in color_key})


# Create the plot with datashader
points=hv.Points(df, [x, y],label="%s vs %s" % (x, y),)
datashaded=datashade(points,aggregator=ds.by(color)).opts(width=800, height=480)

(spread(datashaded,px=4, shape='square')*color_points).opts(legend_position='right')

它产生以下图片: 散点图的图片

您可以看到一些问题:最重要的是,虽然只有一个来自巴黎的人,但您会看到 NA 人(查理)也印有紫色,这是巴黎的颜色。有没有办法让点变灰?我尝试了很多情节,似乎 NA 总是采用图例中最后一项的颜色。

然后有一些我不想提出问题的小问题。(如果您认为他们应该提出自己的问题,请告诉我,我是 stackoverflow 的新手,感谢您的建议。)

另一个问题:这些点的大小并不相同。这是相当丑陋的。有没有办法改变它?

然后我还有一个问题:datashader内部是否也使用.cat.categories-method来决定使用什么颜色?数据着色器使用的颜色是如何确定的?因为我想知道图例是否总是按正确的顺序排列(显示正确的颜色:如果您在cats那时排列顺序color_key并且cats不再按相同的顺序并且图例显示错误的颜色)。它似乎总是像我一样工作,但我觉得有点不安全。

也许有人想给出他们的意见Points,在这种情况下是否可以用于散点图。因为我没有看到任何区别,Scatter并且在语义上也没有真正的一个变量会导致另一个变量(尽管有人可能会争辩说在这种情况下年龄会导致经验,但我将绘制不容易找到的变量那些类型的因果关系)所以Points如果我正确理解文档https://holoviews.org/reference/elements/bokeh/Points.html最好使用。

标签: pythonbokehscatter-plotholoviewsdatashader

解决方案


最重要的是,虽然只有一个人来自巴黎,但您会看到 NA 人(查理)也印有紫色,这是巴黎的颜色。有没有办法让点变灰?我尝试了很多情节,似乎 NA 总是采用图例中最后一项的颜色。

现在我相信 Datashader 用零替换 NaN(参见https://github.com/holoviz/datashader/blob/master/datashader/transfer_functions/__init__.py#L351)。能够为 Datashader 提供用于 NaN 的颜色似乎是一个很好的功能请求,但与此同时,我建议将 NaN 替换为实际的类别名称,例如“其他”或“缺失”或“未知” ,然后着色和图例都应反映该名称。

另一个问题:这些点的大小并不相同。这是相当丑陋的。有没有办法改变它?

通常,Bokeh HoloViews 图中的 Datashader 最初会在放入 Bokeh 布局之前渲染一次,一旦布局完成最终版本,就会触发更新。在这里,初始渲染被自动调整到精确的数据点范围,然后被绘图的边界剪裁(使边缘附近的正方形变成矩形),然后一旦图例被更新,绘图的范围就会更新添加。要查看它是如何工作的,请删除*color_points,您将看到相同形状的点,但现在被绘图边缘裁剪:

裁剪点

您可以通过在显示后稍微缩放或平移来手动触发对绘图的更新,但要强制它更新而无需手动干预,您可以提供明确的绘图范围:

points=hv.Points(df, [x, y],label="%s vs %s" % (x, y),).redim.range(Age=(0,90), Experience=(0,14))

固定的

如果您可以在 HoloViews 上提交错误报告,询问为什么在包含图例的情况下它没有自动刷新,那就太好了。希望有一个简单的修复!

数据着色器内部是否也使用 .cat.categories 方法来决定使用什么颜色?数据着色器使用的颜色是如何确定的?因为我想知道图例是否总是按正确的顺序排列(显示正确的颜色:如果你在猫中排列顺序,那么 color_key 和猫的顺序不再相同,图例显示错误的颜色)。它似乎总是像我一样工作,但我觉得有点不安全。

确实!无论何时显示图例,都应确保将颜色键作为字典传递,以便确保图例和绘图着色对每个类别使用相同的颜色。color_key={k:v for k,v in color_key}打电话的时候直接进来datashade

在这种情况下,也许有人想就点是否可以用于散点图发表意见。因为我看不出与 Scatter 有任何区别,并且在语义上也没有真正的一个变量会导致另一个变量(尽管有人可能会争辩说在这种情况下年龄会导致经验,但我将绘制不容易绘制的变量找到这些因果关系),所以如果我正确理解了文档https://holoviews.org/reference/elements/bokeh/Points.html ,最好使用 Points 。

点适用于两个轴可互换的平面中的 2D 位置,例如几何平面上的物理 x,y 位置。Points 有两个独立的维度,并且希望您将任何相关维度用于颜色、标记形状等。确实,如果您不知道哪个变量可能依赖于另一个变量,那么 Scatter 很难使用,但简单地选择在 x 轴上放置一些东西会让人们认为该变量是独立的,因此对此无能为力。在这种情况下绝对不适合使用积分。


推荐阅读