如何在使用Datashader + Bokeh后端的HoloViews中进行链接数据选择

4
让我先赞扬一下HoloViews的开发者,这个东西真的很神奇。只是由于它有很多组件,有点难以弄清楚如何将它们全部组合起来以实现我的目标 :)
我试图做多维数据绘图关联,即我希望有几个图表显示相同数据在不同维度上的视图。然后,我想利用Bokeh选择工具,在一个图表中选择数据,并查看其在其他图表中的位置。但我还需要使用Datashader来完成它,因为我的数据集很大。
这是我到目前为止的进展(在Python 2的Jupyter笔记本中运行)。
import numpy as np
import pandas as pd
import holoviews as hv
import holoviews.operation.datashader as hvds
hv.notebook_extension('bokeh')
%opts Scatter [tools=['box_select', 'lasso_select']] (size=10 nonselection_color='red' color='blue') Layout [shared_axes=True shared_datasource=True]

# Create some data to plot
x1 = np.arange(0,10,1e-2)
x2 = np.arange(0,10,1e-2)
X1,X2 = np.meshgrid(x1,x2)
x1 = X1.flatten()
x2 = X2.flatten()
x3 = np.sin(x1) * np.cos(x2)
x4 = x1**2 + x2**2

# Pandas dataframe object from the data 
print "Creating Pandas dataframe object"
df = pd.DataFrame.from_dict({"x1": x1, "x2": x2, "x3": x3, "x4": x4})

# Put the dataframe into a HoloViews table
dtab = hv.Table(df)

# Make some linked scatter plots using datashader
scat1 = dtab.to.scatter('x1', 'x2', [])
scat2 = dtab.to.scatter('x1', 'x3', [])
scat3 = dtab.to.scatter('x2', 'x4', [])
hvds.datashade(scat1) + hvds.datashade(scat2) + hvds.datashade(scat3)

这将产生以下结果:

enter image description here

这很简单易懂,但并不完全符合我的要求。数据范围和平移的更改是相互关联的,这非常棒,但是一个图表范围之外的数据仍然可以在其他图表上绘制。我希望所有图表中的数据都消失,只看到落在所有查看的数据范围内的数据,以便在多维空间中动态选择一些超立方体数据进行突出显示。

此外,最好使Bokeh选择工具以同样的方式工作,这样例如我可以选择某个图表上的一些点,并在其他图表上以红色或其他颜色显示它们。尽管我请求了'box_select'和'lasso_select',但我根本没有得到选择工具。我可能请求它们不正确,因为我不太清楚HoloViews如何传递选项。

2个回答

4

参考James的回答(https://dev59.com/TKLia4cB1Zd3GeqPfTTP#44288019),我对问题示例进行了扩展。它将一个绘图作为“主”控制源,并仅在该绘图数据范围内出现的数据绘制到一堆“从”绘图上。虽然这样已经很酷了,但有双向关系会更好。

import numpy as np
import pandas as pd
import holoviews as hv
import holoviews.operation.datashader as hvds
hv.notebook_extension('bokeh')
%opts Layout [shared_axes=False shared_datasource=True]

# Create some data to plot
x1 = np.arange(0,10,1e-2)
x2 = np.arange(0,10,1e-2)
X1,X2 = np.meshgrid(x1,x2)
x1 = X1.flatten()
x2 = X2.flatten()
x3 = np.sin(x1) * np.cos(x2)
x4 = x1**2 + x2**2

# Pandas dataframe object from the data 
print "Creating Pandas dataframe object"
df = pd.DataFrame.from_dict({"x1": x1, "x2": x2, "x3": x3, "x4": x4})

# Make some linked scatter plots using datashader
x1_x2 = hv.Points(df[['x1', 'x2']])
#x1_x3 = hv.Points(df[['x1', 'x3']])
#x2_x4 = hv.Points(df[['x2', 'x4']])

from holoviews import streams

maindata=x1_x2
mainx='x1'
mainy='x2'
def create_dynamic_map(xvar,yvar):
    def link_function(x_range, y_range):
        x_min = x_range[0]; x_max = x_range[1]
        y_min = y_range[0]; y_max = y_range[1]
        pts = hv.Points(df[  (getattr(df,mainx) > x_min) & (getattr(df,mainx) < x_max) 
                           & (getattr(df,mainy) > y_min) & (getattr(df,mainy) < y_max) 
                          ][[xvar, yvar]])
        return pts
    dmap = hv.DynamicMap(link_function, 
                     streams=[hv.streams.RangeXY(x_range=(-100,100), 
                                                 y_range=(-100,100), 
                                                 source=maindata)],
                     kdims=[])
    return dmap

x1_x3 = create_dynamic_map('x1','x3')
x2_x4 = create_dynamic_map('x2','x4')

hvds.datashade(x1_x2) + hvds.datashade(x1_x3) + hvds.datashade(x2_x4)

4

哦,非常好!您有没有关于第二部分的想法?即仅使用数据选择而不是图形范围?如果我正确传递工具选项,这可能会自动有效地工作。 - Ben Farmer
文档中应该有使用数据选择的示例,但如果您没有看到它们,请在gitter频道上询问。 - James A. Bednar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接