『Plotly實戰指南』--Plotly與Pandas的深度融合
在數據分析的世界中,數據處理與可視化是密不可分的兩個環節。
Pandas作為Python數據處理的核心工具,以其強大的數據清洗、轉換和分析能力,成為數據科學家和分析師的必備利器;
而Plotly則是交互式可視化的佼佼者,能夠將復雜的數據以直觀、動態的方式呈現出來。
當我們將Pandas與Plotly深度融合時,就能無縫銜接數據清洗、分析與可視化的全流程,大幅提升數據分析的效率和效果。
1. 從Pandas數據結構到Plotly圖表
1.1. Series 與 DataFrame 數據創建圖表
Plotly提供了強大的plotly.express模塊,能夠直接讀取Pandas的數據結構,如Series和DataFrame,并快速生成各種交互式圖表。
例如,使用px.line(df)可以將一個時間序列的DataFrame轉換為折線圖,而px.bar(series)則可以將一個Series轉換為條形圖。
import pandas as pd
import numpy as np
import plotly.express as px
# 創建一個示例 DataFrame
data = {
"date": pd.date_range(start="2024-01-01", periods=100),
"sales": np.random.randint(100, 500, size=100),
}
df = pd.DataFrame(data)
# 使用 Plotly Express 創建折線圖
fig = px.line(df, x="date", y="sales", title="時間序列銷售數據")
fig.show()

在這個例子中,x='date'和y='sales'將DataFrame的列名映射到了圖表的坐標軸上。
將數據中的某個列(Series)取出來,可以直接繪制條形圖。
series = df["sales"]
fig = px.bar(series)
fig.show()

1.2. 索引與繪圖的關聯
Pandas的索引(如時間戳、分類標簽)在繪圖中也扮演著重要角色。
我們可以直接將Pandas索引作為圖表的坐標軸,從而簡化數據處理過程。
比如,如果一個DataFrame的索引是時間戳,那么它默認就成為X軸。
data = {
"date": pd.date_range(start="2024-01-01", periods=100),
"sales": np.random.randint(100, 500, size=100),
}
df = pd.DataFrame(data)
# 將日期設置為索引
df.set_index('date', inplace=True)
# 繪制圖表,不需要指定X軸
fig = px.line(df, y='sales', title='以索引為時間軸的銷售數據')
fig.show()

對于多級索引(MultiIndex)數據,Plotly也提供了強大的支持。
我們可以利用多級索引來生成分面圖(Facet Plot)或動態篩選圖表。
# 創建多級索引
df = df.reset_index()
df["region"] = ["North", "South"] * 50
df.set_index(["region", "date"], inplace=True)
# 繪制分面圖
fig = px.line(
df.reset_index(),
x="date",
y="sales",
facet_col="region",
title="按地區分面的銷售數據",
)
fig.show()

在處理多級索引時,需要注意索引重置與列名轉換的問題。
上面的示例中,我們先將date索引轉換為普通列,然后把普通列region和date一起轉換為多級索引。
2. 數據預處理與可視化的交響曲
2.1. 數據清洗與驗證可視化
在實際的數據分析中,數據往往存在缺失值和異常值。
Pandas提供了豐富的數據清洗工具,而Plotly可以將清洗前后的數據可視化出來,讓我們更好的把握數據的變化。
首先,生成包含客戶年齡(含缺失值和異常值)、銷售額(對數正態分布)和區域的模擬數據集。
import pandas as pd
import numpy as np
import plotly.express as px
# 模擬含噪聲數據
np.random.seed(42)
dates = pd.date_range('2023-01-01', periods=100)
# Customer_Age 年齡包含異常值(生成平均40,標準差30的數據)
df = pd.DataFrame({
'Date': dates,
'Customer_Age': np.random.normal(40, 30, 100),
})
# 人為添加缺失值
df.loc[np.random.choice(100, 15), 'Customer_Age'] = np.nan
故意添加15%的年齡缺失值,并設置年齡范圍異常(生成年齡的部分中有異常的年齡)。
然后,繪制原始數據的分布圖:
# 原始數據分布
raw_hist = px.histogram(
df,
x='Customer_Age',
title='原始數據分布(含缺失值與異常值)',
labels={'Customer_Age': '客戶年齡'},
nbins=20
)
raw_hist.show()

接下來,開始清洗數據:
dropna():刪除年齡缺失的行query():過濾年齡異常值(保留18-65歲)
# 清洗數據
clean_df = (
df
.dropna(subset=['Customer_Age']) # 刪除缺失值
.query('18 <= Customer_Age <= 65') # 過濾異常值
)
清洗之后再次繪制分布圖:
# 清洗后分布
clean_hist = px.histogram(
clean_df,
x='Customer_Age',
title='清洗后數據分布',
labels={'Customer_Age': '客戶年齡'},
nbins=20,
color_discrete_sequence=['#2ca02c']
)
clean_hist.show()

通過這種方式,我們可以直觀地看到數據清洗的效果,從而更好地評估數據的質量。
2.2. 數據聚合與高級可視化
Pandas的groupby()和pivot_table()是數據聚合的強大工具。
我們可以利用Pandas進行數據重塑,然后用Plotly來繪制重塑之后數據的高級可視化,甚至是通過自定義動畫控制按鈕增強交互體驗。
下面的示例中,我們先生成一些銷售示例數據:
# 模擬數據
np.random.seed(42)
dates = pd.date_range('2023-01-01', periods=100)
df = pd.DataFrame({
'Date': dates,
'Sales': np.random.lognormal(3, 0.5, 100),
'Region': np.random.choice(['北部', '南部', '東部', '西部'], 100)
})
# 對銷售額進行對數轉換(解決右偏分布)
df["Sales"] = np.log(df["Sales"])
然后,生成透視數據并繪制熱力圖。
# 生成透視數據
pivot_df = df.pivot_table(
index=pd.Grouper(key='Date', freq='W'), # 按周聚合
columns='Region',
values='Sales',
aggfunc='mean'
).ffill() # 前向填充缺失值
# 熱力圖
heatmap = px.imshow(
pivot_df.T, # 轉置使時間為X軸
x=pivot_df.index.strftime('%Y-%m-%d'),
y=pivot_df.columns,
labels={'x': '日期', 'y': '區域'},
color_continuous_scale='RdBu_r',
title='區域周均銷售額熱力圖'
)
heatmap.update_layout(height=500)
heatmap.show()

最后,按照月份聚合數據,并生成動態分層柱狀圖,看各個區域隨著時間變化銷售額是如何變化的。
# 動態分層柱狀圖
# 生成聚合數據
agg_df = (
df
.assign(Year_Month=lambda x: x['Date'].dt.to_period('M'))
.groupby(['Year_Month', 'Region'], as_index=False)
['Sales'].mean()
.assign(Year_Month=lambda x: x['Year_Month'].dt.to_timestamp())
)
# 創建動畫圖表
animated_bar = px.bar(
agg_df,
x='Region',
y='Sales',
animation_frame=agg_df['Year_Month'].dt.strftime('%Y-%m'),
range_y=[agg_df['Sales'].min()*0.9, agg_df['Sales'].max()*1.1],
labels={'Sales': '平均銷售額(對數)'},
title='區域銷售趨勢動態演示',
color='Region',
color_discrete_sequence=px.colors.qualitative.Pastel
)
# 優化動畫設置
animated_bar.update_layout(
xaxis={'categoryorder': 'total descending'},
hovermode='x unified',
updatemenus=[{
"buttons": [
{
"args": [None, {"frame": {"duration": 500, "redraw": True},
"fromcurrent": True,
"transition": {"duration": 300}}],
"label": "播放",
"method": "animate"
},
{
"args": [[None], {"frame": {"duration": 0, "redraw": True},
"mode": "immediate",
"transition": {"duration": 0}}],
"label": "暫停",
"method": "animate"
}
],
"direction": "left",
"pad": {"r": 10, "t": 87},
"showactive": False,
"type": "buttons",
"x": 0.1,
"xanchor": "right",
"y": 0,
"yanchor": "top"
}]
)
animated_bar.show()

3. 總結
Plotly與Pandas的深度融合為數據分析提供了一個強大的工具鏈。
從臟數據到洞察力,Pandas 負責數據的清洗和預處理,而 Plotly 則負責將處理后的數據以直觀、動態的方式呈現出來。
這種協同工作模式不僅提升了數據分析的效率,還幫助我們更好地理解數據背后的含義。
在實際應用中,數據處理與可視化的不可分割性至關重要。
高質量的圖表依賴于高質量的數據,而 Plotly 與 Pandas 的結合正是實現這一目標的最佳選擇。

浙公網安備 33010602011771號