使用Pandas,Seaborn和Plotly繪製漂亮的圖表

完整的代碼以及Python可視化指南,介紹了Pandas,Seaborn和Plotly的繪圖。python

2018: Regplot showing how Life Ladder (Happiness) is positively correlated with Log GDP per capita (git

 

在今天的文章中,咱們將研究使用Python繪製數據的三種不一樣方式。 咱們將經過利用《 2019年世界幸福報告》中的數據來作到這一點。我用Gapminder和Wikipedia的信息豐富了《世界幸福報告》數據,以便探索新的關係和可視化。github

《世界幸福報告》試圖回答哪些因素影響着全世界的幸福。express

報告中的幸福定義爲對" Cantril階梯問題"的回答,要求被調查者以0到10的等級來評價他們今天的生活,最糟糕的爲0,最好的爲10。編程

在整篇文章中,我將使用Life Ladder做爲目標變量。 每當咱們談論人生階梯時,請思考幸福是什麼。api

 


本文結構

Photo by Nik MacMillan on Unsplashapp

本文旨在做爲代碼指南,以及當您要查找特定類型的圖時從新訪問的參考。 爲了節省空間,我有時會將多個圖表合併爲一張圖像。 可是請放心,您能夠在此(https://github.com/FBosler/AdvancedPlotting)或相應的Jupyter Notebook中找到全部基礎代碼。框架

目錄dom

· 個人Python繪圖歷史ide

· 分佈的重要性

· 加載數據和包導入

· 快速:使用Pandas進行基本繪圖

· 漂亮:與Seaborn的高級繪圖

· 很棒:使用plotly建立出色的交互式圖

 


我使用Python繪圖的歷史

Photo by Krys Amon on Unsplash

大約兩年前,我開始更認真地學習Python。 從那之後,幾乎沒有一個星期不讓我驚歎於Python自己,或生態系統中衆多使人驚歎的開源庫的簡單性和易用性。 我熟悉的命令,模式和概念越多,那麼全部事情就越有意義。

Matplotlib

使用Python進行繪圖的狀況偏偏相反。 最初,我用Matplotlib建立的幾乎每一個圖表都看起來像是八十年代逃脫的罪犯。 更糟糕的是,要建立這些可憎的東西,我一般不得不在Stackoverflow上花費數小時。 例如,研究nitty-gritty命令以更改x-ticks的傾斜度或相似的愚蠢行爲。 甚至沒有讓我開始使用多張圖表。 結果看起來使人印象深入,而且以編程方式建立這些圖表是一種奇妙的感受。 例如,一次生成50個針對不一樣變量的圖表。 可是,這只是不少工做,須要您記住不少其餘原本沒用的命令。

Seaborn

瞭解Seaborn是一種解脫。 Seaborn提取了許多微調。 毫無疑問,最終圖表的美學意義是一個巨大的飛躍。 可是,它也是基於Matplotlib構建的。 一般,對於非標準調整,仍然有必要深刻了解機器級的matplotlib代碼。

Bokeh

簡要了解一下Bokeh,我覺得Bokeh將成爲個人首選解決方案。 當我從事地理空間可視化工做時遇到了Bokeh。 可是,我很快意識到,雖然Bokeh不同凡響,但它與matplotlib同樣複雜。

Plotly

我確實在一段時間前嘗試了plot.ly(從如今開始被稱爲plotly)。 再一次,致力於地理空間數據的可視化。 那時,它彷佛比前面提到的庫還要不靠譜。 您須要一個賬戶,必須經過筆記本電腦登陸,而後才能使全部內容在線呈現。 而後,您將下載結果圖表。 我迅速放棄了。 可是,最近,我看了一個有關YouTube的視頻,該視頻關於plotly express和plotly 4.0,最重要的是,他們擺脫了全部這些在線限制。 我玩了一下,這篇文章就是它的結果。 我想遲到總比沒有好。

Kepler.gl(地理空間數據榮譽獎)

Kepler.gl雖然絕對不是Python庫,但它是一種用於地理空間數據的基於Web的強大可視化工具。 您只須要CSV文件,便可使用Python輕鬆建立。 試試看!

我目前的工做流程

最終,我決定使用Pandas原始繪圖進行快速檢查,並使用Seaborn生成要在報告和演示文稿中使用的圖表(視覺效果很重要)。

 


分佈的重要性

Photo by Jonny Caspari on Unsplash

在聖地亞哥學習期間,我教過統計學(Stats 119)。 統計119是統計的入門課程。 該課程包括統計基礎,例如數據彙總(可視和定量),概率和機率的概念,迴歸,抽樣以及最重要的分佈。 此次是我對數量和現象的理解幾乎所有轉變爲基於分佈表示(大部分時間是高斯)。

時至今日,我發現這兩個數量的平均含義使人吃驚,而標準誤差能夠幫助您把握現象。 僅經過了解這兩個數字,就能夠輕鬆得出特定結果的可能性。 人們當即知道大部分結果將在哪裏。 它爲您提供了一個參考框架,能夠快速將軼事與有統計意義的事件區分開來,而無需進行過於複雜的計算。

通常而言,面對新數據時,個人第一步是嘗試可視化其分佈,以更好地理解數據。

 


加載數據和導入庫

Photo by Kelli Tungay on Unsplash

讓咱們加載本文中將要使用的數據。 我確實對數據進行了一些預處理。 我在有意義的地方進行數據填充處理。

# Load the data data = pd.read_csv('https://raw.githubusercontent.com/FBosler/AdvancedPlotting/master/combined_set.csv') 
# this assigns labels per year 
data['Mean Log GDP per capita'] = data.groupby('Year')['Log GDP per capita'].transform( pd.qcut, q=5, labels=(['Lowest','Low','Medium','High','Highest']) )

數據集包含如下各列的值:

· Year 年:計量年(從2007年到2018年)

· Life Ladder 人生階梯:受訪者根據Cantril階梯,以0到10的等級(10最佳)衡量他們今天的生活價值

· Log GDP per capita 對數人均GDP:根據購買力平價(PPP)調整的人均GDP,根據世界銀行於2018年11月14日發佈的世界發展指標(WDI)得出

· Social support 社會支持:對問題的回答:"若是遇到麻煩,您是否有親戚或朋友能夠在須要時幫助您?"

· Healthy life expectancy at birth 出生時的健康預期壽命:出生時的預期壽命是根據世界衛生組織(WHO)全球衛生觀察站數據存儲庫中的數據構建的,其中提供了200五、20十、2015和2016年的數據。

· Freedom to make life choices 選擇生活的自由度:對問題的回答:"您對選擇本身的生活的自由感到滿意仍是不滿意?"

· Generosity 慷慨度:與"人均GDP"相比,對"您在過去一個月向慈善機構捐款了嗎?"的迴應

· Perceptions of corruption 對腐敗的見解:回答"腐敗是否在整個政府範圍內普遍存在?"和"腐敗是否在企業內部普遍分佈?"

· Positive affect 積極影響:包括前一天的幸福,笑聲和享受的平均頻率。

· Negative affect 負面影響:包括前一天擔心,悲傷和憤怒的平均頻率。

· Confidence in national government 對國家政府的信心:不言自明

· Democratic Quality 民主素質:一個國家的民主程度

· Delivery Quality 交付質量:一個國家兌現其政策的效果如何

· Gapminder Life Expectancy Gapminder預期壽命:Gapminder的預期壽命

· Gapminder Population Gapminder人口:一個國家的人口

庫加載

import plotly 
import pandas as pd 
import numpy as np import seaborn as sns 
import plotly.express as px import matplotlib 
%matplotlib inline 
assert matplotlib.__version__ == "3.1.0",
""" 
Please install matplotlib version 3.1.0 by running: 
1) !pip uninstall matplotlib 
2) !pip install matplotlib==3.1.0 
"""

 


 

快速:使用Pandas進行基本繪圖

Photo by Marvin Meyer on Unsplash

Pandas具備內置的繪圖功能,能夠在Series或DataFrame上調用它。 我喜歡這些繪圖功能,由於它們簡潔,使用合理的默認值,而且能夠快速瞭解發生的狀況。

要建立繪圖,請對數據調用.plot(kind = ),以下所示:

np.exp(data[data['Year']==2018]['Log GDP per capita']).plot( kind='hist' )

運行上面的命令將產生如下圖表。

 

2018: Histogram of the number of countries per GDP per Capita bucket. Not surprisingly, most countri

 

使用Pandas進行繪圖時,有五個主要參數:

· kind:Pandas必須知道您要建立哪一種圖,如下選項可用hist,bar,barh,scatter,area,kde,line,box,hexbin,餅圖。

· figsize:容許覆蓋6英寸寬和4英寸高的默認輸出大小。 figsize須要一個元組(例如,我常用的figsize =(12,8))

· title:向圖表添加標題。 在大多數狀況下,我用它來澄清圖表中顯示的內容,以便當我回到圖表上時,能夠快速肯定發生了什麼。 title須要一個字符串。

· bins:容許覆蓋直方圖的bin寬度。 bins須要一個列表或相似列表的值序列(例如bins = np.arange(2,8,0.25))

· xlim / ylim:容許覆蓋軸的最大值和最小值的默認值。 xlim和ylim都指望有一個元組(例如xlim =(0,5))

讓咱們快速瀏覽各類可用的plots類型。

垂直條形圖

data[ data['Year'] == 2018 ]
.set_index('Country name')['Life Ladder']
.nlargest(15)
.plot( kind='bar', figsize=(12,8) )

2018: List of 15 happiest countries is led by Finnland

水平條形圖

np.exp(data[ data['Year'] == 2018 ]
.groupby('Continent')['Log GDP per capita']
.mean()).sort_values()
.plot( kind='barh', figsize=(12,8) )

Average GDP per capita by continent in 2011 USD Dollars clearly led by Australia and New Zealand

箱形圖

data['Life Ladder'].plot( kind='box', figsize=(12,8) )

Box plot of the distribution of Life Ladder shows that the median is somewhere around 5.5 ranging fr

散點圖

data[['Healthy life expectancy at birth','Gapminder Life Expectancy']]
.plot( 
kind='scatter', 
x='Healthy life expectancy at birth', 
y='Gapminder Life Expectancy', 
figsize=(12,8) )

Scatter plot of the World Happiness Report life expectation against the Gapminder life expectation s

六邊形圖

data[data['Year'] == 2018]
.plot( kind='hexbin', 
  x='Healthy life expectancy at birth', 
  y='Generosity', 
  C='Life Ladder', 
  gridsize=20, 
  figsize=(12,8),  
  cmap="Blues", # defaults to greenish 
  sharex=False # required to get rid of a bug )

2018: Hexbin plot, plotting life expectancy against generosity. The color of bins indicates the aver

餅圖

data[data['Year'] == 2018]
  .groupby( ['Continent'])['Gapminder Population'] 
  .sum() 
  .plot( 
    kind='pie', 
    figsize=(12,8), 
    cmap="Blues_r", # defaults to orangish 
  )

2018: Pie chart showing the total population by continent

堆積面積圖

data.groupby( ['Year','Continent'])['Gapminder Population']
 .sum()
 .unstack()
 .plot( 
    kind='area', 
    figsize=(12,8), 
    cmap="Blues", # defaults to orangish
 )

Population numbers accross the globe are on the rise.

折線圖

data[ data['Country name'] == 'Germany']
 .set_index('Year')['Life Ladder']
 .plot( kind='line', figsize=(12,8) )

Line chart depicting the development of happiness in Germany.

關於Pandas繪圖的結論

用Pandas繪圖很方便。 它易於訪問,並且速度很快。 Plot很難看。 偏離默認值是不可能的,這是能夠的,由於咱們還有其餘工具可使圖表更具美學吸引力。 去看看seaborn吧。

 


漂亮:Seaborn的高級繪圖

Seaborn使用繪圖默認值。 爲了確保您的結果與個人匹配,請運行如下命令。

sns.reset_defaults() 
sns.set(
 rc={'figure.figsize':(7,5)},
 style="white" # nicer layout )

繪製單變量分佈

如前所述,我很是喜歡分佈。 直方圖和核密度分佈都是可視化特定變量的關鍵特徵的有效方法。 讓咱們看看如何在一個圖表中爲單個變量或多個變量分配生成分佈。

Left chart: Histogram and kernel density estimation of "Life Ladder" for Asian countries in 2018; Ri

繪製雙變量分佈

每當我想直觀地探索兩個或多個變量之間的關係時,一般都會歸結爲某種形式的散點圖和分佈評估。 概念上類似的圖有三種變體。 在每一個圖中,中心圖(散點圖,雙變量KDE和hexbin)有助於理解兩個變量之間的聯合頻率分佈。 此外,在中心圖的右邊界和上邊界,描繪了各個變量的邊際單變量分佈(做爲KDE或直方圖)。

sns.jointplot(
 x='Log GDP per capita',
 y='Life Ladder',
 data=data,
 kind='scatter' # or 'kde' or 'hex' )

Seaborn jointplot with scatter, bivariate kde, and hexbin in the center graph and marginal distribut

散點圖

散點圖是一種可視化兩個變量的聯合密度分佈的方法。 咱們能夠經過添加色相來添加第三個變量,並經過添加size參數來可視化第四個變量。

sns.scatterplot(
 x='Log GDP per capita',
 y='Life Ladder',
 data=data[data['Year'] == 2018],
 hue='Continent',
 size='Gapminder Population' ) 

# both, hue and size are optional
sns.despine() # prettier layout

Log GDP per capita against Life Ladder, colors based on the continent and size on population

 

小提琴圖

小提琴圖是箱形圖和籽粒密度估計值的組合。 它起着箱形圖的做用。 它顯示了跨類別變量的定量數據分佈,以即可以比較那些分佈。

sns.set(
 rc={'figure.figsize':(18,6)},
 style="white" ) 
sns.violinplot(
 x='Continent',
 y='Life Ladder',
 hue='Mean Log GDP per capita',
 data=data
 ) 
sns.despine()

 

Violin plot where we plot continents against Life Ladder, we use the Mean Log GDP per capita to grou

 

配對圖

Seaborn對圖在一個大網格中繪製了兩個變量散點圖的全部組合。 我一般感受這有點信息過載,可是它能夠幫助發現模式。

sns.set(
 style="white",
 palette="muted",
 color_codes=True
 ) 
sns.pairplot(
 data[data.Year == 2018][[ 'Life Ladder','Log GDP per capita', 'Social support','Healthy life expectancy at birth', 'Freedom to make life choices','Generosity', 'Perceptions of corruption', 'Positive affect', 'Negative affect','Confidence in national government', 'Mean Log GDP per capita' ]].dropna(),
 hue='Mean Log GDP per capita'
 )

Seaborn scatterplot grid where all selected variables a scattered against every other variable in th

 

FacetGrid

對我而言,Seaborn的FacetGrid是使用Seaborn的最使人信服的論點之一,由於它使建立多圖變得垂手可得。 經過對圖,咱們已經看到了FacetGrid的示例。 FacetGrid容許建立按變量分段的多個圖表。 例如,行能夠是一個變量(人均GDP類別),列能夠是另外一個變量(大陸)。

它確實比我我的須要更多的自定義(即便用matplotlib),但這仍然很吸引人。

FacetGrid —折線圖

g = sns.FacetGrid(
 data.groupby(['Mean Log GDP per capita','Year','Continent'])['Life Ladder'].mean().reset_index(),
 row='Mean Log GDP per capita',
 col='Continent',
 margin_titles=True ) 
g = (g.map(plt.plot, 'Year','Life Ladder'))

 

Life Ladder on the Y-axis, Year on the X-axis. The grid's columns are the continent, and the grid's rows are the different levels of Mean Log GDP per capita. Overall things seem to be getting better for the countries with a Low Mean Log GDP per Capita in North America and the countries with a Medium or High Mean Log GDP per Capita in Europe

FacetGrid —直方圖

g = sns.FacetGrid(data, col="Continent", col_wrap=3,height=4) 
g = (g.map(plt.hist, "Life Ladder",bins=np.arange(2,9,0.5)))

FacetGrid with a histogram of LifeLadder by continent

 

FacetGrid —帶註釋的KDE圖

也能夠向網格中的每一個圖表添加構面特定的符號。 在下面的示例中,咱們添加平均值和標準誤差,並在該平均值處繪製一條垂直線(下面的代碼)。

 

Life Ladder kernel density estimation based on the continent, annotated with a mean and standard deviation

def vertical_mean_line(x, **kwargs):
    plt.axvline(x.mean(), linestyle ="--", 
                color = kwargs.get("color", "r"))
    txkw = dict(size=15, color = kwargs.get("color", "r"))

    label_x_pos_adjustment = 0.08 # this needs customization based on your data
    label_y_pos_adjustment = 5 # this needs customization based on your data
    if x.mean() < 6: # this needs customization based on your data
        tx = "mean: {:.2f}\n(std: {:.2f})".format(x.mean(),x.std())
        plt.text(x.mean() + label_x_pos_adjustment, label_y_pos_adjustment, tx, **txkw)
    else:
        tx = "mean: {:.2f}\n  (std: {:.2f})".format(x.mean(),x.std())
        plt.text(x.mean() -1.4, label_y_pos_adjustment, tx, **txkw)

_ = data.groupby(['Continent','Year'])['Life Ladder'].mean().reset_index()

g = sns.FacetGrid(_, col="Continent", height=4, aspect=0.9, col_wrap=3, margin_titles=True)
g.map(sns.kdeplot, "Life Ladder", shade=True, color='royalblue')
g.map(vertical_mean_line, "Life Ladder")

FacetGrid —熱圖

我最喜歡的繪圖類型之一是熱圖FacetGrid,即網格每一個面中的熱圖。 這種類型的繪圖對於在一個繪圖中可視化四個維度和一個度量頗有用。 該代碼有點麻煩,但能夠根據須要快速進行調整。 值得注意的是,這種圖表須要相對大量的數據或適當的細分,由於它不能很好地處理缺失值。

 

Facet heatmap, visualizing on the outer rows a year range, outer columns the GDP per Capita, on the inner rows the level of perceived corruption and the inner columns the continents. We see that happiness increases towards the top right (i.e., high GDP per Capita and low perceived corruption). The effect of time is not definite, and some continents (Europe and North America) seem to be happier than others (Africa).

def draw_heatmap(data,inner_row, inner_col, outer_row, outer_col, values, vmin,vmax):
    sns.set(font_scale=1)
    fg = sns.FacetGrid(
        data, 
        row=outer_row,
        col=outer_col, 
        margin_titles=True
    )

    position = left, bottom, width, height = 1.4, .2, .1, .6
    cbar_ax = fg.fig.add_axes(position) 

    fg.map_dataframe(
        draw_heatmap_facet, 
        x_col=inner_col,
        y_col=inner_row, 
        values=values, 
        cbar_ax=cbar_ax,
        vmin=vmin, 
        vmax=vmax
    )

    fg.fig.subplots_adjust(right=1.3)  
    plt.show()

def draw_heatmap_facet(*args, **kwargs):
    data = kwargs.pop('data')
    x_col = kwargs.pop('x_col')
    y_col = kwargs.pop('y_col')
    values = kwargs.pop('values')
    d = data.pivot(index=y_col, columns=x_col, values=values)
    annot = round(d,4).values
    cmap = sns.color_palette("Blues",30) + sns.color_palette("Blues",30)[0::2]
    #cmap = sns.color_palette("Blues",30)
    sns.heatmap(
        d, 
        **kwargs,
        annot=annot, 
        center=0, 
        cmap=cmap, 
        linewidth=.5
    )

# Data preparation
_ = data.copy()
_['Year'] = pd.cut(_['Year'],bins=[2006,2008,2012,2018])

_['GDP per Capita'] = _.groupby(['Continent','Year'])['Log GDP per capita'].transform(
    pd.qcut,
    q=3,
    labels=(['Low','Medium','High'])
).fillna('Low')

_['Corruption'] = _.groupby(['Continent','GDP per Capita'])['Perceptions of corruption'].transform(
    pd.qcut,
    q=3,
    labels=(['Low','Medium','High'])
)

_ = _[_['Continent'] != 'Oceania'].groupby(['Year','Continent','GDP per Capita','Corruption'])['Life Ladder'].mean().reset_index()
_['Life Ladder'] = _['Life Ladder'].fillna(-10)

draw_heatmap(
    data=_,
    outer_row='Corruption',
    outer_col='GDP per Capita',
    inner_row='Year',
    inner_col='Continent',
    values='Life Ladder',
    vmin=3,
    vmax=8,
)

 


很棒:使用plotly建立出色的交互式圖

Photo by Chris Leipelt on Unsplash

 

最後,再也不須要Matplotlib! Plotly具備三個重要功能:

· 懸停:將鼠標懸停在圖表上時,將彈出註釋

· 交互性:無需任何其餘設置便可使圖表互動(例如,穿越時空的旅程)

· 漂亮的地理空間圖:Plotly具備一些內置的基本地圖繪製功能,可是另外,可使用mapbox集成來生成驚人的圖表。

散點圖

咱們經過運行fig = x。(PARAMS)而後調用fig.show()來調用繪圖:

fig = px.scatter(
    data_frame=data[data['Year'] == 2018], 
    x="Log GDP per capita", 
    y="Life Ladder", 
    size="Gapminder Population", 
    color="Continent",
    hover_name="Country name",
    size_max=60
)
fig.show()

 

Plotly scatter plot, plotting Log GDP per capita against Life Ladder, where color indicates continent and size of the marker the population

散點圖-漫步時光

fig = px.scatter(
    data_frame=data, 
    x="Log GDP per capita", 
    y="Life Ladder", 
    animation_frame="Year", 
    animation_group="Country name",
    size="Gapminder Population", 
    color="Continent", 
    hover_name="Country name", 
    facet_col="Continent",
    size_max=45,
    category_orders={'Year':list(range(2007,2019))}     
)
fig.show()

Visualization of how the plotted data changes over the years

並行類別-一種可視化類別的有趣方式

def q_bin_in_3(col):
    return pd.qcut(
        col,
        q=3,
        labels=['Low','Medium','High']
    )
_ = data.copy()
_['Social support'] = _.groupby('Year')['Social support'].transform(q_bin_in_3)
_['Life Expectancy'] = _.groupby('Year')['Healthy life expectancy at birth'].transform(q_bin_in_3)
_['Generosity'] = _.groupby('Year')['Generosity'].transform(q_bin_in_3)
_['Perceptions of corruption'] = _.groupby('Year')['Perceptions of corruption'].transform(q_bin_in_3)
_ = _.groupby(['Social support','Life Expectancy','Generosity','Perceptions of corruption'])['Life Ladder'].mean().reset_index()
fig = px.parallel_categories(_, color="Life Ladder", color_continuous_scale=px.colors.sequential.Inferno)
fig.show()

Seems like not all countries with high life expectations are happy!

 

條形圖—交互式過濾器的示例

fig = px.bar(
    data, 
    x="Continent", 
    y="Gapminder Population", 
    color="Mean Log GDP per capita", 
    barmode="stack", 
    facet_col="Year",
    category_orders={"Year": range(2007,2019)},
    hover_name='Country name',
    hover_data=[
        "Mean Log GDP per capita",
        "Gapminder Population",
        "Life Ladder"
    ]
)
fig.show()

 

Filtering a bar chart is easy. Not surprisingly, South Korea is among the wealthy countries in Asia.

Choropleth plot-幸福如何隨着時間而變化

fig = px.choropleth(
    data, 
    locations="ISO3", 
    color="Life Ladder", 
    hover_name="Country name", 
    animation_frame="Year")
fig.show()

 

Map visualization of how happiness evolves over the years. Syria and Afghanistan are at the very end of the Life Ladder range (unsurprisingly)

 


 

摘要和結束語

今天就這樣。 在本文中,您學習瞭如何成爲真正的Python可視化忍者。 您瞭解瞭如何在快速探索方面提升效率,以及在再次召開該死的董事會會議時如何建立更精美的圖表。 您學習瞭如何建立交互式地圖,這在繪製地理空間數據時特別有用。

 

(本文翻譯自Fabian Bosler的文章《Learn how to create beautiful and insightful charts with Python — the Quick, the Pretty, and the Awesome》 參考https://towardsdatascience.com/plotting-with-python-c2561b8c0f1f)

相關文章
相關標籤/搜索