?再見 Seaborn!Altair 數(shù)據(jù)可視化已超神
數(shù)據(jù)可視化對于通過將數(shù)據(jù)轉(zhuǎn)換為視覺效果來揭示數(shù)據(jù)中隱藏的趨勢和模式非常重要。為了可視化任何形式的數(shù)據(jù),我們都可能在某個(gè)時(shí)間點(diǎn)使用過數(shù)據(jù)透視表和圖表,如條形圖、直方圖、餅圖、散點(diǎn)圖、折線圖、基于地圖的圖表等。這些很容易理解并幫助我們傳達(dá)準(zhǔn)確的信息。基于詳細(xì)的數(shù)據(jù)分析,我們可以決定如何最好地利用手頭的數(shù)據(jù),幫助我們做出明智的決定。
如果你是數(shù)據(jù)科學(xué)或機(jī)器學(xué)習(xí)初學(xué)者,你肯定已經(jīng)嘗試過 Matplotlib 和 Seaborn 來進(jìn)行數(shù)據(jù)可視化。毫無疑問,他們都是用于數(shù)據(jù)分析的兩個(gè)最常用的強(qiáng)大的開源 Python 數(shù)據(jù)可視化庫。
Seaborn 和 Altair
Seaborn 基于 Matplotlib,并為構(gòu)建信息統(tǒng)計(jì)可視化提供了一個(gè)高級接口。但是,有一種替代 Seaborn 的方法。這個(gè)庫被稱為Altair,這是一個(gè)為統(tǒng)計(jì)數(shù)據(jù)可視化而構(gòu)建的開源 Python 庫。根據(jù)官方文檔(https://altair-viz.github.io/),它基于 Vega 和 Vega-lite 語言。使用 Altair,我們可以通過類似于 Seaborn 圖的條形圖、直方圖、散點(diǎn)圖和氣泡圖、網(wǎng)格圖和誤差圖等創(chuàng)建交互式數(shù)據(jù)可視化。

雖然 Matplotlib 庫在語法風(fēng)格上是命令式的,但 Altair 和 Seaborn 庫在方法上都是聲明式的,即用戶只需要指定要做什么,機(jī)器決定它的部分。這使用戶可以自由地專注于解釋數(shù)據(jù),而不是忙于編寫正確的語法。這種聲明式方法的唯一缺點(diǎn)可能是用戶對自定義可視化的控制較少,這對于大多數(shù)不熟悉編碼部分的用戶來說是可以的。
在本文中,我們將 Seaborn 與 Altair 進(jìn)行比較。為了進(jìn)行比較,我們將使用這兩個(gè)庫創(chuàng)建相同的可視化集,并得出結(jié)論,在易用性、語法、可視化外觀和樣式以及自定義可視化的能力方面,一個(gè)庫是否比另一個(gè)具有明顯優(yōu)勢。本文完整數(shù)據(jù)和代碼,可聯(lián)系原文作者云朵君獲取!
安裝 Seaborn 和 Altair
要從 PyPi 安裝這些庫,請使用以下命令
pip?install?altair
pip?install?seaborn
報(bào)錯(cuò)與處理
如果你使用的是 Jupyter Notebook,并且首次運(yùn)行,有如下錯(cuò)誤
Error?loading?script:?Script?error?for?"vega-embed"?http://requirejs.org/docs/errors.html#scripterror
這就涉及到在 Jupyter Notebook 中顯示的問題
經(jīng)典的 Jupyter Notebook 將通過實(shí)時(shí)網(wǎng)絡(luò)連接與 Altair 的默認(rèn)渲染器一起使用:不需要渲染啟用步驟,或者,對于 Jupyter Notebook 中的離線渲染,可以使用 Notebook 渲染器:
alt.renderers.enable('notebook')
如果報(bào)錯(cuò):
NoSuchEntryPoint:?No?'notebook'?entry?point?found?in?group?'altair.vegalite.v4.renderer'
則需要安裝:
pip?install?vega
或者conda中
conda?install?vega?--channel?conda-forge
在舊版本的筆記本 (<5.3) 中,需要額外啟用擴(kuò)展:
jupyter?nbextension?install?--sys-prefix?--py?vega
如果以上方法還不管用(如果你也遇到了同樣的問題,并且有了更好的解決方案的,可以聯(lián)系云朵君,一起學(xué)習(xí)),那就建議你使用??Jupyter Lab,并設(shè)置:
import?altair?as?alt
alt.renderers.enable('mimetype')
正常顯示就沒有問題了。

導(dǎo)入基本庫和數(shù)據(jù)集
與往常一樣,我們導(dǎo)入 Pandas 和 NumPy 庫來處理數(shù)據(jù)集、Matplotlib 和 Seaborn,以及用于構(gòu)建可視化的新安裝庫 Altair。
#導(dǎo)入需要的庫
import?pandas?as?pd
import?numpy?as?np
import?seaborn?as?sns
Import?matplotlib.pyplot?as?plt
import?altair?as?alt
我們將使用來自 seaborn 數(shù)據(jù)集庫的“mpg”或“miles per gallon”數(shù)據(jù)集來生成這些不同的圖。這個(gè)著名的數(shù)據(jù)集包含各種品牌汽車模型的 398 個(gè)樣本和 9 個(gè)屬性。
#導(dǎo)入數(shù)據(jù)集??
df?=?sns.load_dataset('mpg')
df.shape
>>>(398, 9)
#數(shù)據(jù)集列名
df.keys()
輸出
Index(['mpg',?'cylinders',?‘displacement',?‘horsepower',?‘weight',
???????'acceleration',?‘model_year',?‘origin',?'name'],
???????dtype='object')
#檢查數(shù)據(jù)類型
df.dtypes
#檢查數(shù)據(jù)集
df.head()

這個(gè)數(shù)據(jù)集很簡單,很好地融合了分類和數(shù)字特征?,F(xiàn)在繪制圖表進(jìn)行比較。
散點(diǎn)圖和氣泡圖
我們將從簡單的散點(diǎn)圖和氣泡圖開始。我們將使用'mpg'和'horsepower'變量。
Seaborn
對于 Seaborn 散點(diǎn)圖,可以使用?relplot?命令并將“散點(diǎn)圖”作為繪圖類型傳遞
sns.relplot(y='mpg',x='horsepower',data=df,
????????????kind='scatter',size='displacement',
????????????hue='origin',aspect=1.2);
或者可以直接使用?scatterplot?命令。
sns.scatterplot(data=df,?x="horsepower",?y="mpg",?
????????????????size="displacement",?hue='origin',
????????????????legend=True)
Altair
而對于 Altair,使用以下語法
alt.Chart(df).mark_point().encode(alt.Y('mpg'),
??????????????????????????????????alt.X('horsepower'),
??????????????????????????????????alt.Color('origin'),
??????????????????????????????????alt.OpacityValue(0.7),
??????????????????????????????????size='displacement')

在這兩個(gè)庫中,我們將數(shù)據(jù)源的 DataFrame 和先前選擇的"horsepower"、"mpg"列分別作為 x 和 y 傳遞??梢允褂昧硪粋€(gè)屬性?"origin"?為圖例條目著色,并使用兩個(gè)庫的附加變量?"displacement"?控制點(diǎn)的大小。
在 Seaborn 中,我們可以使用?"aspect"?設(shè)置來控制繪圖的縱橫比。但是,在?Altair?中,我們還可以通過傳遞 0 到 1 之間的值來控制點(diǎn)的不透明度值(1 表示完全不透明)。
要將 Seaborn 中的散點(diǎn)圖轉(zhuǎn)換為氣泡圖,只需為"sizes"傳遞一個(gè)值,該值表示圖表中氣泡的最小和最大尺寸。對于 Altair,我們只需通過 (filled=True) 來生成氣泡圖。
sns.scatterplot(data=df,?x="horsepower",?y="mpg",?
????????????????size="displacement",?hue='origin',
????????????????legend=True,?sizes=(10,?500))
alt.Chart(df).mark_point(filled=True).encode(
????x='horsepower',
????y='mpg',
????size='displacement',
????color='origin'
)

通過以上散點(diǎn)圖,我們可以理解"horsepower"和"mpg"變量之間的關(guān)系,即"horsepower"較低的車輛似乎具有較高的"mpg"。兩個(gè)圖的語法相似,可以自定義以顯示值。
折線圖
現(xiàn)在,我們繪制"horsepower"和"mpg"屬性的折線圖。線圖的語法對兩者都非常簡單。我們將 DataFrame 作為數(shù)據(jù)傳遞,上述兩個(gè)變量為 x 和 y,而?'origin'?作為圖例顏色。
Seaborn
sns.lineplot(data=df,?x='horsepower',?
?????????????y='acceleration',hue='origin')
Altair
alt.Chart(df).mark_line().encode(
????alt.X('horsepower'),
????alt.Y('acceleration'),
????alt.Color('origin')
????)

在這里我們可以理解"usa"車輛具有更高的"horsepower"范圍,而其他兩個(gè)"japan"和?"europe"?的"horsepower"范圍更窄。同樣,這兩個(gè)圖都很好地提供了相同的信息并且看起來同樣出色。
條形圖和計(jì)數(shù)圖
在下一組可視化中,我們將繪制一個(gè)基本的條形圖和計(jì)數(shù)圖。這一次,我們還將添加一個(gè)圖表標(biāo)題。我們將使用"cylinders"和"mpg"屬性作為繪圖的 x 和 y。
對于 Seaborn 圖,我們將上述兩個(gè)特征與 Dataframe 一起傳遞。為了自定義顏色,我們從 Seaborn 的預(yù)定義調(diào)色板中選擇了一個(gè)Palette='magma_r'。
sns.catplot(x='cylinders',?y='mpg',?
????????????hue="origin",?kind="bar",?
????????????data=df,?palette='magma_r')
在 Altair 條形圖中,我們傳遞 df、x 和 y,并根據(jù)"origin"特征指定顏色。在這里,我們可以通過在"mark_bar"命令中傳遞一個(gè)值來自定義條形的大小,如下所示。
plot=alt.Chart(df).mark_bar(size=40).encode(
????alt.X('cylinders'),
????alt.Y('mpg'),
????alt.Color('origin')
)
plot.properties(title='cylinders?vs?mpg')

從上面的條形圖中,我們可以看到帶有 4 個(gè)汽缸的車輛對于"mpg"值似乎是最有效的。
這是計(jì)數(shù)圖的語法
Seaborn
我們使用 FacetGrid 命令根據(jù)變量"origin"在網(wǎng)格上顯示多個(gè)圖。

g?=?sns.FacetGrid(df,?col="cylinders",?
??????????????????height=4,aspect=.5,
??????????????????hue='origin',palette='magma_r')
g.map(sns.countplot,?"origin",?
??????order?=?df['origin'].value_counts().index)
Altair
我們再次使用"mark_bar"命令,但將圓柱列的"count()"作為 y 傳遞以生成計(jì)數(shù)圖。
alt.Chart(df).mark_bar().encode(
????x='origin',
????y='count()',
????column='cylinders:Q',
????color=alt.Color('origin')
).properties(
????width=100,
????height=100??
)

從這兩個(gè)計(jì)數(shù)圖中,我們可以很容易地理解"japan"有 (3,4,6) 缸車輛,"europe"有 (4,5,6) 缸車輛,"usa"有 (4,6,8) 缸車輛汽缸車。從語法的角度來看,這些庫需要數(shù)據(jù)源的輸入 x、y 來繪制。兩個(gè)庫的輸出看起來還挺不錯(cuò)的。
接下來嘗試更多的圖并進(jìn)行比較。
直方圖
在這組可視化中,我們將繪制基本的直方圖。在 Seaborn 中,我們使用?distplot?命令并傳遞數(shù)據(jù)框的名稱,要繪制的列的名稱。我們還可以使用"aspect"設(shè)置"寬高比"來調(diào)整繪圖的高度和寬度。
Seaborn
sns.distplot(df,?x='model_year',?aspect=1.2)
Altair
alt.Chart(df).mark_bar().encode(
????alt.X("model_year:Q",?bin=True),
????y='count()',
).configure_mark(
????opacity=0.7,
????color='cyan'
)

在這組可視化中,兩個(gè)庫的選定默認(rèn)?bin?不同,因此繪圖看起來略有不同。我們可以通過調(diào)整?bin?大小在 Seaborn 中獲得相同的圖。
sns.displot(df,?x='model_year',
????????????bins=[70,72,74,76,78,80,82],
????????????aspect=1.2)
現(xiàn)在情節(jié)看起來很相似。然而,在這兩個(gè)圖中,我們可以看到最大的車輛數(shù)量是在 76 年之后,并且在 82 年尤為突出。此外,我們使用了一個(gè)配置命令來修改條的顏色和不透明度,這在 Altair 情節(jié)的情況下就像一個(gè)主題。
帶狀圖
對于 Seaborn,我們將使用?stripplot?命令并將整個(gè) DataFrame 和變量"cylinders"、"horsepower"分別傳遞給 x 和 y。
ax?=?sns.stripplot(data=df,?y=?‘horsepower’,?x=?‘cylinders’)
對于 Altair 圖,我們使用 mark_tick 命令生成具有相同變量的帶狀圖。
alt.Chart(df).mark_tick(filled=True).encode(
????x='horsepower:Q',
????y='cylinders:O',
????color='origin'
)

從上面的圖中,我們可以清楚地看到不同"origin"的分類變量"cylinders"的散布情況。這兩個(gè)圖表在傳達(dá)氣缸數(shù)之間的關(guān)系方面似乎同樣有效。對于 Altair 圖,我們會(huì)發(fā)現(xiàn) x 和 y 列在語法中已互換,以避免出現(xiàn)更高和更窄的圖。
交互圖
我們現(xiàn)在來到這個(gè)比較中的最后一組可視化——交互式繪圖。
與 Bokeh、Plotly 和 Dash 庫相比,Altair 在交互式繪圖方面語法更簡單。另一方面,Seaborn 不提供與任何圖表的交互性。如果你想過濾掉繪圖本身內(nèi)部的數(shù)據(jù)并專注于繪圖中感興趣的區(qū)域/區(qū)域,就不建議使用Seaborn。
為了在 Altair 中設(shè)置交互式圖表,我們定義了一個(gè)具有"interval"類型選擇的選擇,即在圖表上的兩個(gè)值之間。然后我們使用之前定義的選擇定義列的活動(dòng)點(diǎn)。接下來,我們指定要為選擇顯示的圖表類型(繪制在主圖表下方)并傳遞"select"作為顯示值的過濾器。
select?=?alt.selection(type='interval')
values?=?alt.Chart(df).mark_point().encode(
????x='horsepower:Q',
????y='mpg:Q',
????color=alt.condition(select,?'origin:N',?alt.value('lightgray'))
).add_selection(
????select
)
bars?=?alt.Chart(df).mark_bar().encode(
????y='origin:N',
????color='origin:N',
????x='count(origin):Q'
).transform_filter(
????select
)
values?&?bars

對于交互式繪圖,我們可以輕松地可視化所選區(qū)域的樣本數(shù)。當(dāng)圖表的一個(gè)區(qū)域中有太多樣本/點(diǎn)并且我們想要可視化它們的細(xì)節(jié)以更好地理解基礎(chǔ)數(shù)據(jù)時(shí),這很有用。
Altair 其他要點(diǎn)
餅圖和甜甜圈圖
可惜的是,Altair 不支持餅圖。這是 Seaborn 獲勝的一個(gè)點(diǎn),我們可以利用 matplotlib 功能通過 Seaborn 庫生成餅圖。
繪制網(wǎng)格、主題和自定義繪圖大小
這兩個(gè)庫還允許在生成多個(gè)繪圖、操縱縱橫比或圖形大小方面自定義繪圖,并支持為顏色和背景設(shè)置不同的主題以修改圖表的外觀。
高級繪圖
此外,還有其他高級繪圖,如棒棒糖或破折號和點(diǎn)圖、熱圖、樹狀圖,可以使用這兩個(gè)庫進(jìn)行繪制(Seaborn 可能為此需要一些額外的包),但在此比較中這些已被排除在外以保持它簡單的。
寫在最后
我們繪制了不少 Seaborn 和 Altair 的各種類型的圖。數(shù)據(jù)可視化庫——Seaborn 和 Altair 看起來同樣強(qiáng)大。
與 Altair 相比,Seaborn 的語法更易于編寫和理解;而與 Seaborn 圖相比,Altair 中的數(shù)據(jù)可視化似乎更加美觀及引人注目。生成交互式可視化的能力是 Altair 提供的另一個(gè)優(yōu)勢。因此,選擇其中之一取決于個(gè)人喜好和可視化要求。
理想情況下,這兩個(gè)庫都可以自給自足地處理大部分?jǐn)?shù)據(jù)可視化需求。如果你需要快速繪制簡單的圖作為數(shù)據(jù)分析的一部分,那么請選擇 Seaborn。此外,如果你的項(xiàng)目需要餅圖,那么 matplotlib 或 Seaborn 是你的首選。如果要獲得交互式且外觀略微精致的可視化效果,可以選擇 Altair。
推薦閱讀
牛逼!Python常用數(shù)據(jù)類型的基本操作(長文系列第①篇)
牛逼!Python的判斷、循環(huán)和各種表達(dá)式(長文系列第②篇)
推薦閱讀
牛逼!Python常用數(shù)據(jù)類型的基本操作(長文系列第①篇)
牛逼!Python的判斷、循環(huán)和各種表達(dá)式(長文系列第②篇)
