Seaborn中文教程(一):可視化變量間的關系

眾所周知亿胸,Seaborn“可能”是Python下最友好汹想、易用的可視化工具了,可視化效果也非常好腺律。但是截止目前奕短,并沒有一份中文教程供廣大國內Python使用者查閱學習宜肉。怎么能因為語言的問題,讓大家錯過這么好用的一個可視化工具呢翎碑?

思考再三谬返,我決定花一些時間將官方的英文文檔整理出來,為大家提供一份最權威的中文教程日杈∏猜粒考慮到我的時間比較碎片化,這項工作可能會在未來的幾周內完成莉擒,感興趣的朋友可以先關注和收藏下酿炸,后續(xù)的更新會在簡書和我的個人博客中(www.data-insights.cn/www.data-insight.cn)發(fā)布。

今天涨冀,我整理了第一部分:如何用Seaborn可視化變量之間的關系填硕,這一部分非常實用,基本上學習后馬上就能給我們帶來很多幫助鹿鳖。那么接下來扁眯,就開始我們的學習吧!

文章較長翅帜,建議收藏后在PC站或者我的個人博客閱讀姻檀。


統(tǒng)計分析是這樣的一個過程:嘗試去理解一個數(shù)據(jù)集中變量之間的關系,以及這些關系如何受到其他變量的影響涝滴⌒灏妫可視化是這個過程的核心元素,因為當數(shù)據(jù)以非常恰當?shù)姆绞秸故境鰜頃r狭莱,我們可以非常直觀地觀察到某些趨勢或者模式僵娃,而這些,就揭示了變量之間的關系腋妙。

在這篇教程中,我們會討論三個seaborn函數(shù)讯榕。我們用的最多的是relplot()骤素。這是一個圖形級別的函數(shù),它用散點圖和線圖兩種常用的手段來表現(xiàn)統(tǒng)計關系愚屁。relplot()使用兩個坐標軸級別的函數(shù)來結合了FacetGrid

  • scatterplot():(使用kind="scatter"济竹,這是默認參數(shù))
  • lineplot():(使用`kind="line")

正如我們所見,這些函數(shù)非常直白霎槐,因為它們用了簡單易懂的展示方式送浊,卻可以呈現(xiàn)復雜的數(shù)據(jù)集結構。這是因為通過hue丘跌、size袭景、style參數(shù)唁桩,我們可以在二維圖形中表現(xiàn)出更多的變量(除了x軸和y軸的兩個,還可以通過不同的方式額外展示3個變量)耸棒。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(style="darkgrid")

一荒澡、用散點圖展示相關變量

散點圖是統(tǒng)計圖形中的中流砥柱。它用一系列的散點將兩個變量的聯(lián)合分布描繪出來与殃,其中每個點就是一個觀測樣本单山。這種描述方式可以讓我們從視覺上推斷出大量信息,來判斷兩個變量之間是否存在某種有意義的關系幅疼。

seaborn中米奸,我們有數(shù)種方法可以實現(xiàn)散點圖的繪制。最基本的一種適用于兩個變量都是數(shù)值型變量的情況爽篷,它就是scatterplot()悴晰。在分類可視化教程中,我們會看到如何繪制分類數(shù)據(jù)的散點圖狼忱。relplot()的默認類型(kind)就是scatterplot()(當然膨疏,我們也可以強制指定參數(shù)kind="scatter",這和不指定這一參數(shù)時效果是一樣的)钻弄。

tips = sns.load_dataset("tips")
sns.relplot(x="total_bill", y="tip", data=tips);
png

當我們已經將散點繪制在二維的平面上時佃却,我們還可以根據(jù)第三個變量來對這些點施以不同的顏色,從而引入一個新的維度窘俺。在seaborn中饲帅,我們用hue參數(shù)實現(xiàn)了這種想法,因為點的顏色是有意義的瘤泪。

sns.relplot(x="total_bill", y="tip", hue="smoker", data=tips);
png

如果我們想要強調不同分類之間的差異灶泵,同時增加易讀性,我們可以對不同的分類使用不同的標記樣式:

sns.relplot(x="total_bill", y="tip", hue="smoker", style="smoker", data=tips);
png

我們也可以同時展示四個變量对途,只需要將huestyle參數(shù)單獨調整到不同的分類變量即可赦邻。但是我們要謹慎使用這種方法,因為我們的眼睛對于形狀的敏感性遠遠不如對顏色的敏感性实檀。

sns.relplot(x="total_bill", y="tip", hue="smoker", style="time", data=tips);
png

在上邊這個例子中惶洲,hue參數(shù)對應的變量是分類型數(shù)據(jù),因此seaborn自動為它應用了默認的定性(分類)調色板膳犹。如果hue參數(shù)對應的變量是數(shù)值型的(可轉化為浮點數(shù)的)恬吕,那么默認的顏色也會隨之變?yōu)檫B續(xù)的定量調色板。

sns.relplot(x="total_bill", y="tip", hue="size", data=tips);
png

上述兩種情況下(分類或連續(xù)數(shù)據(jù))须床,我們都可以自定義我們的調色板铐料。有很多選項可以實現(xiàn)這一目的。下面,我們使用cubehelix_palette()的字符串接口來定制我們的連續(xù)調色板:

sns.relplot(x="total_bill", y="tip", hue="size", 
            palette="ch:r=-.5,l=.75", data=tips);
png

我們還可以使用點的大小來引入第三個額外的變量:

sns.relplot(x="total_bill", y="tip", size="size", data=tips);
png

matplotlib.pyplot.scatter()不同的是钠惩,這里并不是使用原始數(shù)據(jù)中的數(shù)值來為每個點選擇面積大小柒凉,seaborn將原始數(shù)據(jù)歸一化(正則化)到了某個范圍,這個范圍可以由我們來指定:

sns.relplot(x="total_bill", y="tip", size="size", sizes=(15, 200), data=tips);
png

更多關于如何定制不同參數(shù)來展示統(tǒng)計關系的示例可以在scatterplot()的API中找到妻柒。

二扛拨、使用線圖表現(xiàn)連續(xù)性

散點圖很高效,但是沒有哪種可視化類型可以完美應對所有情況举塔。事實上绑警,我們的可視化呈現(xiàn)方式要適應數(shù)據(jù)集的種類以及我們想要通過圖形回答的問題。

在某些數(shù)據(jù)集中央渣,我們可能想要理解某個變量隨著時間的變化規(guī)律计盒,或者想要理解某個連續(xù)型的變量。這種情況下芽丹,線圖會是一個不錯的選擇北启。在seaborn中,我們可以通過lineplot()函數(shù)或者使用帶有kind="line"參數(shù)的relplot()來實現(xiàn)線圖的繪制拔第。

df = pd.DataFrame(dict(time=np.arange(500), value=np.random.randn(500).cumsum()))
g = sns.relplot(x="time", y="value", kind="line", data=df)
g.fig.autofmt_xdate()
png

由于lineplot()假設用戶在大多數(shù)情況下是在嘗試描繪y相對于x的函數(shù)(變化規(guī)律)咕村,因此它在繪制之前會默認先對x做一個排序。不過我們可以禁止它蚊俺。

df = pd.DataFrame(np.random.randn(500, 2).cumsum(axis=0), columns=["x", "y"])
sns.relplot(x="x", y="y", sort=False, kind="line", data=df);
png

聚合并展示不確定性

在更多復雜的數(shù)據(jù)集中懈涛,會出現(xiàn)一個x軸變量對應了多個觀測值(y)的情況。seaborn會默認將多個觀測值聚合起來泳猬,并且將它們的均值以及95%的置信區(qū)間展示出來:

fmri = sns.load_dataset("fmri")
sns.relplot(x="timepoint", y="signal", kind="line", data=fmri);
png

置信區(qū)間是通過自助采樣法(bootstrapping)計算的批钠,這在遇到大型數(shù)據(jù)集時可以幫助我們節(jié)省時間。當然得封,我們也可以禁止它埋心。

sns.relplot(x="timepoint", y="signal", ci=None, kind="line", data=fmri);
png

另一個不錯的選擇是,我們可以用標準差替代置信區(qū)間來展示每個時間點下觀測值的分布忙上,當數(shù)據(jù)集比較大時這一選擇尤其明智拷呆。

sns.relplot(x="timepoint", y="signal", kind="line", ci="sd", data=fmri);
png

如果想要關閉所有的聚合操作,我們可以設置estimator=None疫粥。不過當同一時間點存在多個觀測值時洋腮,我們的圖會看起來有些奇怪。

sns.relplot(x="timepoint", y="signal", estimator=None, kind="line", data=fmri);
png

通過參數(shù)映射可視化數(shù)據(jù)子集

lineplot()scatterplot()一樣具有很強的靈活性:它也可以通過hue手形、sizestyle參數(shù)來展示額外的三個變量。它和scatterplot()使用了相同的API悯恍,因此我們不需要停下來絞盡腦汁地思考哪些參數(shù)是用來控制線條库糠、哪些參數(shù)是用來控制散點。

使用不同的參數(shù)會決定我們的數(shù)據(jù)如何聚合。比如瞬欧,增加一個具有兩個水平的分類變量作為hue參數(shù)贷屎,會將我們的圖形分為兩條線以及兩個誤差帶,并分別施以不同的顏色來區(qū)分數(shù)據(jù)的分類歸屬艘虎。

sns.relplot(x="timepoint", y="signal", hue="event", 
            kind="line", data=fmri);
png

我們可以增加一個style參數(shù)唉侄,以不同的線條樣式來展示不同的分類:

sns.relplot(x="timepoint", y="signal",  hue="region",  
            style="event", kind="line", data=fmri);
png

我們還可以設置不同分類的標記樣式,標記樣式既可以和線條樣式同時設置野建,也可以各自單獨設置属划。

sns.relplot(x="timepoint", y="signal", hue="region", style="event", 
            dashes=False, markers=True, kind="line", data=fmri);
png

跟散點圖一樣,我們要慎重使用這些參數(shù)來展示太多變量候生。有些時候它們會展示豐富的信息同眯,但是有些時候它們會使圖形太過復雜導致我們難以解析和解釋它。然而當你僅打算考慮額外的一個變量時唯鸭,同時修改它們的顏色和樣式會很有幫助须蜗。當需要考慮到色盲人群時,將圖形顏色設置為黑白色調則是一個不錯的選擇目溉。

sns.relplot(x="timepoint", y="signal", hue="event", style="event",
            kind="line", data=fmri);
png

當我們需要應對重復測量的數(shù)據(jù)時明肮,我們可以將不同的抽樣單元(單次實驗觀測到的數(shù)據(jù)系列)分離開來展示,這并不需要我們使用一個語義參數(shù)(hue/style/size)缭付。后者會導致圖例看起來像一個災難(想象一下幾十個分類的情況):

sns.relplot(x="timepoint", y="signal",  hue="region", 
            units="subject", estimator=None, kind="line", 
            data=fmri.query("event == 'stim'"));
png

scatterplot()類似柿估,lineplot()默認的調色板以及圖例處理方式也取決于hue對應的數(shù)據(jù)是分類型還是連續(xù)數(shù)值型。

dots = sns.load_dataset("dots").query("align == 'dots'")
sns.relplot(x="time", y="firing_rate",
            hue="coherence", style="choice",
            kind="line", data=dots);
png

hue參數(shù)對應的變量的數(shù)據(jù)是均勻分布在對數(shù)刻度上的(即數(shù)據(jù)分布范圍非常大蛉腌,比如從1到1億)官份,即使是連續(xù)的調色板也無法很好地應對這種情況。但是我們可以使用列表或者字典對每條線指定一個顏色烙丛。

palette = sns.cubehelix_palette(light=.8, n_colors=6)
sns.relplot(x="time", y="firing_rate",
            hue="coherence", style="choice",
            palette=palette,
            kind="line", data=dots);
png

或者我們可以直接修改調色板數(shù)值的正則方式:

from matplotlib.colors import LogNorm
palette = sns.cubehelix_palette(light=.7, n_colors=6)
sns.relplot(x="time", y="firing_rate", hue="coherence", style="choice",
            hue_norm=LogNorm(), kind="line", data=dots);
png

不要忘了我們還有個size參數(shù)舅巷,它用來修改線條的寬度:

sns.relplot(x="time", y="firing_rate", size="coherence", 
            style="choice", kind="line", data=dots);
png

size一般接受連續(xù)數(shù)值型變量,但是我們也可以傳入分類型變量河咽。但是要慎重考慮這種做法钠右,因為這樣比“粗線 vs. 細線”的區(qū)分難多了。然而忘蟹,當數(shù)據(jù)具有非常高頻的變異性時飒房,我們使用style表現(xiàn)的不同線條樣式會很難區(qū)分,這時使用不同的線條寬度就是一個更高效的選擇了:

sns.relplot(x="time", y="firing_rate",
           hue="coherence", size="choice",
           palette=palette,
           kind="line", data=dots);
png

繪制時間序列數(shù)據(jù)

線圖常用來描繪日期媚值、時間相關的詩句狠毯。這些方法以原始格式傳入更底層的matplotlib函數(shù)中,這樣它們就可以利用matplotlib的能力來格式化日期數(shù)據(jù)褥芒。但是所有的時間格式化過程都是在matplotlib層實現(xiàn)的嚼松,想要知道更多實現(xiàn)的細節(jié)就需要去看一下matplotlib中關于這部分的文檔:

df = pd.DataFrame(dict(time=pd.date_range("2017-1-1", periods=500),
                       value=np.random.randn(500).cumsum()))
g = sns.relplot(x="time", y="value", kind="line", data=df)
g.fig.autofmt_xdate()
png

三、用更多子圖展示多重關系

前邊我們已經強調過,雖然我們可以在一張圖中展示數(shù)個不同的語義變量(通過hue/style/size參數(shù))献酗,但是這么做并不是總會高效寝受。那么當我們真的很想理解在某些額外變量的影響下兩個變量之間的關系有什么不同時怎么辦呢?

最好的辦法就是畫更多的圖罕偎。由于relplot()是基于FacetGrid的很澄,因此這很容易做到。當我們想要表現(xiàn)出一個額外變量的影響時颜及,我們可以不用將它賦給前邊提到的語義參數(shù)(hue/style/size)甩苛,而是用它來將圖形“面板”化。這意味著我們會創(chuàng)建多個坐標軸器予,分別用來繪制不同的子數(shù)據(jù)集:

sns.relplot(x="total_bill", y="tip", hue="smoker", col="time", data=tips);
png

我們還可以同時使用col(列)和row(行)參數(shù)來展示兩個變量的影響浪藻。當我們在圖中增加了更多的變量時(會有更多的子圖),我們可能會想要調整圖形的大小乾翔。要記住在FacetGrid中爱葵,我們用height(子圖高度)和aspect(高寬比)來定制每個子圖的大小:

sns.relplot(x="timepoint", y="signal", hue="subject", col="region", 
            row="event", height=3, kind="line", estimator=None, data=fmri);
png

當我們想要檢驗某個具有大量水平的變量的影響時反浓,我們可以將這個變量賦給col參數(shù)萌丈,同時我們通過col_wrap參數(shù)設置每行達到多少列就換行:

sns.relplot(x="timepoint", y="signal", hue="event", style="event",
            col="subject", col_wrap=5,
            height=3, aspect=.75, linewidth=2.5,
            kind="line", data=fmri.query("region == 'frontal'"));
png

這種常被叫做“格子圖”或“small-multiples”的可視化方式,非常高效雷则,因為它們呈現(xiàn)數(shù)據(jù)的方式使得我們很容易同時發(fā)現(xiàn)整體的模式以及不同模式之間的偏差辆雾。當你需要利用scatterplot()relplot()的靈活性來表現(xiàn)更多信息時,一定要記住月劈,多幅簡單的圖通常比一幅復雜的圖更加高效度迂。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市猜揪,隨后出現(xiàn)的幾起案子惭墓,更是在濱河造成了極大的恐慌,老刑警劉巖而姐,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件腊凶,死亡現(xiàn)場離奇詭異,居然都是意外死亡拴念,警方通過查閱死者的電腦和手機钧萍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來政鼠,“玉大人风瘦,你說我怎么就攤上這事」悖” “怎么了弛秋?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵器躏,是天一觀的道長。 經常有香客問我蟹略,道長,這世上最難降的妖魔是什么遏佣? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任挖炬,我火速辦了婚禮,結果婚禮上状婶,老公的妹妹穿的比我還像新娘意敛。我一直安慰自己,他們只是感情好膛虫,可當我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布草姻。 她就那樣靜靜地躺著,像睡著了一般稍刀。 火紅的嫁衣襯著肌膚如雪撩独。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天账月,我揣著相機與錄音综膀,去河邊找鬼。 笑死局齿,一個胖子當著我的面吹牛剧劝,可吹牛的內容都是我干的。 我是一名探鬼主播抓歼,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼讥此,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了谣妻?” 一聲冷哼從身側響起萄喳,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎拌禾,沒想到半個月后取胎,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡湃窍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年闻蛀,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片您市。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡觉痛,死狀恐怖,靈堂內的尸體忽然破棺而出茵休,到底是詐尸還是另有隱情薪棒,我是刑警寧澤手蝎,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站俐芯,受9級特大地震影響棵介,放射性物質發(fā)生泄漏。R本人自食惡果不足惜吧史,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一阴颖、第九天 我趴在偏房一處隱蔽的房頂上張望杈湾。 院中可真熱鬧,春花似錦、人聲如沸滞详。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽棘脐。三九已至,卻和暖如春冰啃,著一層夾襖步出監(jiān)牢的瞬間邓夕,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工亿笤, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留翎迁,地道東北人。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓净薛,卻偏偏與公主長得像汪榔,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子肃拜,可洞房花燭夜當晚...
    茶點故事閱讀 45,060評論 2 355