Colors 调整holoviews bokeh中的colormap以匹配值的分布

Colors 调整holoviews bokeh中的colormap以匹配值的分布,colors,bokeh,color-mapping,holoviews,Colors,Bokeh,Color Mapping,Holoviews,我使用以下选项在jupyter笔记本的Holoviews中创建了一个带有bokeh扩展的地图: %output size=150 %opts Overlay [show_legend=True, width=800 height=400] %opts Points.Data [color_index='b' size_index='a' scaling_factor=10 colorbar=True](cmap='RdYlGn' size=3) “b”和“a”都是介于-1和1之间的变量 这会产

我使用以下选项在jupyter笔记本的Holoviews中创建了一个带有bokeh扩展的地图:

%output size=150
%opts Overlay [show_legend=True, width=800 height=400]
%opts Points.Data [color_index='b' size_index='a' scaling_factor=10 colorbar=True](cmap='RdYlGn' size=3)
“b”和“a”都是介于-1和1之间的变量

这会产生两个问题(也比较图片):

  • 根据变量“a”的绝对值调整点的大小。但是,我希望值产生更小(更大)的点,值越负(正)。对此有何解决方案(除了在绘图前将“a”重新缩放到正范围)
  • 由于“b”的正值明显多于负值,因此几乎所有点a都映射为绿色,而颜色范围的负值部分很少使用。我不想转换“b”,因为它的值有意义,我希望在颜色图例中显示。有没有建议如何调整颜色贴图以更好地反映“b”值的分布
  • 我不熟悉holoviews/bokeh,还不习惯语法。因此,我也很欣赏示例代码


    第一个问题的答案非常简单,
    支持一个
    size\fn
    选项,您可以使用该选项在绘制之前转换大小值,例如将点偏移1就可以了。第二个问题比较棘手,没有直接的答案。如果低于0分,我会考虑发散彩色图是否是正确的选择。也许只需将颜色维度的范围设置为0-1,使用标准颜色贴图,并为范围之外的值设置特殊颜色

    # Make some fake data
    lon, lat = np.random.rand(2, 100)*180-90
    a = np.clip((np.random.randn(100) + 1)/2., -1, 1)
    b = np.clip((np.random.randn(100) + 1)/2., -1, 1)
    df = pd.DataFrame({'lon': lon, 'lat': lat, 'a': a, 'b': b})
    
    gv.tile_sources.EsriImagery * gv.Points(df, ['lon', 'lat']).options(
        width=600, height=400, color_index='a', size_fn=lambda x: x+1, 
        scaling_factor=20, size_index='b', colorbar=True, cmap='Greens', 
        clipping_colors={'min': "red"}
    ).redim.range(a=(0, 1))
    

    在上面的示例中,我使用
    size\u fn
    将颜色值偏移1,这样它们都是正值,并且可以缩放。其次,我使用
    .redim.range
    方法将颜色值的范围设置为0-1。最后,我使用了
    clipping_colors
    来表示任何低于最小值(0)的值都应该被涂成红色。

    要回答#2,您可以从默认颜色贴图中创建自己的颜色贴图,并从颜色贴图的末端删除任意多的颜色(更改开始/停止),如下所示

    from matplotlib.colors import LinearSegmentedColormap
    import matplotlib.pyplot as plt
    cmap_name = 'RdBu_r'
    start = 0.4
    stop = 1
    n = 256
    cmap = plt.get_cmap(cmap_name)
    colors = cmap(np.linspace(start, stop, cmap.N))
    new_cmap = LinearSegmentedColormap.from_list('mycmap', colors=colors, N=n)
    
    然后执行
    points=points.redim.range(数据=(-0.2,1))

    作为一个例子,在下面,我删掉了RdBu_r中所有的蓝色,只留下红色