導讀:我們介紹過用matplotlib制作圖表的一些tips,感興趣的同學可以戳→純干貨:手把手教你用Python做數(shù)據(jù)可視化(附代碼)。matplotlib是一個相當?shù)讓拥墓ぞ?。你可以從其基本組件中組裝一個圖表:數(shù)據(jù)顯示(即繪圖的類型:線、條、框、散點圖、輪廓等)、圖例、標題、刻度標記和其他注釋。
在pandas中,我們可能有多個數(shù)據(jù)列,并且?guī)в行泻土械臉撕灐andas自身有很多內(nèi)建方法可以簡化從DataFrame和Series對象生成可視化的過程。另一個是seaborn,它是由Michael Waskom創(chuàng)建的統(tǒng)計圖形庫。seaborn簡化了很多常用可視化類型的生成。
導入seaborn會修改默認的matplotlib配色方案和繪圖樣式,這會提高圖表的可讀性和美觀性。即使你不適用seaborn的API,你可能更喜歡導入seaborn來為通用matplotlib圖表提供更好的視覺美觀度。
作者:Wes McKinney
本文摘編自《利用Python進行數(shù)據(jù)分析》(原書第2版),如需轉(zhuǎn)載請聯(lián)系我們
01 折線圖
Series和DataFrame都有一個plot屬性,用于繪制基本的圖型。默認情況下,plot()繪制的是折線圖(見圖9-13):
In [
60
]: s
=
pd.Series(np.random.randn(
10
).cumsum(), index
=
np.arange(
0
,
100
,
10
))
In [
61
]: s.plot()
▲圖9-13 簡單序列圖形
Series對象的索引傳入matplotlib作為繪圖的x軸,你可以通過傳入use_index=False來禁用這個功能。x軸的刻度和范圍可以通過xticks和xlim選項進行調(diào)整,相應地y軸使用yticks和ylim進行調(diào)整。表9-3是plot的全部選項列表。本節(jié)我會介紹這些選項中的一些,其余你可以自行探索。
大部分pandas的繪圖方法,接收可選的ax參數(shù),該參數(shù)可以是一個matplotlib子圖對象。這使你可以更為靈活的在網(wǎng)格布局中放置子圖。
DataFrame的plot方法在同一個子圖中將每一列繪制為不同的折線,并自動生成圖例(見圖9-14):
In [
62
]: df
=
pd.DataFrame(np.random.randn(
10
,
4
).cumsum(
0
),
....: columns
=
[
'A'
,
'B'
,
'C'
,
'D'
],
....: index
=
np.arange(
0
,
100
,
10
))
In [
63
]: df.plot()
▲圖9-14 簡單DataFrame繪圖
plot屬性包含了不同繪圖類型的方法族。例如,df.plot( )等價于df.plot.line( )。我們之后將會探索這些方法中的一部分。
要繪制的其他關鍵字參數(shù)會傳遞到相應的matplotlib繪圖函數(shù),因此你可以通過了解更多的matplotlib的 API信息來進一步定制這些圖表。
參數(shù) | 描述 |
label | 圖例標簽 |
ax | 繪圖所用的matplotlib子圖對象;如果沒傳值,則使用當前活動的matplotlib子圖 |
style | 傳給matplotlib的樣式字符串,比如'ko--' |
alpha | 圖片不透明度(從0到1) |
kind | 可以是 'area'、 'bar'、 'barh'、 'density'、'hist'、 'kde'、 'line'、 'pie' |
logy | 在y軸上使用對數(shù)縮放 |
use_index | 使用對象索引刻度標簽 |
rot | 刻度標簽的旋轉(zhuǎn)(0到360) |
xticks | 用于x軸刻度的值 |
yticks | 用于y軸 |
xlim | x軸范圍(例如[0,10]) |
ylim | y軸范圍 |
grid | 展示軸網(wǎng)格(默認是打開的) |
▲表9-3 Series.plot方法參數(shù)
DataFrame擁有多個選項,允許靈活地處理列;例如,是否將各列繪制到同一個子圖中,或為各列生成獨立的子圖。參考表9-4了解更多選項。
參數(shù) | 描述 |
subplots | 將DataFrame的每一列繪制在獨立的子圖中 |
sharex | 如果subplots=True,則共享相同的x軸、刻度和范圍 |
sharey | 如果subplots=True,則共享相同的y軸 |
figsize | 用于生成圖片尺寸的元組 |
title | 標題字符串 |
legend | 添加子圖圖例(默認是True) |
sort_columns | 按字母順序繪制各列,默認情況下使用已有的列順序 |
▲表9-4
02 柱狀圖
plot.bar()和plot.barh()可以分別繪制垂直和水平的柱狀圖。在繪制柱狀圖時,Series或DataFrame的索引將會被用作x軸刻度(bar)或y軸刻度(barh)(參考圖9-15):
In [
64
]: fig, axes
=
plt.subplots(
2
,
1
)
In [
65
]: data
=
pd.Series(np.random.rand(
16
), index
=
list
(
'abcdefghijklmnop'
))
In [
66
]: data.plot.bar(ax
=
axes[
0
], color
=
'k'
, alpha
=
0.7
)
Out[
66
]: <>
0x7fb62493d470
>
In [
67
]: data.plot.barh(ax
=
axes[
1
], color
=
'k'
, alpha
=
0.7
)
▲圖9-15 水平柱狀圖和垂直柱狀圖
選項color='k'和alpha=0.7將柱子的顏色設置為黑色,并將圖像的填充色設置為部分透明。
在DataFrame中,柱狀圖將每一行中的值分組到并排的柱子中的一組。參考圖9-16:
In [
69
]: df
=
pd.DataFrame(np.random.rand(
6
,
4
),
....: index
=
[
'one'
,
'two'
,
'three'
,
'four'
,
'five'
,
'six'
],
....: columns
=
pd.Index([
'A'
,
'B'
,
'C'
,
'D'
], name
=
'Genus'
))
In [
70
]: df
Out[
70
]:
Genus A B C D
one
0.370670
0.602792
0.229159
0.486744
two
0.420082
0.571653
0.049024
0.880592
three
0.814568
0.277160
0.880316
0.431326
four
0.374020
0.899420
0.460304
0.100843
five
0.433270
0.125107
0.494675
0.961825
six
0.601648
0.478576
0.205690
0.560547
In [
71
]: df.plot.bar()
▲圖9-16 DataFrame柱狀圖
請注意DataFrame的列名稱'Genus'被用作了圖例標題。我們可以通過傳遞stacked=True來生成堆積柱狀圖,會使得每一行的值堆積在一起(參考圖9-17):
In [
73
]: df.plot.barh(stacked
=
True
, alpha
=
0.5
)
▲圖9-17 DataFrame堆積柱狀圖
使用value_counts: s.value_counts().plot.bar()可以有效的對Series值頻率進行可視化。
回到本書之前使用的數(shù)據(jù)集,假設我們想要繪制一個堆積柱狀圖,用于展示每個派對在每天的數(shù)據(jù)點占比。使用read_csv載入數(shù)據(jù),并根據(jù)星期幾數(shù)值和派對規(guī)模進形成交叉表:
In [
75
]: tips
=
pd.read_csv(
'examples/tips.csv'
)
In [
76
]: party_counts
=
pd.crosstab(tips[
'day'
], tips[
'size'
])
In [
77
]: party_counts
Out[
77
]:
size
1
2
3
4
5
6
day
Fri
1
16
1
1
0
0
Sat
2
53
18
13
1
0
Sun
0
39
15
18
3
1
Thur
1
48
4
5
1
3
# 沒有太多的1人和6人派對
In [
78
]: party_counts
=
party_counts.loc[:,
2
:
5
]
之后,進行標準化以確保每一行的值和為1,然后進行繪圖(見圖9-18):
# 標準化至和為1
In [
79
]: party_pcts
=
party_counts.div(party_counts.
sum
(
1
), axis
=
0
)
In [
80
]: party_pcts
Out[
80
]:
size
2
3
4
5
day
Fri
0.888889
0.055556
0.055556
0.000000
Sat
0.623529
0.211765
0.152941
0.011765
Sun
0.520000
0.200000
0.240000
0.040000
Thur
0.827586
0.068966
0.086207
0.017241
In [
81
]: party_pcts.plot.bar()
▲圖9-18 每天派對數(shù)量的百分比
你可以看到本數(shù)據(jù)集中的派對數(shù)量在周末會增加。
對于在繪圖前需要聚合或匯總的數(shù)據(jù),使用seaborn包會使工作更為簡單。現(xiàn)在讓我們看下使用seaborn進行按星期幾數(shù)值計算小費百分比(見圖9-19中的結(jié)果圖):
In [
83
]:
import
seaborn as sns
In [
84
]: tips[
'tip_pct'
]
=
tips[
'tip'
]
/
(tips[
'total_bill'
]
-
tips[
'tip'
])
In [
85
]: tips.head()
Out[
85
]:
total_bill tip smoker day time size tip_pct
0
16.99
1.01
No Sun Dinner
2
0.063204
1
10.34
1.66
No Sun Dinner
3
0.191244
2
21.01
3.50
No Sun Dinner
3
0.199886
3
23.68
3.31
No Sun Dinner
2
0.162494
4
24.59
3.61
No Sun Dinner
4
0.172069
In [
86
]: sns.barplot(x
=
'tip_pct'
, y
=
'day'
, data
=
tips, orient
=
'h'
)
▲圖9-19 用錯誤欄按天顯示小費百分比
seaborn中的繪圖函數(shù)使用一個data參數(shù),這個參數(shù)可以是pandas的DataFrame。其他的參數(shù)則與列名有關。因為day列中有多個觀測值,柱子的值是tip_pct的平均值。柱子上畫出的黑線代表的是95%的置信區(qū)間(置信區(qū)間可以通過可選參數(shù)進行設置)。
seaborn.barplot擁有一個hue選項,允許我們通過一個額外的分類值將數(shù)據(jù)分離:
In [
88
]: sns.barplot(x
=
'tip_pct'
, y
=
'day'
, hue
=
'time'
, data
=
tips, orient
=
'h'
)
▲圖9-20 根據(jù)星期幾數(shù)值和時間計算的小費百分比
請注意seaborn自動改變了圖表的美觀性:默認的調(diào)色板、圖背景和網(wǎng)格線條顏色。你可以使用seaborn.set在不同的繪圖外觀中進行切換:
In [
90
]: sns.
set
(style
=
'whitegrid'
)
03 直方圖和密度圖
直方圖是一種條形圖,用于給出值頻率的離散顯示。數(shù)據(jù)點被分成離散的,均勻間隔的箱,并且繪制每個箱中數(shù)據(jù)點的數(shù)量。使用之前的小費數(shù)據(jù),我們可以使用Series的plot.hist方法制作小費占總費用百分比的直方圖(見圖9-21):
In [
92
]: tips[
'tip_pct'
].plot.hist(bins
=
50
)
▲圖9-21 小費百分比的直方圖
密度圖是一種與直方圖相關的圖表類型,它通過計算可能產(chǎn)生觀測數(shù)據(jù)的連續(xù)概率分布估計而產(chǎn)生。通常的做法是將這種分布近似為“內(nèi)核”的混合,也就是像正態(tài)分布那樣簡單的分布。因此,密度圖也被成為內(nèi)核密度估計圖(KDE)。plot.kde使用傳統(tǒng)法定混合法估計繪制密度圖(見圖9-22):
In [
94
]: tips[
'tip_pct'
].plot.density()
▲圖9-22 小費百分比密度圖
distplot方法可以繪制直方圖和連續(xù)密度估計,通過distplot方法seaborn使直方圖和密度圖的繪制更為簡單。作為例子,考慮由兩個不同的標準正態(tài)分布組成的雙峰分布(見圖9-23):
In [
96
]: comp1
=
np.random.normal(
0
,
1
, size
=
200
)
In [
97
]: comp2
=
np.random.normal(
10
,
2
, size
=
200
)
In [
98
]: values
=
pd.Series(np.concatenate([comp1, comp2]))
In [
99
]: sns.distplot(values, bins
=
100
, color
=
'k'
)
▲圖9-23 正態(tài)混合的標準化直方圖與密度估計
04 散點圖或點圖
點圖或散點圖可以用于檢驗兩個一維數(shù)據(jù)序列之間的關系。例如,這里我們從statsmodels項目中載入了macrodata數(shù)據(jù)集,并選擇了一些變量,之后計算對數(shù)差:
In [
100
]: macro
=
pd.read_csv(
'examples/macrodata.csv'
)
In [
101
]: data
=
macro[[
'cpi'
,
'm1'
,
'tbilrate'
,
'unemp'
]]
In [
102
]: trans_data
=
np.log(data).diff().dropna()
In [
103
]: trans_data[
-
5
:]
Out[
103
]:
cpi m1 tbilrate unemp
198
-
0.007904
0.045361
-
0.396881
0.105361
199
-
0.021979
0.066753
-
2.277267
0.139762
200
0.002340
0.010286
0.606136
0.160343
201
0.008419
0.037461
-
0.200671
0.127339
202
0.008894
0.012202
-
0.405465
0.042560
然后我們可以使用seaborn的reglot方法,該方法可以繪制散點圖,并擬合出一個條線性回歸線(見圖9-24):
In [
105
]: sns.regplot(
'm1'
,
'unemp'
, data
=
trans_data)
Out[
105
]: <>
0x7fb613720be0
>
In [
106
]: plt.title(
'Changes in log %s versus log %s'
%
(
'm1'
,
'unemp'
))
▲圖9-24 seaborn回歸/散點圖
在探索性數(shù)據(jù)分析中,能夠查看一組變量中的所有散點圖是有幫助的; 這被稱為成對圖或散點圖矩陣。從頭開始繪制這樣一個圖是有點工作量的,所以seaborn有一個方便的成對圖函數(shù),它支持在對角線上放置每個變量的直方圖或密度估計值(結(jié)果圖見圖9-25):
In [
107
]: sns.pairplot(trans_data, diag_kind
=
'kde'
, plot_kws
=
{
'alpha'
:
0.2
})
▲圖9-25 statsmodels macro數(shù)據(jù)的成對圖矩陣
你可能會注意到plot_ksw參數(shù),這個參數(shù)使我們能夠?qū)⑴渲眠x項傳遞給非對角元素上的各個繪圖調(diào)用。參考seaborn.pairplot的文檔字符串可以看到更多細節(jié)的設置選項。
05 分面網(wǎng)格和分類數(shù)據(jù)
如果數(shù)據(jù)集有額外的分組維度怎么辦?使用分面網(wǎng)格是利用多種分組變量對數(shù)據(jù)進行可視化的方式。seaborn擁有一個有效的內(nèi)建函數(shù)factorplot,可以簡化多種分面繪圖(見圖9-26):
In [
108
]: sns.factorplot(x
=
'day'
, y
=
'tip_pct'
, hue
=
'time'
, col
=
'smoker'
,
.....: kind
=
'bar'
, data
=
tips[tips.tip_pct <>
1
])
▲圖9-26 按星期幾數(shù)值/時間/是否吸煙劃分的小費百分比
除了根據(jù)'time'在一個面內(nèi)將不同的柱分組為不同的顏色,我們還可以通過每個時間值添加一行來擴展分面網(wǎng)格(見圖9-27):
In [
109
]: sns.factorplot(x
=
'day'
, y
=
'tip_pct'
, row
=
'time'
,
.....: col
=
'smoker'
,
.....: kind
=
'bar'
, data
=
tips[tips.tip_pct <>
1
])
▲圖9-27 根據(jù)時間/是否吸煙分面后按星期幾數(shù)值劃分的小費百分比
factorplot 支持其他可能有用的圖類型,具體取決于你要顯示的內(nèi)容。 例如,箱形圖(顯示中位值,四分位數(shù)和異常值)可以是有效的可視化類型(圖9-28):
In [
110
]: sns.factorplot(x
=
'tip_pct'
, y
=
'day'
, kind
=
'box'
,
.....: data
=
tips[tips.tip_pct <>
0.5
])
▲圖9-28 根據(jù)星期幾數(shù)值繪制的小費百分比箱型圖
你可以使用更通用的seaborn.FacetGrid類創(chuàng)建自己的分面網(wǎng)格圖。 具體請查看更多的seaborn文檔。
06 其他Python可視化工具
和開源代碼一樣,在Python語言下創(chuàng)建圖形的選擇有很多(太多而無法一一列舉)。自從2010年以來,很多開發(fā)工作都集中在創(chuàng)建web交互式圖形上。借助像Bokeh和Plotly這樣的工具,在web瀏覽器中創(chuàng)建動態(tài)的、交互式圖像的工作現(xiàn)在已經(jīng)可以實現(xiàn)。
如果是創(chuàng)建用于印刷或網(wǎng)頁的靜態(tài)圖形,我建議根據(jù)你的需要使用默認的matplotlib以及像pandas和seaborn這樣的附加庫。 對于其他數(shù)據(jù)可視化要求,學習其他可用工具之一可能是有用的。我鼓勵你探索Python可視化生態(tài)系統(tǒng),因為它將持續(xù)增添新內(nèi)容并在未來進行更多創(chuàng)新。
關于作者:韋斯·麥金尼(Wes McKinney)是流行的Python開源數(shù)據(jù)分析庫pandas的創(chuàng)始人。他是一名活躍的演講者,也是Python數(shù)據(jù)社區(qū)和Apache軟件基金會的Python/C++開源開發(fā)者。目前他在紐約從事軟件架構師工作。
聯(lián)系客服