Python利用Plotly打造可縮放的數(shù)據(jù)報(bào)告
本節(jié)學(xué)習(xí)目標(biāo)
完成本節(jié)學(xué)習(xí)后,你將能夠:
- 理解 Plotly 的核心概念與 Plotly Express 的便捷用法
- 創(chuàng)建交互式散點(diǎn)圖、柱狀圖、折線圖
- 自定義圖表樣式、顏色、布局和動(dòng)畫(huà)
- 使用子圖(subplots)布局多圖表
- 為圖表添加懸停信息、按鈕和交互控件
- 將交互式圖表導(dǎo)出為 HTML 文件進(jìn)行分享
- 在 Jupyter Notebook 和 Web 環(huán)境中嵌入 Plotly 圖表
為什么學(xué)這個(gè)
想象兩份銷售報(bào)告:
- 報(bào)告A:包含 20 張靜態(tài) PNG 圖片,每張圖展示一個(gè)維度的數(shù)據(jù)。
- 報(bào)告B:包含 3 張交互式圖表,可以鼠標(biāo)懸停查看具體數(shù)值、拖拽縮放某個(gè)時(shí)間段、點(diǎn)擊圖例篩選特定產(chǎn)品。
你會(huì)選擇哪份?毫無(wú)疑問(wèn),報(bào)告B的信息密度更高,用戶體驗(yàn)更好,決策效率更高。
這就是 Plotly 的價(jià)值所在。如果說(shuō) Matplotlib 和 Seaborn 是"拍照"——拍完就不能改了;那么 Plotly 就是"拍視頻"——用戶可以暫停、回放、放大看細(xì)節(jié)。
Plotly 的核心優(yōu)勢(shì):
- 零門(mén)檻交互:生成的圖表自帶縮放、平移、懸停提示、截圖等功能
- Web 原生:導(dǎo)出為 HTML 即可在瀏覽器中運(yùn)行,無(wú)需額外軟件
- Express 模式:一行代碼創(chuàng)建復(fù)雜圖表
- 與 Pandas 完美集成:直接傳入 DataFrame
核心知識(shí)點(diǎn)講解
一、Plotly Express——一行代碼的魔法
Plotly Express(簡(jiǎn)稱 px)是 Plotly 的高級(jí)接口,設(shè)計(jì)理念是"用最少的代碼做最多的事"。它的用法與 Seaborn 非常相似——傳入 DataFrame 和列名即可。
1.1 安裝與導(dǎo)入
# 安裝 Plotly(如果尚未安裝) # pip install plotly pandas import plotly.express as px import plotly.graph_objects as go from plotly.subplots import make_subplots import pandas as pd import numpy as np
1.2 你的第一個(gè)交互式散點(diǎn)圖
import plotly.express as px
import numpy as np
import pandas as pd
# 生成模擬數(shù)據(jù)
np.random.seed(42)
n = 150
df = pd.DataFrame({
'廣告投入': np.random.uniform(10, 100, n),
'銷售額': 0,
'產(chǎn)品類別': np.random.choice(['電子產(chǎn)品', '服裝', '食品', '家居'], n),
'區(qū)域': np.random.choice(['華東', '華南', '華北', '西部'], n)
})
df['銷售額'] = (2.5 * df['廣告投入'] +
np.where(df['產(chǎn)品類別'] == '電子產(chǎn)品', 50, 0) +
np.where(df['區(qū)域'] == '華東', 30, 0) +
np.random.normal(0, 15, n))
# 一行代碼創(chuàng)建交互式散點(diǎn)圖
fig = px.scatter(df, x='廣告投入', y='銷售額',
color='產(chǎn)品類別', # 顏色按類別區(qū)分
size='銷售額', # 氣泡大小按銷售額
hover_data=['區(qū)域'], # 懸停時(shí)顯示區(qū)域信息
title='廣告投入與銷售額關(guān)系(交互式)',
labels={'廣告投入': '廣告投入(萬(wàn)元)', '銷售額': '銷售額(萬(wàn)元)'},
color_discrete_map={'電子產(chǎn)品': '#1E88E5', '服裝': '#E53935',
'食品': '#43A047', '家居': '#FB8C00'})
# 設(shè)置圖表布局
fig.update_layout(
font=dict(size=13),
title=dict(font=dict(size=18), x=0.5),
hovermode='closest' # 懸停時(shí)最近的數(shù)據(jù)點(diǎn)都高亮
)
# 顯示圖表(在 Jupyter 中直接顯示,腳本中會(huì)打開(kāi)瀏覽器)
fig.show()
交互式操作說(shuō)明:
- 鼠標(biāo)懸停:顯示該數(shù)據(jù)點(diǎn)的詳細(xì)信息
- 拖拽:平移圖表
- 滾輪/框選:縮放某個(gè)區(qū)域
- 雙擊:重置縮放
- 點(diǎn)擊圖例:顯示/隱藏對(duì)應(yīng)類別
- 右上角工具欄:截圖、縮放、平移、重置等功能
二、交互式柱狀圖
2.1 基礎(chǔ)柱狀圖
import plotly.express as px
import pandas as pd
import numpy as np
# 模擬數(shù)據(jù):各部門(mén)季度營(yíng)收
df = pd.DataFrame({
'部門(mén)': ['銷售部', '市場(chǎng)部', '技術(shù)部', '運(yùn)營(yíng)部', '人事部', '財(cái)務(wù)部'],
'Q1': [450, 320, 580, 290, 150, 200],
'Q2': [480, 350, 620, 310, 160, 210],
'Q3': [520, 380, 650, 330, 155, 220],
'Q4': [550, 400, 700, 350, 165, 230]
})
# 需要將寬格式轉(zhuǎn)為長(zhǎng)格式
df_melted = df.melt(id_vars='部門(mén)', var_name='季度', value_name='營(yíng)收')
# 創(chuàng)建分組柱狀圖
fig = px.bar(df_melted, x='部門(mén)', y='營(yíng)收', color='季度',
barmode='group', # 分組模式(還有 'stack' 堆疊模式)
title='各部門(mén)季度營(yíng)收對(duì)比',
labels={'部門(mén)': '部門(mén)', '營(yíng)收': '營(yíng)收(萬(wàn)元)', '季度': '季度'},
color_discrete_sequence=['#4CAF50', '#FF9800', '#2196F3', '#9C27B0'])
fig.update_layout(
title=dict(font=dict(size=18), x=0.5),
font=dict(size=13),
xaxis_tickangle=-30, # X軸標(biāo)簽旋轉(zhuǎn)
hovermode='x unified' # 懸停時(shí)同一X軸的所有值一起顯示
)
fig.show()
2.2 水平柱狀圖(適合長(zhǎng)標(biāo)簽)
import plotly.express as px
import pandas as pd
# 模擬數(shù)據(jù):各產(chǎn)品線年度銷售排名
df = pd.DataFrame({
'產(chǎn)品線': ['智能手機(jī)Pro Max', '筆記本電腦Ultra', '智能手表S9',
'無(wú)線耳機(jī)AirPods', '平板電腦Mini', '智能音箱Home'],
'銷售額': [2850, 2100, 1650, 1420, 980, 750]
})
# 按銷售額排序
df = df.sort_values('銷售額', ascending=True)
fig = px.bar(df, x='銷售額', y='產(chǎn)品線', orientation='h',
title='各產(chǎn)品線年度銷售額排行(萬(wàn)元)',
color='銷售額',
color_continuous_scale='Blues',
text='銷售額') # 在柱子上顯示數(shù)值
fig.update_layout(
title=dict(font=dict(size=16), x=0.5),
font=dict(size=13),
yaxis={'categoryorder': 'total ascending'}
)
# 添加數(shù)據(jù)標(biāo)簽
fig.update_traces(texttemplate='%{text:,}', textposition='outside')
fig.show()
三、交互式折線圖
3.1 時(shí)間序列折線圖
import plotly.express as px
import pandas as pd
import numpy as np
# 模擬數(shù)據(jù):兩年的日銷售數(shù)據(jù)
np.random.seed(42)
dates = pd.date_range('2023-01-01', '2024-12-31', freq='D')
base_sales = 1000
df = pd.DataFrame({
'日期': dates,
'基礎(chǔ)銷量': base_sales + 200 * np.sin(np.arange(len(dates)) * 2 * np.pi / 365), # 季節(jié)性
'隨機(jī)波動(dòng)': np.random.normal(0, 100, len(dates))
})
df['銷售額'] = df['基礎(chǔ)銷量'] + df['隨機(jī)波動(dòng)']
df['年份'] = df['日期'].dt.year.astype(str)
df['月份'] = df['日期'].dt.month
# 按月聚合
monthly = df.groupby(['年份', '月份'])['銷售額'].mean().reset_index()
monthly.columns = ['年份', '月份', '平均日銷售額']
fig = px.line(monthly, x='月份', y='平均日銷售額', color='年份',
title='月度平均日銷售額趨勢(shì)對(duì)比',
labels={'月份': '月份', '平均日銷售額': '平均日銷售額(元)', '年份': '年份'},
markers=True,
line_shape='linear',
color_discrete_map={'2023': '#1E88E5', '2024': '#E53935'})
fig.update_layout(
title=dict(font=dict(size=16), x=0.5),
font=dict(size=13),
hovermode='x unified',
xaxis=dict(tickmode='linear', tick0=1, dtick=1, title='月份')
)
# 添加標(biāo)記和填充
fig.update_traces(mode='lines+markers', marker=dict(size=8))
fig.show()
3.2 帶誤差線的折線圖
import plotly.graph_objects as go
import numpy as np
import pandas as pd
# 模擬A/B測(cè)試數(shù)據(jù)
df = pd.DataFrame({
'周次': range(1, 9),
'A組轉(zhuǎn)化率': [3.2, 3.5, 3.8, 4.0, 4.2, 4.1, 4.3, 4.5],
'A組誤差': [0.3, 0.3, 0.4, 0.3, 0.3, 0.4, 0.3, 0.3],
'B組轉(zhuǎn)化率': [3.1, 3.3, 3.6, 3.8, 4.0, 4.3, 4.6, 4.9],
'B組誤差': [0.3, 0.3, 0.3, 0.4, 0.3, 0.3, 0.4, 0.4]
})
fig = go.Figure()
# A組
fig.add_trace(go.Scatter(
x=df['周次'], y=df['A組轉(zhuǎn)化率'],
name='A組(對(duì)照組)',
mode='lines+markers',
line=dict(color='#1E88E5', width=3),
marker=dict(size=10),
error_y=dict(type='data', array=df['A組誤差'], visible=True, thickness=2, width=5)
))
# B組
fig.add_trace(go.Scatter(
x=df['周次'], y=df['B組轉(zhuǎn)化率'],
name='B組(實(shí)驗(yàn)組)',
mode='lines+markers',
line=dict(color='#E53935', width=3, dash='dash'),
marker=dict(size=10, symbol='square'),
error_y=dict(type='data', array=df['B組誤差'], visible=True, thickness=2, width=5)
))
fig.update_layout(
title='A/B測(cè)試:轉(zhuǎn)化率對(duì)比(含置信區(qū)間)',
title=dict(font=dict(size=16), x=0.5),
xaxis=dict(title='周次', tickmode='linear', dtick=1),
yaxis=dict(title='轉(zhuǎn)化率(%)'),
font=dict(size=13),
hovermode='x unified',
legend=dict(yanchor='top', y=0.99, xanchor='left', x=0.01)
)
fig.show()
四、子圖布局(Subplots)
Plotly 使用 make_subplots 創(chuàng)建多圖表布局,用法靈活。
4.1 基礎(chǔ)子圖布局
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import numpy as np
# 創(chuàng)建 2x2 子圖
fig = make_subplots(
rows=2, cols=2,
subplot_titles=('銷售額趨勢(shì)', '產(chǎn)品占比', '區(qū)域分布', '客戶評(píng)分'),
specs=[[{'type': 'xy'}, {'type': 'domain'}], # domain 用于餅圖
[{'type': 'xy'}, {'type': 'xy'}]]
)
# 子圖(1,1):折線圖
months = ['1月', '2月', '3月', '4月', '5月', '6月',
'7月', '8月', '9月', '10月', '11月', '12月']
fig.add_trace(go.Scatter(
x=months, y=[120, 135, 148, 162, 175, 190, 210, 225, 240, 230, 215, 250],
mode='lines+markers', name='銷售額', line=dict(color='#1E88E5', width=2),
marker=dict(size=8)
), row=1, col=1)
# 子圖(1,2):餅圖
fig.add_trace(go.Pie(
labels=['電子產(chǎn)品', '服裝', '食品', '家居'],
values=[450, 320, 280, 180],
marker=dict(colors=['#1E88E5', '#E53935', '#43A047', '#FB8C00']),
textinfo='label+percent',
hole=0.4 # 空心圓環(huán)圖
), row=1, col=2)
# 子圖(2,1):柱狀圖
fig.add_trace(go.Bar(
x=['華東', '華南', '華北', '西南', '華中', '東北'],
y=[580, 420, 380, 250, 310, 190],
name='區(qū)域',
marker=dict(color=['#1E88E5', '#E53935', '#43A047', '#FB8C00', '#9C27B0', '#00BCD4'])
), row=2, col=1)
# 子圖(2,2):面積圖
fig.add_trace(go.Scatter(
x=['Q1', 'Q2', 'Q3', 'Q4'], y=[60, 79, 101, 104],
fill='tozeroy', name='利潤(rùn)',
line=dict(color='#E53935', width=2),
fillcolor='rgba(229, 57, 53, 0.3)'
), row=2, col=2)
fig.update_layout(
title=dict(text='年度經(jīng)營(yíng)數(shù)據(jù)看板', x=0.5, font=dict(size=20)),
showlegend=False,
height=700,
font=dict(size=12)
)
fig.show()
4.2 復(fù)雜布局(不規(guī)則網(wǎng)格)
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import numpy as np
# 創(chuàng)建不規(guī)則布局:上方大圖 + 下方兩個(gè)小圖
fig = make_subplots(
rows=3, cols=2,
row_heights=[0.5, 0.25, 0.25],
specs=[[{'colspan': 2}, None], # 第一行橫跨兩列
[{'type': 'xy'}, {'type': 'xy'}], # 第二行兩個(gè)子圖
[{'colspan': 2}, None]] # 第三行橫跨兩列
)
x = np.linspace(0, 10, 100)
# 上方大圖:多條曲線
fig.add_trace(go.Scatter(x=x, y=np.sin(x), name='sin(x)', line=dict(color='#1E88E5')), row=1, col=1)
fig.add_trace(go.Scatter(x=x, y=np.cos(x), name='cos(x)', line=dict(color='#E53935')), row=1, col=1)
# 左下:散點(diǎn)
np.random.seed(42)
fig.add_trace(go.Scatter(
x=np.random.randn(100), y=np.random.randn(100),
mode='markers', name='隨機(jī)數(shù)據(jù)',
marker=dict(color=np.random.randn(100), colorscale='Viridis',
size=8, showscale=True)
), row=2, col=1)
# 右下:柱狀圖
fig.add_trace(go.Bar(
x=['A', 'B', 'C', 'D'], y=[45, 32, 58, 29],
marker_color=['#4CAF50', '#FF9800', '#2196F3', '#9C27B0']
), row=2, col=2)
# 底部:面積圖
fig.add_trace(go.Scatter(
x=list(range(30)), y=np.cumsum(np.random.randn(30)),
fill='tozeroy', fillcolor='rgba(229, 57, 53, 0.3)',
line=dict(color='#E53935')
), row=3, col=1)
fig.update_layout(
title=dict(text='綜合數(shù)據(jù)看板', x=0.5, font=dict(size=18)),
height=900,
font=dict(size=12)
)
fig.show()
五、高級(jí)交互功能
5.1 自定義懸停信息
import plotly.graph_objects as go
import pandas as pd
import numpy as np
# 模擬產(chǎn)品數(shù)據(jù)
np.random.seed(42)
df = pd.DataFrame({
'產(chǎn)品': [f'產(chǎn)品{i}' for i in range(1, 16)],
'銷售額': np.random.randint(100, 500, 15),
'利潤(rùn)率': np.random.uniform(10, 40, 15),
'增長(zhǎng)率': np.random.uniform(-10, 30, 15),
'庫(kù)存天數(shù)': np.random.randint(5, 60, 15)
})
fig = go.Figure()
fig.add_trace(go.Scatter(
x=df['銷售額'], y=df['利潤(rùn)率'],
mode='markers',
marker=dict(
size=df['庫(kù)存天數(shù)'] / 2, # 氣泡大小
color=df['增長(zhǎng)率'], # 顏色
colorscale='RdYlGn', # 紅黃綠漸變
showscale=True,
colorbar=dict(title='增長(zhǎng)率(%)')
),
# 自定義懸停模板
hovertemplate=
'<b>%{text}</b><br><br>' +
'銷售額: %{x:,.0f} 萬(wàn)元<br>' +
'利潤(rùn)率: %{y:.1f}%<br>' +
'庫(kù)存天數(shù): %{marker.size:.0f} 天<br>' +
'<extra></extra>', # 隱藏 trace name
text=df['產(chǎn)品']
))
fig.update_layout(
title='產(chǎn)品矩陣分析(氣泡=庫(kù)存,顏色=增長(zhǎng)率)',
title=dict(x=0.5, font=dict(size=16)),
xaxis=dict(title='銷售額(萬(wàn)元)', gridcolor='lightgray'),
yaxis=dict(title='利潤(rùn)率(%)', gridcolor='lightgray'),
font=dict(size=13)
)
fig.show()
5.2 添加按鈕和下拉選擇器
import plotly.graph_objects as go
import numpy as np
# 生成數(shù)據(jù):不同產(chǎn)品的銷售曲線
np.random.seed(42)
months = [f'{i}月' for i in range(1, 13)]
fig = go.Figure()
products = {
'產(chǎn)品A': np.cumsum(np.random.normal(20, 10, 12)) + 100,
'產(chǎn)品B': np.cumsum(np.random.normal(15, 8, 12)) + 80,
'產(chǎn)品C': np.cumsum(np.random.normal(25, 12, 12)) + 120
}
for name, data in products.items():
fig.add_trace(go.Scatter(
x=months, y=data, name=name,
mode='lines+markers', visible=True
))
# 創(chuàng)建按鈕
buttons = []
for i, name in enumerate(products.keys()):
visibility = [False] * len(products)
visibility[i] = True
buttons.append(dict(
label=name,
method='update',
args=[{'visible': visibility},
{'title': f'{name} 月度銷售趨勢(shì)'}]
))
# 添加"全部顯示"按鈕
buttons.append(dict(
label='全部顯示',
method='update',
args=[{'visible': [True] * len(products)},
{'title': '所有產(chǎn)品月度銷售趨勢(shì)'}]
))
fig.update_layout(
updatemenus=[dict(
buttons=buttons,
direction='down',
showactive=True,
x=0.1, y=1.15,
xanchor='left', yanchor='top',
bgcolor='white',
bordercolor='gray'
)],
title=dict(text='產(chǎn)品趨勢(shì)查看器', x=0.5, font=dict(size=16)),
font=dict(size=13)
)
fig.show()
六、動(dòng)畫(huà)效果
Plotly 可以為圖表添加動(dòng)畫(huà),讓數(shù)據(jù)"動(dòng)"起來(lái)。
import plotly.express as px
import pandas as pd
import numpy as np
# 模擬數(shù)據(jù):各區(qū)域月度銷售額變化(帶動(dòng)畫(huà))
np.random.seed(42)
records = []
for month in range(1, 13):
for region in ['華東', '華南', '華北', '西南', '華中']:
base = {'華東': 500, '華南': 350, '華北': 300, '西南': 200, '華中': 250}[region]
growth = month * 20
records.append({
'區(qū)域': region,
'月份': f'{month}月',
'月序號(hào)': month,
'銷售額': base + growth + np.random.normal(0, 30),
'利潤(rùn)率': np.random.uniform(15, 35)
})
df = pd.DataFrame(records)
# 創(chuàng)建帶動(dòng)畫(huà)的散點(diǎn)圖
fig = px.scatter(df, x='銷售額', y='利潤(rùn)率',
animation_frame='月序號(hào)', # 動(dòng)畫(huà)按月份推進(jìn)
animation_group='區(qū)域',
color='區(qū)域',
size='銷售額',
range_x=[100, 800],
range_y=[10, 40],
title='各區(qū)域銷售額與利潤(rùn)率月度演變',
labels={'銷售額': '銷售額(萬(wàn)元)', '利潤(rùn)率': '利潤(rùn)率(%)'},
color_discrete_map={'華東': '#1E88E5', '華南': '#E53935',
'華北': '#43A047', '西南': '#FB8C00', '華中': '#9C27B0'})
fig.update_layout(
title=dict(x=0.5, font=dict(size=16)),
font=dict(size=13)
)
# 設(shè)置動(dòng)畫(huà)速度
fig.layout.updatemenus[0].buttons[0].args[1]['frame']['duration'] = 500
fig.show()
七、導(dǎo)出與分享
7.1 導(dǎo)出為 HTML
import plotly.express as px
import pandas as pd
import numpy as np
# 創(chuàng)建示例圖表
np.random.seed(42)
df = pd.DataFrame({
'月份': [f'{i}月' for i in range(1, 13)],
'銷售額': [120, 135, 148, 162, 175, 190, 210, 225, 240, 230, 215, 250]
})
fig = px.bar(df, x='月份', y='銷售額',
title='月度銷售額(可導(dǎo)出為HTML)',
color='銷售額',
color_continuous_scale='Blues')
# 導(dǎo)出為 HTML 文件
fig.write_html('月度銷售報(bào)告.html',
full_html=True, # 包含完整的 HTML 頁(yè)面
include_plotlyjs=True, # 內(nèi)嵌 Plotly.js 庫(kù)
auto_open=False) # 不自動(dòng)打開(kāi)瀏覽器
print("HTML 文件已保存為: 月度銷售報(bào)告.html")
print("用瀏覽器打開(kāi)此文件即可查看交互式圖表")
7.2 導(dǎo)出為靜態(tài)圖片
# 導(dǎo)出為 PNG(需要安裝 kaleido: pip install kaleido)
# fig.write_image('chart.png', width=1200, height=600, scale=2)
# 導(dǎo)出為 PDF
# fig.write_image('chart.pdf')
# 導(dǎo)出為 SVG(矢量圖)
# fig.write_image('chart.svg')
print("提示:導(dǎo)出靜態(tài)圖片需要安裝 kaleido 庫(kù)")
print("安裝命令: pip install kaleido")
實(shí)戰(zhàn)練習(xí)
練習(xí)一:交互式銷售儀表盤(pán)
創(chuàng)建一個(gè)包含以下內(nèi)容的交互式銷售儀表盤(pán):
- 月度銷售趨勢(shì)折線圖(可縮放查看特定時(shí)間段)
- 各產(chǎn)品線銷售占比餅圖(懸停顯示金額)
- 區(qū)域銷售對(duì)比柱狀圖
- 散點(diǎn)圖:廣告投入與銷售額關(guān)系,氣泡大小代表利潤(rùn)
參考答案:
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import pandas as pd
import numpy as np
np.random.seed(42)
# 創(chuàng)建儀表盤(pán)布局
fig = make_subplots(
rows=2, cols=2,
subplot_titles=('月度銷售趨勢(shì)', '產(chǎn)品線占比', '區(qū)域銷售對(duì)比', '廣告投入-銷售額矩陣'),
specs=[[{'type': 'xy'}, {'type': 'domain'}],
[{'type': 'xy'}, {'type': 'xy'}]]
)
# 圖1:趨勢(shì)
months = [f'{i}月' for i in range(1, 13)]
sales = [120, 135, 148, 162, 175, 190, 210, 225, 240, 230, 215, 250]
fig.add_trace(go.Scatter(x=months, y=sales, mode='lines+markers',
line=dict(color='#1E88E5', width=3),
marker=dict(size=8), fill='tozeroy',
fillcolor='rgba(30, 136, 229, 0.1)',
name='銷售額'),
row=1, col=1)
# 圖2:餅圖
fig.add_trace(go.Pie(labels=['電子', '服裝', '食品', '家居'],
values=[450, 320, 280, 180],
marker=dict(colors=['#1E88E5', '#E53935', '#43A047', '#FB8C00']),
textinfo='label+percent+value', hole=0.4),
row=1, col=2)
# 圖3:柱狀圖
regions = ['華東', '華南', '華北', '西南', '華中', '東北']
reg_sales = [580, 420, 380, 250, 310, 190]
fig.add_trace(go.Bar(x=regions, y=reg_sales,
marker=dict(color=['#1E88E5', '#E53935', '#43A047',
'#FB8C00', '#9C27B0', '#00BCD4'])),
row=2, col=1)
# 圖4:散點(diǎn)
n = 50
ad = np.random.uniform(10, 80, n)
rev = 2.5 * ad + np.random.normal(0, 20, n)
profit = np.random.uniform(10, 60, n)
fig.add_trace(go.Scatter(x=ad, y=rev, mode='markers',
marker=dict(size=profit/3, color=profit,
colorscale='Viridis', showscale=True,
colorbar=dict(title='利潤(rùn)'))),
row=2, col=2)
fig.update_layout(
title=dict(text='銷售數(shù)據(jù)交互式儀表盤(pán)', x=0.5, font=dict(size=20)),
height=800, showlegend=False, font=dict(size=12)
)
# 導(dǎo)出
fig.write_html('銷售儀表盤(pán).html', full_html=True)
print("儀表盤(pán)已導(dǎo)出為: 銷售儀表盤(pán).html")
fig.show()
練習(xí)二:A/B測(cè)試結(jié)果可視化
模擬一個(gè)A/B測(cè)試場(chǎng)景:兩組用戶分別在4周內(nèi)使用新舊版產(chǎn)品,追蹤每周的轉(zhuǎn)化率。創(chuàng)建交互式圖表展示結(jié)果。
參考答案:
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import numpy as np
np.random.seed(42)
fig = make_subplots(
rows=1, cols=2,
subplot_titles=('轉(zhuǎn)化率趨勢(shì)對(duì)比', '累計(jì)轉(zhuǎn)化數(shù)對(duì)比')
)
weeks = [f'第{i}周' for i in range(1, 5)]
# A組(對(duì)照組)
conv_a = [3.2, 3.5, 3.8, 4.0]
cum_a = [320, 350, 380, 400]
# B組(實(shí)驗(yàn)組)
conv_b = [3.1, 3.4, 4.0, 4.5]
cum_b = [310, 340, 400, 450]
# 轉(zhuǎn)化率折線
fig.add_trace(go.Scatter(x=weeks, y=conv_a, name='A組(舊版)',
mode='lines+markers', line=dict(color='#1E88E5', width=3),
marker=dict(size=10)), row=1, col=1)
fig.add_trace(go.Scatter(x=weeks, y=conv_b, name='B組(新版)',
mode='lines+markers', line=dict(color='#E53935', width=3, dash='dash'),
marker=dict(size=10, symbol='square')), row=1, col=1)
# 累計(jì)轉(zhuǎn)化面積
fig.add_trace(go.Scatter(x=weeks, y=cum_a, name='A組累計(jì)',
fill='tozeroy', fillcolor='rgba(30,136,229,0.2)',
line=dict(color='#1E88E5')), row=1, col=2)
fig.add_trace(go.Scatter(x=weeks, y=cum_b, name='B組累計(jì)',
fill='tozeroy', fillcolor='rgba(229,57,53,0.2)',
line=dict(color='#E53935')), row=1, col=2)
fig.update_layout(
title=dict(text='A/B測(cè)試:新舊版產(chǎn)品對(duì)比', x=0.5, font=dict(size=18)),
height=450, font=dict(size=13)
)
fig.write_html('AB測(cè)試報(bào)告.html', full_html=True)
print("報(bào)告已導(dǎo)出為: AB測(cè)試報(bào)告.html")
fig.show()
本節(jié)總結(jié)
本節(jié)我們系統(tǒng)學(xué)習(xí)了 Plotly 交互式可視化的核心技能:
- Plotly Express:一行代碼創(chuàng)建交互式圖表,與 Seaborn 用法類似
- 交互式散點(diǎn)圖:懸停顯示詳情、顏色/大小編碼多維度信息
- 柱狀圖與折線圖:支持分組、堆疊、誤差線等多種變體
- 子圖布局:make_subplots 靈活組合多種圖表類型
- 高級(jí)交互:自定義懸停信息、按鈕控件、下拉選擇器、動(dòng)畫(huà)效果
- 導(dǎo)出分享:HTML 文件可在瀏覽器中直接打開(kāi),無(wú)需安裝任何軟件
- 靜態(tài)導(dǎo)出:借助 kaleido 庫(kù)導(dǎo)出 PNG、PDF、SVG 等格式
核心認(rèn)知:Plotly 的最大價(jià)值在于"讓圖表會(huì)說(shuō)話"。靜態(tài)圖表展示的是"結(jié)果",而交互式圖表讓讀者可以"探索"數(shù)據(jù)本身。在商業(yè)匯報(bào)中,一個(gè)交互式儀表盤(pán)往往勝過(guò) 20 頁(yè)靜態(tài)PPT。
以上就是Python利用Plotly打造可縮放的數(shù)據(jù)報(bào)告的詳細(xì)內(nèi)容,更多關(guān)于Python Plotly可縮放數(shù)據(jù)報(bào)告的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Django上傳excel表格并將數(shù)據(jù)寫(xiě)入數(shù)據(jù)庫(kù)的詳細(xì)步驟
這篇文章主要介紹了Django上傳excel表格并將數(shù)據(jù)寫(xiě)入數(shù)據(jù)庫(kù),將文件上傳到服務(wù)器指定路徑,其實(shí)很簡(jiǎn)單,本文分三個(gè)步驟給大家詳細(xì)介紹,需要的朋友可以參考下2022-06-06
Python基于pillow庫(kù)實(shí)現(xiàn)生成圖片水印
這篇文章主要介紹了Python基于pillow庫(kù)實(shí)現(xiàn)生成圖片水印,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09
一文教會(huì)你用Python繪制動(dòng)態(tài)可視化圖表
數(shù)據(jù)可視化是數(shù)據(jù)科學(xué)中關(guān)鍵的一步,下面這篇文章主要給大家介紹了關(guān)于如何利用Python繪制動(dòng)態(tài)可視化圖表的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-05-05
python 從csv讀數(shù)據(jù)到mysql的實(shí)例
今天小編就為大家分享一篇python 從csv讀數(shù)據(jù)到mysql的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-06-06
Python?paddleocr快速使用及參數(shù)配置詳解
PaddleOCR是基于PaddlePaddle深度學(xué)習(xí)框架的開(kāi)源OCR工具,但它提供了推理模型/訓(xùn)練模型/預(yù)訓(xùn)練模型,用戶可以直接使用推理模型進(jìn)行識(shí)別,也可以對(duì)訓(xùn)練模型或預(yù)訓(xùn)練模型進(jìn)行再訓(xùn)練,這篇文章主要介紹了Python?paddleocr快速使用及參數(shù)詳解,需要的朋友可以參考下2024-06-06

