当前位置:首页>python>Python数据可视化:交互篇 - Plotly

Python数据可视化:交互篇 - Plotly

  • 2026-09-06 08:50:21
Python数据可视化:交互篇 - Plotly

引言:为什么选择Plotly?

Plotly是一个强大的交互式数据可视化库,它可以让你创建出具有高度交互性的图表。与Matplotlib和Seaborn不同,Plotly生成的图表可以:

  • 交互式操作:缩放、平移、悬停查看详情
  • 动态更新:支持下拉选择、滑块等控件
  • Web友好:直接导出为HTML,可嵌入网页
  • 3D可视化:支持3D图表和地图可视化

本文将带你掌握Plotly的核心技能。


一、Plotly介绍

什么是Plotly

Plotly是一个交互式数据可视化库,支持创建交互式图表和仪表板。

特点

  • 交互式图表:可缩放、悬停查看详情
  • 3D图表:支持3D图表和地图可视化
  • 多格式导出:可导出为HTML、图片等格式
  • Web集成:适合创建Web应用中的可视化

二、环境搭建

1. 安装Plotly

# 使用pip安装
pip install plotly pandas numpy

# 或使用conda安装
conda install plotly pandas numpy

2. 验证安装

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

print("Plotly版本:", px.__version__)
print("环境搭建成功!")

三、基础交互式图表

1. 交互式散点图

散点图可以悬停查看每个点的详细信息。

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

# 加载示例数据
tips = px.data.tips()

# 创建交互式散点图
fig = px.scatter(tips, 
                 x='total_bill', 
                 y='tip', 
                 color='sex', 
                 size='size',
                 hover_data=['day', 'time'],
                 title='账单金额与小费的关系',
                 labels={'total_bill': '账单金额 ($)', 'tip': '小费 ($)'},
                 color_discrete_map={'Male': '
#4ECDC4', 'Female': '#FF6B6B'})

# 更新布局
fig.update_layout(
    title_font_size=16,
    xaxis_title_font_size=12,
    yaxis_title_font_size=12,
    legend_title_font_size=12,
    height=600,
    width=900
)

# 显示图表
fig.show()

2. 交互式柱状图

柱状图可以悬停查看具体数值。

fig = px.bar(tips, 
             x='day', 
             y='total_bill', 
             color='sex',
             barmode='group',
             title='每天的账单金额',
             labels={'total_bill': '账单金额 ($)', 'day': '星期'},
             color_discrete_map={'Male': '#4ECDC4', 'Female': '#FF6B6B'})

fig.update_layout(
    title_font_size=16,
    height=600,
    width=900
)

fig.show()

3. 交互式折线图

折线图适合展示时间序列数据。

# 创建时间序列数据
np.random.seed(42)
dates = pd.date_range('2024-01-01', '2024-12-31', freq='D')
values1 = np.cumsum(np.random.randn(365)) + 100
values2 = np.cumsum(np.random.randn(365)) + 100

df_line = pd.DataFrame({
'日期': dates,
'产品A': values1,
'产品B': values2
})

# 转换为长格式
df_line_melt = df_line.melt('日期', var_name='产品', value_name='销售额')

fig = px.line(df_line_melt,
              x='日期',
              y='销售额',
              color='产品',
              title='产品销售趋势',
              labels={'销售额': '销售额', '日期': '日期'},
              color_discrete_map={'产品A': '#4ECDC4', '产品B': '#FF6B6B'})

fig.update_layout(
    title_font_size=16,
    height=600,
    width=1000,
    hovermode='x unified'
)

fig.show()

4. 交互式饼图

饼图可以悬停查看每个部分的占比。

fig = px.pie(tips,
             values='total_bill',
             names='day',
             title='每天的账单金额占比',
             color_discrete_sequence=px.colors.qualitative.Set2)

fig.update_layout(
    title_font_size=16,
    height=600,
    width=800
)

fig.update_traces(
    textposition='inside',
    textinfo='percent+label',
    hovertemplate='%{label}: $%{value:.2f}<br>占比: %{percent}'
)

fig.show()

5. 交互式直方图

直方图可以悬停查看每个区间的频率。

fig = px.histogram(tips,
                    x='total_bill',
                    color='sex',
                    nbins=20,
                    title='账单金额分布',
                    labels={'total_bill': '账单金额 ($)'},
                    color_discrete_map={'Male': '#4ECDC4', 'Female': '#FF6B6B'},
                    marginal='box')  # 添加边际图

fig.update_layout(
    title_font_size=16,
    height=600,
    width=900,
    barmode='overlay'
)

fig.update_traces(opacity=0.7)

fig.show()

四、高级交互式图表

1. 3D散点图

Plotly的3D图表非常强大。

iris = px.data.iris()

fig = px.scatter_3d(iris,
                    x='sepal_length',
                    y='sepal_width',
                    z='petal_length',
                    color='species',
                    size='petal_width',
                    title='鸢尾花数据的3D可视化',
                    labels={'sepal_length': '萼片长度', 
'sepal_width': '萼片宽度', 
'petal_length': '花瓣长度'},
                    color_discrete_map={'setosa': '#FF6B6B', 
'versicolor': '#4ECDC4', 
'virginica': '#45B7D1'})

fig.update_layout(
    title_font_size=16,
    height=700,
    width=900,
    scene=dict(
        xaxis_title='萼片长度',
        yaxis_title='萼片宽度',
        zaxis_title='花瓣长度'
    )
)

fig.show()

2. 密度热力图

密度热力图可以展示两个变量的联合分布。

fig = px.density_heatmap(tips,
                         x='total_bill',
                         y='tip',
                         marginal_x='histogram',
                         marginal_y='histogram',
                         title='账单金额与小费的密度热力图',
                         labels={'total_bill': '账单金额 ($)', 'tip': '小费 ($)'},
                         color_continuous_scale='Viridis')

fig.update_layout(
    title_font_size=16,
    height=700,
    width=900
)

fig.show()

3. 平行坐标图

平行坐标图适合展示多变量数据。

fig = px.parallel_coordinates(iris,
                              color='species_id',
                              title='鸢尾花数据的平行坐标图',
                              color_continuous_scale=px.colors.diverging.Tealrose,
                              color_continuous_midpoint=2)

fig.update_layout(
    title_font_size=16,
    height=600,
    width=1000
)

fig.show()

4. 小提琴图

小提琴图可以展示数据分布。

fig = px.violin(tips,
                y='total_bill',
                x='day',
                color='sex',
                box=True,
                points='all',
                title='每天的账单金额分布',
                labels={'total_bill': '账单金额 ($)', 'day': '星期'},
                color_discrete_map={'Male': '#4ECDC4', 'Female': '#FF6B6B'})

fig.update_layout(
    title_font_size=16,
    height=600,
    width=900
)

fig.show()

5. 旭日图

旭日图适合展示层级数据。

# 创建层级数据
data = {
'类别': ['电子产品', '电子产品', '电子产品', '配件', '配件', '配件'],
'产品': ['智能手机', '笔记本电脑', '平板电脑', '耳机', '充电器', '保护壳'],
'销售额': [50000, 40000, 30000, 15000, 10000, 5000]
}

df_sunburst = pd.DataFrame(data)

fig = px.sunburst(df_sunburst,
                  path=['类别', '产品'],
                  values='销售额',
                  title='产品销售构成',
                  color='类别',
                  color_discrete_map={'电子产品': '#4ECDC4', '配件': '#FF6B6B'})

fig.update_layout(
    title_font_size=16,
    height=700,
    width=700
)

fig.show()

五、交互式控件

1. 下拉菜单

添加下拉菜单可以动态切换数据。

import plotly.graph_objects as go

# 创建数据
np.random.seed(42)
x = np.linspace(0, 10, 100)
y1 = np.sin(x)
y2 = np.cos(x)
y3 = np.tan(x)

fig = go.Figure()

# 添加三个轨迹
fig.add_trace(go.Scatter(x=x, y=y1, name='sin(x)', visible=True))
fig.add_trace(go.Scatter(x=x, y=y2, name='cos(x)', visible=False))
fig.add_trace(go.Scatter(x=x, y=y3, name='tan(x)', visible=False))

# 更新菜单
fig.update_layout(
    updatemenus=[
        dict(
            buttons=list([
                dict(
                    label='sin(x)',
                    method='update',
                    args=[{'visible': [True, False, False]},
                          {'title': '正弦函数'}]),
                dict(
                    label='cos(x)',
                    method='update',
                    args=[{'visible': [False, True, False]},
                          {'title': '余弦函数'}]),
                dict(
                    label='tan(x)',
                    method='update',
                    args=[{'visible': [False, False, True]},
                          {'title': '正切函数'}])
            ]),
            direction='down',
            showactive=True,
        )
    ],
    title='正弦函数',
    height=600,
    width=900
)

fig.show()

2. 滑块

滑块可以动态调整参数。

# 创建数据
x = np.linspace(0, 10, 100)

fig = go.Figure()

# 添加初始轨迹
fig.add_trace(go.Scatter(x=x, y=np.sin(x), name='sin(x)'))

# 创建滑块步骤
steps = []
for freq in np.arange(0.5, 3.1, 0.5):
    step = dict(
        method='update',
        args=[{'y': [np.sin(freq * x)]},
              {'title': f'正弦函数 (频率={freq})'}],
        label=f'{freq:.1f}'
    )
    steps.append(step)

# 添加滑块
fig.update_layout(
    sliders=[dict(
        active=0,
        currentvalue={"prefix": "频率: "},
        pad={"t": 50},
        steps=steps
    )],
    title='正弦函数 (频率=0.5)',
    height=600,
    width=900
)

fig.show()

六、实战案例:销售数据分析

1. 数据描述

我们有一份销售数据,包含以下字段:

  • date: 销售日期
  • product: 产品名称
  • category: 产品类别
  • quantity: 销售数量
  • price: 单价
  • revenue: 销售额

2. 可视化目标

  • 销售趋势分析
  • 产品销售排名
  • 价格与销售额的关系

3. 代码实现

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

# 创建模拟数据
np.random.seed(42)
dates = pd.date_range('2024-01-01', '2024-12-31', freq='D')
products = ['智能手机', '笔记本电脑', '平板电脑', '耳机', '充电器']
categories = ['电子产品', '电子产品', '电子产品', '配件', '配件']

data = {
'date': np.random.choice(dates, 1000),
'product': np.random.choice(products, 1000),
'category': np.random.choice(categories, 1000),
'quantity': np.random.randint(1, 10, 1000),
'price': np.random.choice([2999, 5999, 1999, 299, 99], 1000)
}

df = pd.DataFrame(data)
df['revenue'] = df['quantity'] * df['price']
df['month'] = df['date'].dt.month

# 1. 销售趋势分析
daily_sales = df.groupby('date')['revenue'].sum().reset_index()

fig = px.line(daily_sales,
              x='date',
              y='revenue',
              title='2024年每日销售趋势',
              labels={'revenue': '销售额', 'date': '日期'})

fig.update_layout(
    title_font_size=16,
    height=500,
    width=1000,
    hovermode='x unified'
)

fig.update_traces(
    line_color='#45B7D1',
    line_width=2
)

fig.show()

# 2. 产品销售排名
top_products = df.groupby('product')['revenue'].sum().sort_values(ascending=False).reset_index()

fig = px.bar(top_products,
             x='product',
             y='revenue',
             title='销售额前10的产品',
             labels={'revenue': '销售额', 'product': '产品'},
             color='revenue',
             color_continuous_scale='Viridis')

fig.update_layout(
    title_font_size=16,
    height=500,
    width=900
)

fig.update_traces(
    texttemplate='%{y:,.0f}',
    textposition='outside'
)

fig.show()

# 3. 价格与销售额的关系
fig = px.scatter(df,
                 x='price',
                 y='revenue',
                 color='category',
                 size='quantity',
                 hover_data=['product'],
                 title='价格与销售额的关系',
                 labels={'price': '价格', 'revenue': '销售额', 'category': '类别'},
                 color_discrete_map={'电子产品': '#4ECDC4', '配件': '#FF6B6B'})

fig.update_layout(
    title_font_size=16,
    height=600,
    width=900
)

fig.show()

# 4. 月度销售情况
monthly_sales = df.groupby('month')['revenue'].sum().reset_index()
month_names = ['1月', '2月', '3月', '4月', '5月', '6月', 
'7月', '8月', '9月', '10月', '11月', '12月']
monthly_sales['month_name'] = monthly_sales['month'].map(lambda x: month_names[x-1])

fig = px.bar(monthly_sales,
             x='month_name',
             y='revenue',
             title='2024年月度销售额',
             labels={'revenue': '销售额', 'month_name': '月份'},
             color='revenue',
             color_continuous_scale='Viridis')

fig.update_layout(
    title_font_size=16,
    height=500,
    width=900
)

fig.update_traces(
    texttemplate='%{y:,.0f}',
    textposition='outside'
)

fig.show()

# 5. 交互式仪表板(组合图表)
fig = go.Figure()

# 添加销售额趋势
fig.add_trace(go.Scatter(
    x=daily_sales['date'],
    y=daily_sales['revenue'],
    name='销售额',
    yaxis='y',
    line_color='#45B7D1'
))

# 添加移动平均线
daily_sales['MA7'] = daily_sales['revenue'].rolling(7).mean()
fig.add_trace(go.Scatter(
    x=daily_sales['date'],
    y=daily_sales['MA7'],
    name='7日移动平均',
    yaxis='y',
    line_color='#FF6B6B',
    line_dash='dash'
))

fig.update_layout(
    title='销售趋势与移动平均',
    title_font_size=16,
    height=500,
    width=1000,
    yaxis=dict(title='销售额'),
    hovermode='x unified'
)

fig.show()

七、图表导出与分享

1. 导出为HTML

# 创建一个图表
fig = px.scatter(tips, x='total_bill', y='tip', color='sex')

# 导出为HTML文件
fig.write_html('interactive_chart.html')
print("图表已导出为 interactive_chart.html")

2. 导出为图片

# 需要安装kaleido
# pip install kaleido

# 导出为PNG
fig.write_image('chart.png', width=1200, height=800, scale=2)
print("图表已导出为 chart.png")

# 导出为SVG
fig.write_image('chart.svg')
print("图表已导出为 chart.svg")

# 导出为PDF
fig.write_image('chart.pdf')
print("图表已导出为 chart.pdf")

八、最佳实践

1. 性能优化

  • 大数据集时使用采样
  • 避免在一个图表中显示过多数据点
  • 使用WebGL渲染大数据集

2. 交互设计

  • 确保悬停信息清晰有用
  • 合理使用颜色和大小编码
  • 提供清晰的图例和说明

3. 图表选择

场景
推荐图表
探索数据关系
scatter, scatter_3d
时间序列
line
分类对比
bar, violin
层级数据
sunburst, treemap
分布展示
histogram, density_heatmap

九、学习资源推荐

1. 官方资源

  • Plotly官网:https://plotly.com/python/
  • Plotly Express文档:https://plotly.com/python/plotly-express/
  • Plotly示例库:https://plotly.com/python/

2. 书籍

  • 《交互式数据可视化》(Plotly官方文档)
  • 《Python数据科学手册》(Jake VanderPlas)

十、总结

Plotly让数据可视化变得生动而有趣。通过本文的学习,你已经掌握了:

  • Plotly的基本概念和环境搭建
  • 基础交互式图表的创建
  • 高级交互式图表的使用
  • 交互式控件的添加
  • 实战案例应用
  • 图表导出与分享

Plotly的交互性能让你的数据故事更加生动,让读者能够主动探索数据。记住,好的交互式可视化应该既美观又实用,让用户能够真正从交互中获得洞见!

小贴士:Plotly图表默认显示在浏览器中,你可以通过右上角的工具栏进行缩放、平移、下载等操作。探索这些功能,让你的可视化体验更好!

最新文章

随机文章