使用 Datashader 从 NumPy 数组绘制数据的最佳方法是什么?

What is the best method for using Datashader to plot data from a NumPy array?

Datashader example notebook demonstrating lines 之后,输入是 Pandas DataFrame(尽管 Dask DataFrame 似乎也可以)。我的数据在 NumPy 数组中。我可以使用 Datashader 绘制 NumPy 数组中的线条,而无需先将它们放入 DataFrame 中吗?

line glyph 的文档似乎表明这是可能的,但我没有找到示例。我链接到的示例笔记本使用了我在文档中找不到的 Canvas.line

我没有找到在 NumPy 数组中绘制数据而不先将其放入 DataFrame 的方法。如何做到这一点并不是特别直观,Datashader 似乎要求列标签为 non-numeric 字符串,因此可以使用 df.col_label 语法调用它们(而不是 df[col_label] 语法,也许不过这是有充分理由的。

在当前系统中,我必须执行以下操作才能将 NumPy 数组放入具有 Datashader 可接受的列标签的 DataFrame 中。

df = pd.DataFrame(data=data.T)
data_cols = ['c{}'.format(c) for c in df.columns]
df.columns = data_cols
df['x'] = x_values

y_range = data.min(), data.max()
x_range = x_values[0], x_values[-1]

canvas = datashader.Canvas(x_range=x_range, y_range=y_range, 
                           plot_height=300, plot_width=900)
aggs = collections.OrderedDict((c, canvas.line(df, 'q', c)) for c in data_cols)

merged = xarray.concat(saxs_aggs.values(), dim=pd.Index(cols, name='cols'))
saxs_img = datashader.transfer_functions.shade(merged.sum(dim='cols'), 
                                               how='eq_hist')

请注意,使用 data_cols 变量很重要,而不是简单地使用 df.columns,因为它必须排除 x 列(最初不直观)。

这是使用散景添加轴的结果示例。

OrderedDictxarray.concat 方法在应用于许多数据曲线时非常慢。以下示例演示了一种更快的方法。有关时间安排和进一步讨论,请参阅 this GitHub issue

import pandas as pd
import numpy as np
import datashader
import bokeh.plotting
import collections
import xarray
import time
from bokeh.palettes import Colorblind7 as palette

bokeh.plotting.output_notebook()

# create some data worth plotting
nx = 50
x = np.linspace(0, np.pi * 2, nx)
y = np.sin(x)
n = 10000
data = np.empty([n+1, len(y)])
data[0] = x
prng = np.random.RandomState(123)

# scale the data using a random normal distribution
offset = prng.normal(0, 0.1, n).reshape(n, -1)
data[1:] = y
data[1:] += offset

# make some data noisy
n_noisy = prng.randint(0, n,5)
for i in n_noisy:
    data[i+1] += prng.normal(0, 0.5, nx)

dfs = []
split = pd.DataFrame({'x': [np.nan]})
for i in range(len(data)-1):
    x = data[0]
    y = data[i+1]
    df = pd.DataFrame({'x': x, 'y': y})
    dfs.append(df)
    dfs.append(split)

df = pd.concat(dfs, ignore_index=True)   

canvas = datashader.Canvas(x_range=x_range, y_range=y_range, 
                           plot_height=300, plot_width=300)
agg = canvas.line(df, 'x', 'y', datashader.count())
img = datashader.transfer_functions.shade(agg, how='eq_hist')
img