Holoviews简介
HoloViews 是一个用于数据可视化的 Python 库,旨在简化复杂数据的可视化过程,并促进数据分析与探索。它提供了一种声明性的方法来描述数据与其表示方式,从而使得用户可以更快速地从数据中获取洞察。
以下是 HoloViews 的一些关键特性和功能:
- 声明式接口:HoloViews 提供了一种声明式接口,使得用户可以专注于数据的结构和关系,而不是具体的绘图细节。用户可以通过简单的对象定义来创建复杂的可视化。
- 高效的数据处理:HoloViews 支持大规模数据集的可视化,并且可以与诸如 Dask 和 Pandas 等库集成,以实现高效的数据处理。
- 多种输出格式:它可以与多个后端集成,包括 Matplotlib、Bokeh 和 Plotly,从而支持静态和交互式可视化。用户可以根据需求选择合适的后端。
- 易于集成:HoloViews 可以与其他数据科学工具(如 Jupyter Notebook)无缝集成,适合在交互式环境中进行数据探索。
- 丰富的可视化组件:提供了丰富的图形组件,如曲线图、散点图、直方图、热图等,支持多种数据类型的可视化。
- 可扩展性:用户可以通过扩展 HoloViews 来创建自定义的可视化组件,以满足特定的分析需求。
- 支持动态可视化:HoloViews 支持动态和交互式可视化,允许用户创建动态更新的图表和仪表板,适合于实时数据分析。
- 易于分享和重现:由于其声明式的特性,HoloViews 的可视化可以很容易地被分享和重现,适合于协作和展示。
示例代码
import numpy as np import holoviews as hv hv.extension('bokeh') # 创建数据 x = np.linspace(0, np.pi*4, 100) y = np.sin(x) # 创建曲线图 curve = hv.Curve((x, y), 'x', 'y').opts(title="Sine Wave", width=400)
Holoviews使用指引
基础概念
HoloViews 的声明式编程模型是一种高层次的可视化方法,它强调通过描述数据和其关系来生成可视化,而不是直接指定绘图的细节。这种方法使得用户可以专注于数据本身,而不是如何绘制图形。以下是对
声明式编程模型
- 数据与可视化分离:在声明式编程中,用户主要描述数据的结构和关系,而具体的绘图细节由库来处理。这意味着用户不需要关心如何具体绘制每个点或线,而是描述数据如何映射到可视化。
- 高层次的抽象:HoloViews 提供了一种抽象层,使得用户可以通过少量的代码生成复杂的可视化。这种抽象隐藏了很多低层次的细节,使得代码更简洁、易读。
- 元素(Elements):HoloViews 的基本构建块是“元素”,它们是数据的可视化表示。例如,Curve表示一条线,Scatter 表示一组散点,Image 表示图像数据等。
数据映射到可视化元素
定义元素:用户通过实例化不同的元素类来定义数据的可视化表示。例如:
import holoviews as hv import numpy as np hv.extension('bokeh') # 定义数据 x = np.linspace(0, 10, 100) y = np.sin(x) # 创建一个曲线图元素 curve = hv.Curve((x, y), 'x', 'y')
数据传递:数据通常以数组、列表或 Pandas DataFrame 的形式传递给元素。用户需要指定数据的维度(例如 x 和 y 轴),这些维度将映射到元素的视觉特征。
组合和布局:多个元素可以通过 Overlay 和 Layout 进行组合。例如,+ 运算符可以用于水平布局,* 运算符可以用于叠加多个图形:
scatter = hv.Scatter((x, np.cos(x)), 'x', 'y') combined = curve * scatter # 叠加 layout = curve + scatter # 布局
选项与样式:使用 .opts() 方法,可以为元素添加样式和选项,例如颜色、线宽、标题等:
curve.opts(color='red', line_width=2, title='Sine Curve')
动态与交互:HoloViews 支持动态可视化,可以通过 DynamicMap 创建响应用户交互的图形。
通过这种声明式方法,HoloViews 允许用户用更少的代码生成高质量的可视化,同时使得代码更具可读性和可维护性。这种模型非常适合快速探索数据并创建可重现的分析。
数据结构
HoloViews 支持多种数据结构,这些数据结构主要用于定义和组织不同类型的可视化元素。理解这些数据结构对于有效使用 HoloViews 至关重要。以下是 HoloViews 中常见的数据结构及其用途:
Element(元素)
Element 是 HoloViews 的基本构建块,用于表示单个数据集的可视化。每种 Element 都对应一种特定类型的可视化。常见的 Element 类型:
Curve:表示二维曲线图。
import holoviews as hv import numpy as np hv.extension('bokeh') x = np.linspace(0, 10, 100) y = np.sin(x) curve = hv.Curve((x, y), 'x', 'y')
Scatter:表示散点图。
x = np.random.rand(100) y = np.random.rand(100) scatter = hv.Scatter((x, y))
Histogram:表示直方图。
data = np.random.randn(1000) histogram = hv.Histogram(data)
HeatMap:表示热图。
data = np.random.rand(10, 10) heatmap = hv.HeatMap(data)
Image:表示二维图像。
image_data = np.random.rand(100, 100) image = hv.Image(image_data)
Points:表示点集。
points = np.random.rand(100, 2) point_set = hv.Points(points)
Raster:表示栅格数据。
raster_data = np.random.rand(100, 100) raster = hv.Raster(raster_data)
Text:表示文本注释。
text = hv.Text(0.5, 0.5, "Hello, World!")
Polygons:表示多边形。
polygons = np.array([[0, 0], [1, 0], [1, 1], [0, 1]]) polygon = hv.Polygons([polygons])
Path:表示路径。
path_data = np.array([[0, 0], [1, 1], [2, 0]]) path = hv.Path([path_data])
Container(容器)
Container 用于组织多个 Element 或其他 Container,形成更复杂的可视化布局。常见的 Container 类型:
Overlay:表示多个 Element 的叠加。
overlay = curve * scatter
Layout:表示多个 Element 的水平或垂直布局。
layout = curve + scatter
NdLayout:表示多维布局,常用于动态可视化。
ndlayout = {i: hv.Curve((x, np.sin(x + i))) for i in range(5)}
HoloMap:表示动态映射,可以随着参数变化生成不同的可视化。
holomap = hv.HoloMap({i: hv.Curve((x, np.sin(x + i))) for i in range(5)}, kdims=['Phase'])
Dimension(维度)
Dimension 用于定义数据的维度信息,包括键维度(kdims)和值维度(vdims)。示例:
键维度(kdims):用于索引数据。
ndlayout = {i: hv.Curve((x, np.sin(x + i))) for i in range(5)}
值维度(vdims):用于表示数据的实际值。
curve = hv.Curve((x, y), kdims=['x'], vdims=['y'])
Grouping(分组)
Grouping 用于对多个 Element 进行逻辑分组,便于管理和操作。示例:
Group:表示一组 Element。
group = hv.Group([curve, scatter])
Options(选项)
在 HoloViews 中,.opts() 方法用于定制图形的样式和外观。你可以通过这个方法来设置颜色、大小、标签等属性,从而创建更加美观和易于理解的可视化。以下是如何使用 .opts() 方法的详细说明和示例:
基本使用
.opts() 方法可以直接应用于 HoloViews 的元素(Element)或容器(如 Overlay、Layout)。你可以通过关键字参数来设置各种样式选项。
示例:
import holoviews as hv import numpy as np hv.extension('bokeh') # 创建数据 x = np.linspace(0, 10, 100) y = np.sin(x) # 创建曲线图 curve = hv.Curve((x, y), 'x', 'y') # 使用 .opts() 方法定制样式 curve = curve.opts( color='red', # 设置线条颜色 line_width=2, # 设置线条宽度 xlabel='X Axis', # 设置 x 轴标签 ylabel='Y Axis', # 设置 y 轴标签 title='Sine Wave', # 设置图形标题 show_grid=True # 显示网格 ) # 显示图形 curve
高级使用
.opts() 方法还可以通过传递字典来设置多个属性,或者使用特定的样式对象(如 opts.Curve)来设置。
使用字典:
# 使用字典设置样式 curve_opts = { 'color': 'blue', 'line_dash': 'dashed', 'tools': ['hover'] } curve = curve.opts(**curve_opts)
使用样式对象:
from holoviews import opts # 使用样式对象设置样式 curve = curve.opts( opts.Curve(color='green', line_width=3, tools=['hover']) )
组合样式
对于 Overlay 或 Layout,可以使用 .opts() 方法分别设置每个元素的样式。
示例:
# 创建散点图 scatter = hv.Scatter((x, np.cos(x)), 'x', 'y') # 创建叠加图 overlay = curve * scatter # 使用 .opts() 分别设置每个元素的样式 overlay = overlay.opts( opts.Curve(color='red', line_width=2), opts.Scatter(size=8, color='purple', marker='square') ) # 显示叠加图 overlay
使用场景
- 颜色和大小:设置图形元素的颜色、线条宽度、点的大小等。
- 标签和标题:设置轴标签、图形标题等文本信息。
- 工具和交互:启用或禁用交互工具(如缩放、悬停工具)。
- 网格和背景:控制网格显示、背景颜色等布局选项。
通过使用 .opts() 方法,你可以灵活地定制 HoloViews 图形的外观,使得可视化更符合分析需求和美观标准。
综合示例
下面是一个综合示例,展示了如何使用 HoloViews 的各种数据结构来创建和组合不同的可视化元素:
import holoviews as hv import numpy as np hv.extension('bokeh') # 定义数据 x = np.linspace(0, 10, 100) y = np.sin(x) # 创建曲线图 curve = hv.Curve((x, y), 'x', 'y').opts(color='red', line_width=2) # 创建散点图 scatter = hv.Scatter((x, np.cos(x)), 'x', 'y').opts(color='blue', size=5) # 创建直方图 data = np.random.randn(1000) histogram = hv.Histogram(data).opts(fill_color='green', line_color='black') # 创建热图 heatmap_data = np.random.rand(10, 10) heatmap = hv.HeatMap(heatmap_data).opts(cmap='viridis') # 组合元素 overlay = curve * scatter layout = overlay + histogram + heatmap # 显示图形 layout
通过这些数据结构,HoloViews 提供了一个灵活且强大的框架,使得用户可以轻松地创建和组合各种类型的可视化。
后端集成
HoloViews 支持多种渲染后端,包括 Bokeh、Matplotlib 和 Plotly。选择和配置合适的渲染后端可以帮助你实现所需的静态或交互式输出。以下是如何选择和配置不同渲染后端的详细说明:
Bokeh
Bokeh 是 HoloViews 的默认后端,适用于创建交互式和动态的可视化。它提供了丰富的交互功能,如缩放、平移和工具提示。
使用 Bokeh:
import holoviews as hv hv.extension('bokeh') # 创建一个简单的曲线图 curve = hv.Curve([1, 2, 3, 4, 5]) curve
配置 Bokeh:
Bokeh 提供了许多选项,可以通过 .opts() 方法配置,如工具、图例、标题等。
curve.opts( tools=['hover'], # 启用悬停工具 legend_position='top_left', # 设置图例位置 title='Bokeh Curve' # 设置图形标题 )
Matplotlib
Matplotlib 适用于创建高质量的静态图形。它非常适合生成论文级别的图形。
使用 Matplotlib:
import holoviews as hv hv.extension('matplotlib') # 创建一个简单的直方图 histogram = hv.Histogram([1, 2, 2, 3, 3, 3, 4]) histogram
配置 Matplotlib:
Matplotlib 的样式可以通过 .opts() 方法调整,类似于 Bokeh。
histogram.opts( color='green', # 设置颜色 xlabel='Value', # 设置 x 轴标签 ylabel='Frequency', # 设置 y 轴标签 title='Matplotlib Histogram' # 设置标题 )
Plotly
Plotly 是一个强大的交互式绘图库,适用于需要高度交互和动态更新的场景。
使用 Plotly:
import holoviews as hv hv.extension('plotly') # 创建一个简单的散点图 scatter = hv.Scatter([(1, 2), (2, 3), (3, 4)]) scatter
配置 Plotly:
Plotly 的选项同样可以通过 .opts() 方法进行设置。
scatter.opts( size=10, # 设置点的大小 color='red', # 设置颜色 title='Plotly Scatter Plot' # 设置标题 )
选择合适的后端
- Bokeh:适合需要交互功能的可视化,如实时更新、缩放、工具提示等。默认情况下,HoloViews 使用 Bokeh。
- Matplotlib:适合生成高质量的静态图形,适用于出版物和报告。
- Plotly:适合需要复杂交互和动态更新的场景,支持丰富的交互功能。
切换后端
你可以通过调用 hv.extension() 方法并传入后端名称来切换后端。例如,要在同一个笔记本中切换到不同的后端,可以多次调用 hv.extension():
hv.extension('bokeh') # 使用 Bokeh hv.extension('matplotlib') # 切换到 Matplotlib hv.extension('plotly') # 切换到 Plotly
注意事项
- 确保安装了所需的后端库。例如,使用 Plotly 时需要安装plotly 库。
- 不同后端可能支持的功能和选项有所不同,需要根据具体需求选择合适的后端。
- 在同一个会话中频繁切换后端可能会导致不一致的行为,建议在项目初期确定好后端。
动态可视化
HoloViews 提供了强大的工具来创建动态和交互式可视化,其中 DynamicMap 是一个关键组件。DynamicMap 允许你根据参数的变化实时更新可视化,非常适合需要动态响应用户输入或数据变化的场景。以下是如何使用 DynamicMap 来实现动态和交互式可视化的详细指南。
基本概念
- DynamicMap:DynamicMap是一个动态容器,可以根据参数变化生成不同的可视化。它可以与函数结合使用,根据输入参数实时计算和更新可视化。
- 参数化:通过定义参数范围或使用交互控件(如滑块、选择框),用户可以动态地改变可视化的内容。
创建 DynamicMap
使用函数生成可视化
首先,你需要定义一个函数,该函数根据输入参数返回一个 HoloViews 元素。
import holoviews as hv import numpy as np hv.extension('bokeh') # 定义一个函数,根据参数生成曲线图 def sine_curve(phase): x = np.linspace(0, 10, 100) y = np.sin(x + phase) return hv.Curve((x, y), 'x', 'y').opts(title=f'Sine Curve with Phase {phase}') # 创建 DynamicMap dmap = hv.DynamicMap(sine_curve, kdims='Phase').redim.range(Phase=(0, np.pi*2)) dmap
添加交互控件
HoloViews 会自动为 DynamicMap 创建交互控件(如滑块)以调整参数。你可以通过 .redim.range() 来设置参数的范围。
高级用法
多参数 DynamicMap
你可以为 DynamicMap 定义多个参数,并通过函数处理这些参数。
# 定义一个函数,根据两个参数生成曲线图 def parametric_curve(phase, amplitude): x = np.linspace(0, 10, 100) y = amplitude * np.sin(x + phase) return hv.Curve((x, y), 'x', 'y').opts(title=f'Curve with Phase {phase} and Amplitude {amplitude}') # 创建多参数 DynamicMap dmap_multi = hv.DynamicMap(parametric_curve, kdims=['Phase', 'Amplitude']).redim.range(Phase=(0, np.pi*2), Amplitude=(0.5, 2)) dmap_multi
与小部件结合
你可以将 DynamicMap 与 Panel 库结合使用,以创建更复杂的交互界面。
import panel as pn # 定义小部件 phase_slider = pn.widgets.FloatSlider(name='Phase', start=0, end=np.pi*2, step=0.1, value=0) amplitude_slider = pn.widgets.FloatSlider(name='Amplitude', start=0.5, end=2, step=0.1, value=1) # 将小部件与 DynamicMap 绑定 dmap_bound = hv.DynamicMap(parametric_curve, kdims=[]).redim.values(Phase=phase_slider, Amplitude=amplitude_slider) # 创建面板 pn.Row(pn.Column(phase_slider, amplitude_slider), dmap_bound).servable()
注意事项
- 性能:DynamicMap通过惰性计算来提高性能,只在需要时更新可视化。这对于处理大型数据集或复杂计算非常有用。
- 交互性:在 Jupyter Notebook 中,DynamicMap的交互性可以直接显示。但在其他环境中(如网页应用),可能需要结合 Panel 或 Bokeh Server 来实现完整的交互功能。
- 定制控件:虽然 HoloViews 会自动生成控件,但你可以通过Panel 自定义控件以实现更复杂的交互界面。
通过使用 DynamicMap,你可以轻松创建响应用户输入或数据变化的动态可视化,使得分析和展示更加灵活和互动。
数据管道和转换
HoloViews 提供了数据管道功能,可以在可视化之前对数据进行转换和操作。这对于需要对数据进行预处理的场景非常有用。数据管道可以通过 Stream 和 Pipe 来实现,它们允许你动态更新数据并将这些变化反映在可视化中。
基本概念
- Stream:Stream是 HoloViews 中的一个组件,用于将外部参数变化传递给可视化元素。它可以用来响应用户交互或数据的实时更新。
- Pipe:Pipe是一种特殊的 Stream,用于将数据直接传递给 DynamicMap。它允许你在不重新创建图形的情况下更新数据。
使用 Pipe 进行数据更新
- Pipe 可以用来将新的数据推送到现有的 DynamicMap 中,从而动态更新可视化。适用于需要直接更新数据的场景,可以用于实时数据流的可视化。
import holoviews as hv import numpy as np hv.extension('bokeh') # 创建一个空的 Pipe pipe = hv.streams.Pipe(data=[]) # 定义一个函数,使用 Pipe 中的数据创建散点图 def update_scatter(data): return hv.Scatter(data, 'x', 'y') # 创建 DynamicMap,并将 Pipe 连接到它 dmap = hv.DynamicMap(update_scatter, streams=[pipe]) # 初始显示 dmap 通过向 Pipe 发送新数据,你可以动态更新可视化: python复制代码 # 生成新的随机数据 new_data = np.random.rand(100, 2) # 向 Pipe 发送新数据 pipe.send(new_data)
使用 Stream 进行参数化数据转换
Stream 可以用于响应参数变化,实时更新数据处理逻辑。 用于需要响应参数变化的场景,可以用于动态调整数据处理逻辑。
from holoviews.streams import Stream, param # 定义一个参数化类 class SineWave(param.Parameterized): phase = param.Number(default=0, bounds=(0, np.pi*2)) amplitude = param.Number(default=1, bounds=(0.1, 2)) # 创建一个实例 sine_wave = SineWave() # 定义一个函数,根据参数生成曲线 def sine_curve(phase, amplitude): x = np.linspace(0, 10, 100) y = amplitude * np.sin(x + phase) return hv.Curve((x, y), 'x', 'y') # 创建 Stream,并连接到参数化类 stream = Stream.define('SineWave', phase=sine_wave.param.phase, amplitude=sine_wave.param.amplitude)() # 创建 DynamicMap,并将 Stream 连接到它 dmap = hv.DynamicMap(sine_curve, streams=[stream]) # 显示 dmap 通过改变 sine_wave 的参数,你可以动态更新可视化: # 更新参数 sine_wave.phase = np.pi / 2 sine_wave.amplitude = 1.5
数据转换与操作
在数据管道中,你可以进行各种数据转换和操作,例如过滤、聚合、变换等。这些操作可以在传递给 DynamicMap 的函数中实现。
示例:数据过滤
# 定义一个过滤函数 def filter_data(data, threshold=0.5): filtered_data = data[data[:, 1] > threshold] return hv.Scatter(filtered_data, 'x', 'y') # 创建 DynamicMap,并应用过滤函数 dmap_filtered = hv.DynamicMap(filter_data, streams=[pipe]) # 向 Pipe 发送数据 pipe.send(new_data) # 显示过滤后的数据 dmap_filtered
集成与扩展
HoloViews 可以与其他数据分析库(如 Pandas 和 Dask)无缝集成,以便更有效地处理和可视化数据。此外,你可以通过扩展 HoloViews 的功能来满足特定需求。
与 Pandas 集成
Pandas 是一个强大的数据处理库,HoloViews 可以直接使用 Pandas 的 DataFrame 作为数据源进行可视化。
使用 Pandas DataFrame
import holoviews as hv import pandas as pd hv.extension('bokeh') # 创建一个 Pandas DataFrame data = pd.DataFrame({ 'x': range(10), 'y': [i**2 for i in range(10)] }) # 使用 HoloViews 可视化 DataFrame curve = hv.Curve(data, 'x', 'y').opts(title='Pandas DataFrame Curve') curve
你可以在使用 HoloViews 可视化之前,利用 Pandas 的功能对数据进行预处理。
# 计算移动平均 data['y_avg'] = data['y'].rolling(window=3).mean() # 可视化原始数据和移动平均 curve_original = hv.Curve(data, 'x', 'y').opts(color='blue') curve_avg = hv.Curve(data, 'x', 'y_avg').opts(color='red') # 叠加两个曲线 overlay = curve_original * curve_avg overlay.opts(title='Original and Moving Average')
与 Dask 集成
Dask 是一个并行计算库,适用于处理大规模数据集。HoloViews 可以与 Dask 集成,以便在处理大型数据集时实现高效的可视化。
使用 Dask DataFrame
import dask.dataframe as dd # 创建一个 Dask DataFrame dask_data = dd.from_pandas(data, npartitions=2) # 使用 HoloViews 可视化 Dask DataFrame # 需要确保在处理数据之前将其转换为 Pandas DataFrame curve_dask = hv.Curve(dask_data.compute(), 'x', 'y').opts(title='Dask DataFrame Curve') curve_dask
扩展 HoloViews 功能
HoloViews 的可扩展性使得你可以通过插件或自定义组件来满足特定的需求。
自定义元素
你可以通过继承 HoloViews 的 Element 类来创建自定义可视化元素。
from holoviews.core.element import Element class CustomElement(Element): def __init__(self, data, **params): super().__init__(data, **params) def plot(self): # 自定义绘图逻辑 pass # 使用自定义元素 custom_element = CustomElement(data)
使用 Hooks 扩展功能
HoloViews 提供了 hooks 功能,允许你在渲染图形时执行自定义的 Python 代码。
def custom_hook(plot, element): plot.state.title.text = 'Customized Title' # 应用 hook curve = hv.Curve(data, 'x', 'y').opts(hooks=[custom_hook])
结合其他工具
- Panel:结合 Panel 库创建交互式应用程序或仪表板。
- Datashader:处理和可视化大规模数据集时,可以结合 Datashader 进行高效渲染。
- Bokeh Server:用于创建具有复杂交互功能的 web 应用。
交互和工具
HoloViews 提供了多种交互工具,特别是在使用 Bokeh 作为渲染后端时。这些工具可以显著增强用户与图形的交互性,包括缩放、平移和悬停工具等。通过这些交互工具,用户可以更深入地探索数据和理解可视化内容。
启用交互工具
在 HoloViews 中,可以通过 .opts() 方法来启用和配置交互工具。以下是一些常用的交互工具及其配置方法:
缩放工具
缩放工具允许用户在可视化中放大或缩小特定区域。
import holoviews as hv hv.extension('bokeh') # 创建一个简单的曲线图 curve = hv.Curve([(0, 0), (1, 1), (2, 4), (3, 9)]) # 启用缩放工具 curve.opts( tools=['box_zoom', 'wheel_zoom'], # 启用框选缩放和滚轮缩放 active_tools=['box_zoom'] # 设置默认激活的缩放工具 )
平移工具
平移工具允许用户在可视化中拖动以查看不同的部分。
# 启用平移工具 curve.opts( tools=['pan'], # 启用平移工具 active_tools=['pan'] # 设置默认激活的平移工具 )
悬停工具
悬停工具显示鼠标悬停在数据点上的详细信息。
# 启用悬停工具 curve.opts( tools=['hover'], # 启用悬停工具 hover_line_color='red', # 设置悬停时线条颜色 hover_line_width=2 # 设置悬停时线条宽度 )
组合使用工具
你可以组合多种工具以实现更复杂的交互。
# 启用多种工具 curve.opts( tools=['pan', 'box_zoom', 'wheel_zoom', 'hover'], # 启用多种工具 active_tools=['box_zoom'] # 设置默认激活的工具 )
自定义工具行为
HoloViews 允许你通过 Bokeh 的选项来自定义工具的行为。例如,你可以自定义悬停工具显示的信息。
from bokeh.models import HoverTool # 自定义悬停工具 hover = HoverTool(tooltips=[ ("Index", "$index"), ("(x, y)", "($x, $y)"), ("Value", "@y") ]) # 应用自定义悬停工具 curve.opts( tools=[hover, 'pan', 'box_zoom'] )
使用 Panel 增强交互
结合 Panel 库,你可以创建更复杂的交互界面,例如添加滑块、选择框等控件来动态更新可视化。
import panel as pn # 定义一个滑块 slider = pn.widgets.FloatSlider(name='Multiplier', start=1, end=10, step=0.1, value=1) # 定义一个函数,根据滑块值更新曲线 def update_curve(multiplier): return hv.Curve([(x, y * multiplier) for x, y in zip(range(4), [0, 1, 4, 9])]) # 创建一个动态映射 dmap = hv.DynamicMap(update_curve, streams=[hv.streams.Params(slider, ['value'])]) # 创建一个 Panel 布局 layout = pn.Column(slider, dmap) layout.servable()
参考链接: