一个Plotly热图

警告: 此笔记本需要一个运行中的内核才能完全交互,请在本地运行或在 mybinder 上运行。

Binder

仪表板: 或者通过使用Voila渲染此笔记本来获取仪表板:

voila

一个Plotly热图#

确保你先完成了Vaex-jupyter教程

创建自己的可视化的最简单方法是遵循与Vaex-jupyter教程中描述的类似方法,我们在那里使用matplotlib来创建图表。然而,当使用plotly时,我们可以首先构建小部件,并在每次回调时更新相关组件。这比每次更新时创建一个全新的小部件要高效得多。

为了解决这个两步过程(初始化和更新),我们编写了一个实现dunder调用方法的包装类,使其可调用(像函数一样)。

[1]:
import vaex
import numpy as np
import vaex.jupyter.model as vjm
import matplotlib.pyplot as plt

# Fetch a dataset
df = vaex.datasets.helmi_de_zeeuw.fetch()
[2]:
# Define the axes
extend = 50
x_axis = vjm.Axis(df=df, expression=df.x, shape=100, min=-extend, max=extend)
y_axis = vjm.Axis(df=df, expression=df.y, shape=140, min=-extend, max=extend)
# in this case we need to know the min and max directly
await vaex.jupyter.gather()
[3]:
import plotly.graph_objs as go

class PlotlyHeatmap:
    def __init__(self, x_axis, y_axis, figure_height=500, figure_width=400, title="Hi vaex, hi plotly"):
        self.x_axis = x_axis
        self.y_axis = y_axis
        self.heatmap = go.Heatmap()
        self.layout = go.Layout(height=figure_height,
                                width=figure_width,
                                title=title,
                                xaxis=go.layout.XAxis(title=str(x_axis.expression),
                                                      range=[x_axis.min, x_axis.max]
                                                     ),
                                yaxis=go.layout.YAxis(title=str(y_axis.expression),
                                                      range=[y_axis.min, y_axis.max]
                                                     )
                               )
        self.fig = go.FigureWidget(data=[self.heatmap], layout=self.layout)
        # we respond to zoom/pan
        self.fig.layout.on_change(self._pan_and_zoom, 'xaxis.range', 'yaxis.range')

    def _pan_and_zoom(self, layout, xrange, yrange):
        self.x_axis.min, self.x_axis.max = xrange
        self.y_axis.min, self.y_axis.max = yrange

    def __call__(self, data_array):
        ar = data_array.data  # take the numpy array data
        assert data_array.ndim == 2
        dim_x = data_array.dims[0]
        dim_y = data_array.dims[1]
        x0, x1 = data_array.coords[dim_x].attrs['min'], data_array.coords[dim_x].attrs['max']
        y0, y1 = data_array.coords[dim_y].attrs['min'], data_array.coords[dim_y].attrs['max']
        dx = (x1 - x0)/data_array.shape[0]
        dy = (y1 - y0)/data_array.shape[1]

        z = np.log1p(ar).T
        self.fig.update_traces(dict(z=z, x0=x0, y0=y0, dx=dx, dy=dy))
        heatmap_plotly.fig.update_layout(
            xaxis=go.layout.XAxis(title=dim_x, range=[x0, x1]),
            yaxis=go.layout.YAxis(title=dim_y, range=[y0, y1])
        )


heatmap_plotly = PlotlyHeatmap(x_axis, y_axis)
[4]:
# we use `heatmap_plotly` as a callable function
da_view = df.widget.data_array(axes=[x_axis, y_axis], display_function=heatmap_plotly)

# we display the progress bar and possible output (stack traces)
display(da_view)

# and the plotly figure widget
display(heatmap_plotly.fig)

我们还可以创建表达式小部件来直接编辑上图上的轴

[5]:
x_widget = df.widget.expression(x_axis)
y_widget = df.widget.expression(y_axis)
display(x_widget)
display(y_widget)

使用 ipyvuetify 我们可以创建漂亮的按钮并为它们分配一些功能:

[6]:
import ipyvuetify as v

# A button to reset the figure ot its initial state
button_reset = v.Btn(children=['reset'])

def reset(*ignore_arguments):
    x_axis.expression = df.x
    y_axis.expression = df.y
button_reset.on_event('click', reset)

# A button that presents a specific figure
button_fireball = v.Btn(children=['fireball'])

def fireball(*ignore_arguments):
    x_axis.expression = np.log(df.x**2)
    y_axis.expression = df.y
button_fireball.on_event('click', fireball)

preset_widget = v.Col(children=[button_reset, button_fireball])
preset_widget

Voila vuetify 设置#

我们可以使用Voila更优雅地展示在此笔记本中创建的可视化。

[7]:
from vaex.jupyter.widgets import ContainerCard, Html, LinkList
[9]:
LinkList(items=
    [{'title': 'Vaex', 'url': 'https://vaex.io', 'img': 'https://vaex.io/img/logos/logo-grey.svg', },
     {'title': 'Vaex on GitHub', 'url': 'https://github.com/vaexio/vaex', 'img': 'https://github.githubassets.com/pinned-octocat.svg'},
     {'title': 'Vaex DataFrame server', 'url': 'http://dataframe.vaex.io/', 'icon': 'mdi-database'},
     {'title': 'Voila (dashboard)', 'url': 'https://github.com/voila-dashboards/voila', 'icon': 'dashboard'},
     {'title': 'Plotly', 'url': 'https://plotly.com/', 'img': 'https://plotly.com/img/favicon.ico'},
    ], _metadata={'mount_id': 'content-nav'})
[10]:
card_widget = ContainerCard(title=f'{len(df):,} Simulated stars',
                            subtitle="using vaex-jupyter",
                            main=heatmap_plotly.fig,
                            controls=[x_widget, y_widget, preset_widget],
                            show_controls=True,
                            card_props={'style': 'width: 420px;', 'class': 'pa-2 ma-4'},
                            _metadata={'mount_id': 'content-main'}
                           )
[11]:
# You do not have to render the widget for it to show up in voila-vuetify
card_widget
[12]:
Html(tag='span',
     children=['Simulated stars'],
     _metadata={'mount_id': 'content-bar'})
Html(tag='span',
     children=['Resources'],
     _metadata={'mount_id': 'content-title'});

screenshot