【交互式数据可视化】Plotly完全指南:10种高级图表+实战案例 | Python数据分析必备技能

Plotly:交互式图表开发详解

一、Plotly 简介

Plotly 是一个功能强大的 Python 数据可视化库,专注于创建交互式、出版级别的图表和仪表板。相比于 Matplotlib 和 Seaborn 这类静态图表库,Plotly 的核心优势在于其原生支持交互功能,使用户可以直接与图表进行交互,包括缩放、平移、悬停信息显示等。

1.1 Plotly 的主要特点

  • 交互性:支持丰富的用户交互方式,如缩放、平移、选择数据点等
  • 跨平台:可以在 Jupyter Notebook、Web 应用和移动设备上运行
  • 美观性:默认样式现代化,符合当代数据可视化审美
  • 多样性:支持超过40种图表类型,从基础的散点图到复杂的3D图表
  • 兼容性:支持与 Pandas、NumPy 等数据处理库无缝集成
  • 可扩展性:支持自定义组件和布局

1.2 安装和基本配置

# 安装 Plotly
pip install plotly

# 对于 Jupyter Notebook 用户,建议安装 nbformat
pip install nbformat

# 如果需要离线使用,还可以安装 plotly-orca
pip install plotly-orca

基本导入和配置:

import plotly.graph_objects as go  # 低级接口
import plotly.express as px  # 高级接口
import plotly.io as pio

# 设置默认渲染模式
pio.renderers.default = "notebook"  # Jupyter Notebook
# pio.renderers.default = "browser"  # 浏览器

二、Plotly 核心组件

2.1 基本架构

Plotly 的 Python 库主要有两个核心接口:

  1. Plotly Express (px):高级接口,类似于 Seaborn,提供简洁的语法快速创建常见图表
  2. Graph Objects (go):低级接口,提供精细控制图表的每个方面,适合创建自定义和复杂的可视化

2.2 Figure 对象

在 Plotly 中,Figure 对象是可视化的基础,它由以下核心组件组成:

  • data:包含要绘制的数据集和图表类型
  • layout:定义图表的外观(标题、坐标轴、图例等)
  • frames:用于创建动画
  • config:控制用户交互选项
import plotly.graph_objects as go

# 创建一个 Figure 对象
fig = go.Figure(
    data=[go.Scatter(x=[1, 2, 3], y=[1, 3, 2])],
    layout=go.Layout(title="简单散点图示例")
)

# 显示图表
fig.show()

三、基础图表类型

3.1 散点图和线图

使用 Plotly Express:

import plotly.express as px
import pandas as pd

# 样本数据
df = pd.DataFrame({
    'x': [1, 2, 3, 4, 5],
    'y': [1, 3, 2, 4, 3],
    'size': [10, 20, 15, 25, 30],
    'category': ['A', 'B', 'A', 'B', 'A']
})

# 散点图
fig = px.scatter(df, x='x', y='y', size='size', color='category',
                hover_name='category', title='交互式散点图')
fig.show()

# 折线图
fig = px.line(df, x='x', y='y', color='category', title='交互式折线图')
fig.show()

使用 Graph Objects:

import plotly.graph_objects as go

# 散点图
fig = go.Figure()
fig.add_trace(go.Scatter(
    x=[1, 2, 3, 4, 5],
    y=[1, 3, 2, 4, 3],
    mode='markers',  # 'markers'表示散点图
    marker=dict(size=[10, 20, 15, 25, 30], color=['red', 'blue', 'red', 'blue', 'red']),
    text=['A', 'B', 'A', 'B', 'A'],
    name='数据系列'
))
fig.update_layout(title='自定义散点图', xaxis_title='X轴', yaxis_title='Y轴')
fig.show()

3.2 柱状图和条形图

import plotly.express as px
import pandas as pd

# 样本数据
df = pd.DataFrame({
    '水果': ['苹果', '香蕉', '橙子', '草莓', '葡萄'],
    '销量': [20, 14, 23, 17, 19],
    '价格': [5, 3, 4, 7, 6]
})

# 柱状图
fig = px.bar(df, x='水果', y='销量', color='水果',
             hover_data=['价格'], title='各类水果销量对比')
fig.show()

# 条形图(水平柱状图)
fig = px.bar(df, y='水果', x='销量', color='水果',
             orientation='h', title='各类水果销量对比(水平)')
fig.show()

3.3 饼图和环形图

import plotly.express as px
import pandas as pd

# 样本数据
df = pd.DataFrame({
    '类别': ['类别A', '类别B', '类别C', '类别D', '类别E'],
    '数值': [20, 15, 30, 25, 10]
})

# 饼图
fig = px.pie(df, values='数值', names='类别', title='类别占比分析')
fig.show()

# 环形图
fig = px.pie(df, values='数值', names='类别', title='类别占比分析(环形图)',
             hole=0.4)  # hole参数控制中心孔的大小
fig.show()

四、高级交互特性

4.1 悬停信息与工具提示

import plotly.express as px
import pandas as pd
import numpy as np

# 创建示例数据
np.random.seed(42)
df = pd.DataFrame({
    'x': np.random.normal(0, 1, 100),
    'y': np.random.normal(0, 1, 100),
    'group': np.random.choice(['A', 'B', 'C'], 100),
    'size': np.random.uniform(5, 20, 100),
    'extra': np.random.uniform(0, 1, 100)
})

# 自定义悬停信息
fig = px.scatter(df, x='x', y='y', color='group', size='size',
                hover_data={
                    'x': ':.2f',  # 保留两位小数
                    'y': ':.2f',
                    'extra': True,  # 显示额外数据
                    'size': False  # 不显示size
                },
                labels={'x': 'X轴', 'y': 'Y轴', 'extra': '额外数据'},
                title='自定义悬停信息的散点图')
fig.show()

4.2 缩放、平移和选择

import plotly.graph_objects as go
import numpy as np

# 创建示例数据
np.random.seed(42)
x = np.random.normal(0, 1, 1000)
y = np.random.normal(0, 1, 1000)

# 创建散点图
fig = go.Figure(data=go.Scatter(
    x=x,
    y=y,
    mode='markers',
    marker=dict(
        size=8,
        color=y,
        colorscale='Viridis',
        showscale=True
    )
))

# 配置交互选项
fig.update_layout(
    title='交互式数据探索',
    xaxis=dict(
        title='X轴',
        range=[-3, 3]  # 初始视图范围
    ),
    yaxis=dict(
        title='Y轴',
        range=[-3, 3]  # 初始视图范围
    ),
    # 添加按钮和交互工具
    updatemenus=[
        dict(
            type="buttons",
            direction="left",
            buttons=[
                dict(
                    args=[{"xaxis.range": [-3, 3], "yaxis.range": [-3, 3]}],
                    label="重置视图",
                    method="relayout"
                ),
                dict(
                    args=[{"xaxis.range": [-1, 1], "yaxis.range": [-1, 1]}],
                    label="放大视图",
                    method="relayout"
                )
            ],
            pad={"r": 10, "t": 10},
            showactive=True,
            x=0.11,
            xanchor="left",
            y=1.1,
            yanchor="top"
        ),
    ]
)

# 添加选择工具配置
fig.update_layout(
    dragmode='select',  # 默认选择模式:'select', 'lasso', 'zoom', 'pan'
    hovermode='closest'
)

fig.show()

4.3 动态筛选与交互控件

import plotly.graph_objects as go
import pandas as pd
import numpy as np

# 创建示例数据
np.random.seed(42)
dates = pd.date_range('2022-01-01', periods=100)
df = pd.DataFrame({
    'date': dates,
    'value': np.cumsum(np.random.normal(0, 1, 100)),
    'category': np.random.choice(['A', 'B', 'C'], 100)
})

# 创建基础图表
fig = go.Figure()

# 为每个类别添加一条线
for category in df['category'].unique():
    df_filtered = df[df['category'] == category]
    fig.add_trace(go.Scatter(
        x=df_filtered['date'],
        y=df_filtered['value'],
        mode='lines+markers',
        name=f'类别 {category}'
    ))

# 添加交互式范围滑块
fig.update_layout(
    title='时间序列数据交互式筛选',
    xaxis=dict(
        rangeselector=dict(
            buttons=list([
                dict(count=7, label="1周", step="day", stepmode="backward"),
                dict(count=1, label="1月", step="month", stepmode="backward"),
                dict(count=3, label="3月", step="month", stepmode="backward"),
                dict(step="all", label="全部")
            ])
        ),
        rangeslider=dict(visible=True),
        type="date"
    )
)

fig.show()

五、高级可视化技术

5.1 地图可视化

import plotly.express as px
import pandas as pd

# 准备地理数据示例
df = pd.DataFrame({
    'city': ['北京', '上海', '广州', '深圳', '成都'],
    'lat': [39.9042, 31.2304, 23.1291, 22.5431, 30.5723],
    'lon': [116.4074, 121.4737, 113.2644, 114.0579, 104.0665],
    'population': [21.54, 24.28, 15.31, 12.59, 16.33],
    'growth': [2.3, 3.1, 4.2, 3.9, 3.5]
})

# 散点地图
fig = px.scatter_mapbox(df, 
                      lat="lat", 
                      lon="lon", 
                      hover_name="city", 
                      size="population",
                      color="growth",
                      color_continuous_scale=px.colors.cyclical.IceFire,
                      size_max=15,
                      zoom=3,
                      title="中国主要城市人口与增长率")

# 设置地图样式
fig.update_layout(mapbox_style="open-street-map")
fig.update_layout(margin={"r":0,"t":30,"l":0,"b":0})
fig.show()

5.2 3D 可视化

import plotly.express as px
import pandas as pd
import numpy as np

# 创建3D数据
np.random.seed(42)
n = 100
theta = np.random.uniform(0, 2*np.pi, n)
r = np.random.uniform(0, 1, n)
x = r * np.cos(theta)
y = r * np.sin(theta)
z = np.random.normal(0, 0.2, n) + r  # z与r相关,加上一些噪声

df = pd.DataFrame({
    'x': x,
    'y': y,
    'z': z,
    'category': np.random.choice(['A', 'B', 'C'], n),
    'value': np.random.uniform(0, 10, n)
})

# 3D散点图
fig = px.scatter_3d(df, x='x', y='y', z='z',
                   color='category', size='value',
                   opacity=0.7, title='3D交互式散点图')

# 调整视角
fig.update_layout(scene_camera=dict(
    up=dict(x=0, y=0, z=1),
    center=dict(x=0, y=0, z=0),
    eye=dict(x=1.5, y=1.5, z=1.5)
))

fig.show()

# 3D曲面图
# 创建网格数据
x = np.linspace(-5, 5, 50)
y = np.linspace(-5, 5, 50)
x_grid, y_grid = np.meshgrid(x, y)
z_grid = np.sin(np.sqrt(x_grid**2 + y_grid**2))

# 绘制3D曲面
fig = px.surface(z=z_grid, x=x, y=y, title='3D曲面图示例')
fig.show()

5.3 复合图表与子图

import plotly.graph_objects as go
from plotly.subplots import make_subplots
import pandas as pd
import numpy as np

# 创建示例数据
np.random.seed(42)
dates = pd.date_range('2022-01-01', periods=100)
df = pd.DataFrame({
    'date': dates,
    'value1': np.cumsum(np.random.normal(0, 1, 100)),
    'value2': np.random.uniform(20, 30, 100),
    'category': np.random.choice(['A', 'B', 'C'], 100)
})

# 创建包含2行1列的子图
fig = make_subplots(
    rows=2, cols=1,
    shared_xaxes=True,  # 共享x轴
    vertical_spacing=0.1,  # 子图垂直间距
    subplot_titles=('时间序列图', '柱状图')  # 子图标题
)

# 添加第一个子图(时间序列图)
fig.add_trace(
    go.Scatter(x=df['date'], y=df['value1'], mode='lines+markers', name='趋势线'),
    row=1, col=1
)

# 添加第二个子图(柱状图)
fig.add_trace(
    go.Bar(x=df['date'], y=df['value2'], name='每日数值'),
    row=2, col=1
)

# 更新布局
fig.update_layout(
    title_text='复合图表示例 - 时间序列分析',
    height=600,
    showlegend=True
)

fig.show()

六、动态与实时数据可视化

6.1 动画图表

import plotly.express as px
import pandas as pd
import numpy as np

# 创建时间序列数据
np.random.seed(42)
dates = pd.date_range('2022-01-01', periods=365)
countries = ['中国', '美国', '印度', '日本', '德国']
data = []

for country in countries:
    base_value = np.random.randint(100, 1000)
    growth_rate = np.random.uniform(0.001, 0.005)
    noise = np.random.normal(0, 0.02, len(dates))
    
    for i, date in enumerate(dates):
        value = base_value * (1 + growth_rate * i + noise[i])
        data.append({
            'date': date,
            'country': country,
            'value': value,
            'month': date.strftime('%Y-%m')
        })

df = pd.DataFrame(data)

# 创建动画图表
fig = px.scatter(
    df, 
    x='date', 
    y='value', 
    color='country',
    size='value',
    hover_name='country',
    animation_frame='month',  # 按月份创建动画帧
    animation_group='country',  # 按国家分组
    range_y=[0, df['value'].max() * 1.1],
    title='各国经济指标月度动态变化',
    labels={'value': '指标值', 'date': '日期'}
)

# 调整动画设置
fig.update_layout(
    updatemenus=[
        dict(
            type='buttons',
            showactive=False,
            buttons=[
                dict(label='播放',
                     method='animate',
                     args=[None, {'frame': {'duration': 500, 'redraw': True}, 'fromcurrent': True}]),
                dict(label='暂停',
                     method='animate',
                     args=[[None], {'frame': {'duration': 0, 'redraw': True}, 'mode': 'immediate'}])
            ],
            x=0.1,
            y=0,
            xanchor='right',
            yanchor='top'
        )
    ]
)

fig.show()

6.2 实时数据更新

import plotly.graph_objects as go
from plotly.subplots import make_subplots
import time
import numpy as np

# 注意:这个例子在Jupyter Notebook中运行效果最佳
# 如果在脚本中运行,需要使用其他方式来显示和更新图表

# 初始化图表
fig = make_subplots(rows=1, cols=2, 
                   subplot_titles=('实时折线图', '实时柱状图'))

# 初始数据
x_data = list(range(10))
y_line = np.random.randn(10).cumsum()
y_bar = np.random.uniform(1, 10, 10)

# 添加初始跟踪
line_trace = go.Scatter(x=x_data, y=y_line, mode='lines+markers', name='实时折线')
bar_trace = go.Bar(x=x_data, y=y_bar, name='实时柱状')

fig.add_trace(line_trace, row=1, col=1)
fig.add_trace(bar_trace, row=1, col=2)

# 更新布局
fig.update_layout(title_text='实时数据可视化示例',
                 showlegend=False,
                 height=400)

# Jupyter中的实时更新(注释掉这段代码以避免在常规脚本中运行)
"""
from IPython.display import display
import ipywidgets as widgets

output = widgets.Output()
display(output)

with output:
    display(fig)

# 模拟数据更新
for i in range(10, 30):
    time.sleep(1)  # 每秒更新一次
    
    # 更新数据
    x_data.append(i)
    y_line = np.append(y_line, y_line[-1] + np.random.randn())
    y_bar = np.append(y_bar, np.random.uniform(1, 10))
    
    if len(x_data) > 20:  # 保持最近20个数据点
        x_data = x_data[-20:]
        y_line = y_line[-20:]
        y_bar = y_bar[-20:]
    
    # 更新图表
    fig.data[0].x = x_data
    fig.data[0].y = y_line
    fig.data[1].x = x_data
    fig.data[1].y = y_bar
    
    with output:
        output.clear_output(wait=True)
        display(fig)
"""

七、Plotly 与 Dash 结合开发

Dash 是基于 Plotly 构建的 Web 应用框架,允许开发者在 Python 中创建交互式 Web 应用,无需前端开发知识。以下是一个简单的 Dash 应用示例:

# 安装 Dash: pip install dash

from dash import Dash, dcc, html, Input, Output
import plotly.express as px
import pandas as pd
import numpy as np

# 初始化应用
app = Dash(__name__)

# 生成示例数据
np.random.seed(42)
df = pd.DataFrame({
    'x': np.random.normal(0, 1, 1000),
    'y': np.random.normal(0, 1, 1000),
    'group': np.random.choice(['A', 'B', 'C', 'D'], 1000)
})

# 定义应用布局
app.layout = html.Div([
    html.H1("Plotly Dash 交互式应用示例"),
    
    html.Div([
        html.Label("选择点的大小:"),
        dcc.Slider(
            id='size-slider',
            min=2,
            max=20,
            value=8,
            marks={i: str(i) for i in range(2, 21, 2)},
            step=1
        ),
    ], style={'width': '50%', 'padding': '20px'}),
    
    html.Div([
        html.Label("选择颜色分组:"),
        dcc.Dropdown(
            id='color-dropdown',
            options=[
                {'label': '分组', 'value': 'group'},
                {'label': 'X值', 'value': 'x'},
                {'label': 'Y值', 'value': 'y'}
            ],
            value='group'
        ),
    ], style={'width': '50%', 'padding': '20px'}),
    
    dcc.Graph(id='scatter-plot')
])

# 定义回调以更新图表
@app.callback(
    Output('scatter-plot', 'figure'),
    [Input('size-slider', 'value'),
     Input('color-dropdown', 'value')]
)
def update_graph(marker_size, color_by):
    fig = px.scatter(
        df, 
        x='x', 
        y='y', 
        color=color_by,
        size_max=marker_size,
        opacity=0.7,
        title=f'散点图 (按 {color_by} 着色)'
    )
    
    fig.update_layout(transition_duration=500)
    return fig

# 运行应用
if __name__ == '__main__':
    app.run_server(debug=True)

八、案例研究:综合数据分析仪表板

以下是一个综合案例,展示如何使用 Plotly 创建一个完整的多图表数据分析仪表板:

import plotly.graph_objects as go
from plotly.subplots import make_subplots
import pandas as pd
import numpy as np

# 创建模拟的股票市场数据
np.random.seed(42)
dates = pd.date_range('2022-01-01', periods=365)
price = 100 + np.cumsum(np.random.normal(0.05, 1, 365))
volume = np.random.lognormal(10, 0.5, 365)
news_sentiment = np.random.normal(0, 1, 365)
tech_indicators = pd.DataFrame({
    'RSI': 50 + np.random.normal(0, 10, 365),
    'MACD': np.random.normal(0, 1, 365),
    'ATR': np.random.uniform(1, 3, 365)
})

df_stock = pd.DataFrame({
    'date': dates,
    'price': price,
    'volume': volume,
    'news_sentiment': news_sentiment
})

# 添加移动平均线
df_stock['MA_7'] = df_stock['price'].rolling(window=7).mean()
df_stock['MA_30'] = df_stock['price'].rolling(window=30).mean()

# 创建仪表板布局
fig = make_subplots(
    rows=4, cols=2,
    shared_xaxes=True,
    vertical_spacing=0.05,
    horizontal_spacing=0.05,
    specs=[
        [{"colspan": 2}, None],
        [{"colspan": 2}, None],
        [{"type": "indicator"}, {"type": "indicator"}],
        [{"colspan": 2}, None],
    ],
    subplot_titles=(
        "股价走势与移动平均线", 
        "交易量", 
        "当前股价", 
        "交易量变化",
        "技术指标"
    )
)

# 添加股价线图
fig.add_trace(
    go.Scatter(
        x=df_stock['date'], 
        y=df_stock['price'],
        mode='lines',
        name='股价',
        line=dict(color='royalblue')
    ),
    row=1, col=1
)

# 添加移动平均线
fig.add_trace(
    go.Scatter(
        x=df_stock['date'], 
        y=df_stock['MA_7'],
        mode='lines',
        name='7日均线',
        line=dict(color='orange', dash='dash')
    ),
    row=1, col=1
)

fig.add_trace(
    go.Scatter(
        x=df_stock['date'], 
        y=df_stock['MA_30'],
        mode='lines',
        name='30日均线',
        line=dict(color='green', dash='dash')
    ),
    row=1, col=1
)

# 添加交易量柱状图
fig.add_trace(
    go.Bar(
        x=df_stock['date'], 
        y=df_stock['volume'],
        name='交易量',
        marker_color='darkblue',
        opacity=0.7
    ),
    row=2, col=1
)

# 添加当前股价指示器
fig.add_trace(
    go.Indicator(
        mode="number+delta",
        value=df_stock['price'].iloc[-1],
        delta={'reference': df_stock['price'].iloc[-2], 'relative': True, 'valueformat': '.2%'},
        title={'text': "当前股价"},
        number={'prefix': "¥", 'valueformat': '.2f'}
    ),
    row=3, col=1
)

# 添加交易量指示器
fig.add_trace(
    go.Indicator(
        mode="number+delta",
        value=df_stock['volume'].iloc[-1],
        delta={'reference': df_stock['volume'].iloc[-2], 'relative': True, 'valueformat': '.2%'},
        title={'text': "交易量"},
        number={'valueformat': '.2f'}
    ),
    row=3, col=2
)

# 添加技术指标热图
tech_data = tech_indicators.iloc[-30:].copy()  # 取最近30天的数据
# 归一化数据到0-1范围用于热图
for col in tech_data.columns:
    tech_data[col] = (tech_data[col] - tech_data[col].min()) / (tech_data[col].max() - tech_data[col].min())

fig.add_trace(
    go.Heatmap(
        z=tech_data.values.T,
        x=dates[-30:],
        y=tech_data.columns,
        colorscale='RdBu',
        showscale=False
    ),
    row=4, col=1
)

# 更新图表布局
fig.update_layout(
    title_text="股票市场数据分析仪表板",
    height=900,
    template="plotly_white",
    showlegend=True,
    legend=dict(
        orientation="h",
        yanchor="bottom",
        y=1.02,
        xanchor="right",
        x=1
    )
)

# 添加范围选择器
fig.update_xaxes(
    rangeselector=dict(
        buttons=list([
            dict(count=7, label="1周", step="day", stepmode="backward"),
            dict(count=1, label="1月", step="month", stepmode="backward"),
            dict(count=3, label="3月", step="month", stepmode="backward"),
            dict(count=6, label="6月", step="month", stepmode="backward"),
            dict(step="all", label="全部")
        ])
    ),
    rangeslider=dict(visible=True),
    type="date",
    row=1, col=1
)

# 添加注释
fig.add_annotation(
    text="数据分析:股价与交易量趋势明显相关",
    x=dates[200],
    y=price[200] * 1.1,
    arrowhead=2,
    showarrow=True,
    row=1, col=1
)

fig.show()

九、最佳实践与性能优化

9.1 代码最佳实践

  1. 使用适当的接口:根据需求选择 plotly.expressplotly.graph_objects

    # 简单图表使用 px
    import plotly.express as px
    fig = px.scatter(df, x='x', y='y')
    
    # 复杂自定义图表使用 go
    import plotly.graph_objects as go
    fig = go.Figure(data=go.Scatter(x=df['x'], y=df['y']))
    
  2. 保持代码模块化:创建函数生成图表组件

    def create_time_series(df, x_col, y_col, title):
        """创建时间序列图"""
        fig = px.line(df, x=x_col, y=y_col, title=title)
        fig.update_xaxes(rangeslider_visible=True)
        return fig
    
    def create_distribution(df, col, title):
        """创建分布图"""
        fig = px.histogram(df, x=col, title=title)
        return fig
    
    # 使用
    fig_time = create_time_series(df, 'date', 'value', '时间序列')
    fig_dist = create_distribution(df, 'value', '值分布')
    
  3. 使用模板:一致的视觉风格

    import plotly.io as pio
    
    # 设置默认模板
    pio.templates.default = "plotly_white"
    
    # 或单独设置
    fig.update_layout(template="plotly_dark")
    

9.2 性能优化

  1. 减少数据点数量:大数据集采样或聚合

    # 数据量大时进行采样
    if len(df) > 10000:
        df_sampled = df.sample(n=10000, random_state=42)
        fig = px.scatter(df_sampled, x='x', y='y')
    else:
        fig = px.scatter(df, x='x', y='y')
    
    # 或数据聚合
    df_agg = df.groupby('category').agg({'value': 'mean'}).reset_index()
    fig = px.bar(df_agg, x='category', y='value')
    
  2. 使用 WebGL 渲染:大量数据点使用 Scattergl

    import plotly.graph_objects as go
    
    # 对于大量数据点,使用 WebGL 加速渲染
    fig = go.Figure(data=go.Scattergl(  # 注意这里是 Scattergl 而不是 Scatter
        x=large_df['x'],
        y=large_df['y'],
        mode='markers'
    ))
    
  3. 优化图表更新:局部更新而非重绘

    # 在 Dash 应用程序中局部更新图表
    @app.callback(
        Output('chart', 'figure'),
        [Input('dropdown', 'value')]
    )
    def update_figure(selected_value):
        # 保留布局配置,只更新数据
        return {
            'data': [go.Scatter(x=df['x'], y=df[selected_value])],
            'layout': fig.layout  # 复用之前的布局配置
        }
    

十、总结与扩展资源

Plotly 以其强大的交互式可视化能力和现代的美学设计,成为 Python 数据可视化领域的重要工具。其主要优势在于:

  1. 原生交互功能:提供丰富的用户交互选项
  2. 美观的默认样式:符合现代设计审美
  3. 多样的图表类型:支持从简单到复杂的各类可视化需求
  4. Web 兼容性:轻松集成到 Web 应用程序中
  5. 与 Dash 框架集成:快速构建数据仪表板

扩展资源

  1. Plotly 官方文档
  2. Dash 框架文档
  3. Plotly 图表示例库
  4. Plotly 社区论坛
  5. Plotly GitHub 存储库
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Is code

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值