1. 程式人生 > >機器學習-資料視覺化

機器學習-資料視覺化

現在每天產生的資料都是海量的,這些資料中既有高質量的也有很多垃圾,如何從這些海量的資料中洞察出這些資料的內在聯絡是我們機器學習的核心內容。如果光把資料丟在大家的面前,咱們肯定是無感的,無法獲取這些資料的意義。為了能夠更加直觀的瞭解這些資料的一些特徵,例如資料的分佈情況,資料的趨勢和走勢,資料之間的對比等等。這些特性可以很好的幫助我們理解一些資料的內在特性,從而對我們的特徵工程也有很大的輔助功能。還有最大的一個功能就是幫助咱們做很多看起來很牛逼影象,然後在報告上面裝B(大家都懂的,噓噓噓噓)。在資料科學的領域中,比較底層的資料視覺化元件事matplotlib. 但是鑑於上一節咱們已經說過pandas,pandas的視覺化介面也都是基於matplotlib的,但是pandas的更加抽象,所以運用起來也更加簡單一點。另外我也會簡單的介紹一款專門用於資料視覺化的元件叫做seaborn,它也是基於matplotlib的,但是seaborn也更加抽象,level也更加高,在視覺化方面提供的介面也更加簡單豐富。具體要用哪一個都一樣,大家隨便選擇,只要大家能在PPT或者報告中能成功在老闆面前把B裝起來,咱們就成功了,不管黑貓白貓,能抓住老鼠的就是好貓。哈哈,那咱們就開始咱們的表演吧。

  • categorical data type plot (univarate bar chart)

首先咱們先要了解category data是什麼,category data通常也分兩種:nominal category和ordinal category。nominal category通常是一些名詞,然後對於這些category的順序並不care,例如省份,國家,品牌等等(地域黑除外,哈哈);ordinal category通常是一些對於順序很敏感的變數,然後對於趨勢和分佈比較重要的資料,例如:分數,月份,年份,人口,消費等等啦。對於category data通常的視覺化操作都是bar chart 或者 pie chart.下面的主要以bar chart作為例子來解釋。本文主要是講述資料的視覺化,預設咱們已經載入的資料哈,具體載入資料的過程,下面的程式碼就不展示了。看下面的bar chart例項,然後我來解釋細節

reviews.points.value_counts().plot.bar()#sorting value from max to min(default)
reviews.points.value_counts().sort_index().plot.bar()#sorting index from min to max (can see the trend)

由於value_counts()返回的是一個series,並且返回的series的排序是按照這個series的value值從大到小的順序,所以plot的結果就是隻有一個變數,就是這個series的index,那麼這個變數對應的值就是這個series的value值。第一句程式碼的影象結果如下:

 

從上圖可以看出,上圖的變數是亂序的,縱座標(value)是按照從大到小的順序的。 上面的第二句程式碼多了一句sort_index(), 直譯過來就是將原來series的index 排序了,那麼新的series的index是按照從小到大的順序排列的。它的結果如下:

 

 從上圖可以很清晰的看出資料的分佈情況,第二幅圖也能給我們更加重要的資料資訊。

補充:對於ordinal category的資料,咱們還有一種常用的繪圖方式,那就是hist()。hist()能自動將series中的index進行排序,然後分成N個bins,每個bins 對應的縱座標則是這個bin相對應的frequency(即出現的次數)。例如下面的程式碼和圖片

reviews.points.plot.hist()

 

 從上面的程式碼和圖片可以看出,hist()函式不需要將現將points進行value_counts進行計算,它可以直接自動將series中的value按照順序分成N個bins,然後自動計算在每個bin中的數量。從上面的程式碼可以看出,bar()是講series中的index作為變數,而hist()是將series中的value作為變數,而frequency(即出現的次數)作為y. 這一點在初學者中經常弄混淆,甚至認為兩者是一樣的。其實兩者是有本質區別的,bar()是從series中一條一條的取資料,然後分別將index和value作為x,y進行繪製;而hist()則是一條一條的在series中取資料,只將series中的value作為x, 然後一直count每一個x。這兩種plot都是統計series中的value出現的次數,另外,無論hist()還是bar(),series的value必須是numerical,不能是categorical。

有的時候,另外一種圖也能很好的反映index和value之間的關係,那就是line chart。這種圖片也能非常好的反映資料的趨勢,所以一般也是用在ordinal的category中。如下

reviews.points.value_counts().sort_index().plot.line()

 

  •  Biavariate

在很多情況下,咱們會遇到要展示2個自變數的圖片。例如經緯度,bmi等等。通常這種情況下,這種圖都是反映的是出現的頻率,熱度等。通常展現兩個自變數的圖有scatter,hexbin.好了,下面咱們就直接上程式碼和結果給大家解釋一下

reviews[reviews.price<100].sample(100).plot.scatter(x='price',y='points')

 

 上面就是scatter圖的程式碼和結果,咱們可以啃方便的看出資料的分佈情況,不同於bar chart和histogram 它們都是展現一個維度的資料分佈情況, scatter是展示的2個維度的資料分佈情況。但是他有個致命的弱點,就是資料特別多並且它們很多的值都一樣的時候,它們是覆蓋在一起的,咱們就無法用眼睛直觀的準確的分辨出它們的分佈情況了。scatter適合那些資料不是特別多,並且重複資料很少的情況。那麼咱們怎麼解決這些問題呢?答案就是hexbin圖啦,前人已經幫咱們把坑都填好啦,哈哈,下面咱們看看hexbin是如何展現2個變數的分佈情況吧

#another plot method - Hex plot could perfectly deal with the scatter plot's drawbacks. Hex aggregatepoints in
#a hexagons, and the colors of the hexagons represent the values within them, which clearly conveys the meaningful
#results and view to us, such as: where does the examples cluster. in this case, it clusters around 87.5points and around 20 dollars
reviews[reviews.price<100].plot.hexbin(x='price',y='points',gridsize=15)

 

 上面的的註釋已經講得很清楚啦,hexbin圖中,顏色越深,出現的次數就越多。這樣咱們就不怕資料重疊的問題啦,非常直觀的就可以看出資料的分佈情況。綜上所述,當然啦,對於bivariate的資料視覺化肯定還有很多其他的API,不可能全在這講完,對於一名合格的程式設計師,咱們最重要的品質就是看文件的能力,具體咱們看,你們直接去pandas的官網看哈。總之對於資料量不大,重複資料不多的情況,咱們可以選擇scatter,對於資料量很大,並且很多重複資料的時候,就選hexbin,可以更加簡單的看到資料的分佈情況。

  • Subplotting

大家很多時候一定遇到過在同一個畫布上面同時畫出好幾個圖片的需求,可能用於對比,可能用於展示更加豐富的資訊。這種時候,咱們就想起了subplot了。下面先通過一個簡單的例項展示一個最簡單的subplot

fig,axarr = plt.subplots(2,2,figsize=(12,8))
first_150_reviews['points'].value_counts().sort_index().plot.bar(ax=axarr[0][0])
first_150_reviews['price'].value_counts().plot.hist(ax=axarr[0][1])
first_150_reviews['variety'].value_counts().head(20).plot.bar(ax=axarr[1][0])
first_150_reviews['province'].value_counts().head(20).plot.bar(ax=axarr[1][1])

 

 

上面的程式碼展示了一個subplot的最簡單的方式,首先第一個引數是(2,2)代表著是有幾個subplot,第二個引數figsize代表著整個畫布的大小,所以第一行程式碼是初始化一個畫布,並且設定一些畫布的初始值。後面的四行程式碼則是繪圖的過程,每一行的引數ax代表著座標系,ax後面的index分別對應著subplot的row和column,例如ax[0][1]代表著第一行第二列。所以大家看看subplot是不是可以展現出更加豐富的內容呢。當然啦,每一個subplot ax[row][column] 也可以有一些個性化的設定,這個咱們後面慢慢說,上面只是一個最最最最簡單的繪畫subplot的一種方法。

  • 圖片個性化

當然啦,既然是圖嘛,免不了很多時候咱們想著要美化一下下嘛,畢竟經常要給別人展示的,門面還是很重要的。所以咱們經常需要將圖形進行一些個性化設定,例如圖形的顏色,字型大小,圖形標題,圖形大小等等一系列的特性。首先咱們看一下圖形的大小哈,咱們可以通過figsize的引數進行設定,如下

reviews.points.value_counts().sort_index().plot.bar(figsize=(20,6))

可以通過設定tuple裡面的資料對圖片的大小進行設定。接下來咱們可以看看對圖形顏色的設定

#customerize the color of the bars
reviews.points.value_counts().sort_index().plot.bar(figsize = (12,6), color = 'green')

上面程式碼就是將bar chart中的bar設定成綠色。接下來咱們瞧一瞧座標系上字型大小的設定

#coustomerize font
reviews.points.value_counts().sort_index().plot.bar(figsize = (12,6), color = 'red', fontsize = 20)

上面程式碼的fontsize可以設定座標系字型的大小。最後咱們來看看圖形標題的設定

reviews.points.value_counts().sort_index().plot.bar(
        figsize=(12,6),
        color='green', 
        fontsize = 16, 
        title='Rankings Given By Wine Magazine'
        )

上面的程式碼可以給這個圖片設定一個標題叫做“Rankings Given By Wine Magazine”,這裡咱們有個小細節需要注意一下就是標題的字型大小也可以設定,但是在pandas plot的框架上面沒法設定,必須去更加底層的matplotlib去設定圖片標題的字型大小,程式碼如下

import matplotlib.pyplot as plt
title_customerise_plot = reviews.points.value_counts().sort_index().plot.bar(
        figsize = (12,6),
        color = 'green',
        fontsize = 16
        )
title_customerise_plot.set_title("Ranking Given By Wine Magazine",fontsize = 20)

咱們必須通過matplotlib.pyplot中的set_title()的方法來設定圖片標題的大小,而無法直接在pandas中設定它。上面的結果如下

 

  • Seaborn 簡介

資料的視覺化呢,除了pandas提供一些簡單易用的API之外,還有一個專門用於資料視覺化的框架,那就是seaborn。它也是基於matplotlib的,但是用起來比matplotlib簡單,功能也比pandas的繪圖功能更加豐富,畢竟seaborn人家是專業的嘛,哈哈。關於seaborn我也就在這裡簡單的演示一下bar chart,line chart,scatter plot, kde 等等一些簡單的應用哈。還是那句話,關於繪圖有無數個API,需要大家安靜下來去seaborn的documentation細細品味,嘻嘻. 下面的程式碼分別展示了bar chart,line chart在seaborn中的應用

import matplotlib.pyplot as plt
import seaborn as sns
#data flight_delays = pd.read_csv("C:\\Users\\tangx\\OneDrive\\Desktop\\DATA\\flight_delays.csv",index_col='Month',parse_dates = True) spotify_df = pd.read_csv("C:\\Users\\tangx\\OneDrive\\Desktop\\DATA\\spotify.csv",index_col="Date",parse_dates = True) #plotting
sns.lineplot(data=spotify_df['Despacito'],label = "Despacito") sns.barplot(x=flight_delays.index,y= flight_delays.NK)

從上面的程式碼可以看出,series都是作為引數(資料來源)傳遞給函式的,而不像在pandas繪圖那樣,將繪圖的方法作為series的方法。seaborn中也可以傳遞很多的引數來個性化圖形,例如上面的label。大家有興趣可以自己去看看哈。上面的結果如下

 

 咱們可以從上圖看出,對於資料來源咱們既可以直接把series傳給data引數,也可以分別將橫座標縱座標的值分別傳遞給x,y。而且如果你選擇第二種它還能自動給橫座標和縱座標命名,還挺智慧。seaborn還有更加牛的功能,看看下面兩個個scatter plot,你去瞧一瞧那些牛逼的功能

sns.scatterplot(x=insurance.bmi,y=insurance.charges)
sns.scatterplot(x=insurance.bmi,y=insurance.charges,hue=insurance.smoker)

 

通過上面咱們可以看出,雖然是同一個scatter,但是它還可以通過hue這個引數,將資料根據一定的條件(例如上面的是不是吸菸者)來分開,從而可以幫助咱們更加深刻的理解資料。如果看到這裡你們就覺得seaborn牛逼,那麼只能說你們還是太年輕,哈哈,它還是有大招的,那就是它還可以話擬合線,具體是什麼呢?看看下面的程式碼

sns.regplot(x=insurance['bmi'], y=insurance['charges'])
sns.lmplot(x='bmi',y='charges',hue='smoker',data=insurance)

 

 

 regplot相當於直接畫一條regression line,而lmplot則能夠根據不同條件下的子集畫出不同的regression line,這對於咱們分析資料走勢,和一些資料的subset的趨勢都有很大的幫助。最後咱們來看看seaborn的另外一個大殺器,那就是KDE plot, 那麼很大同學可能會有疑問了,什麼是kde呢? kde其實是kernel density estimation的簡稱,它其實是一種概率分佈的技術,像是一個小window從咱們的圖形從左到右的走一遍,然後把那些偏離很大的值(outliers)和那些突然變化很大的值(in-between values)刪除和變成一條更加順滑的線,並且將結果轉成概率。它既可以用於univariate也可以用於bivariate。注意:kde的y值(函式的變數)是概率(對於2d資料來說,是通過顏色的深淺來判斷的),而不是frequency!!!!!!!。那咱們現在來看看kde的簡單應用

first_150_reviews[first_150_reviews['price']<200]['price'].value_counts().sort_index().plot.line()
sns.kdeplot(first_150_reviews.query('price<200').price)

 

 咱們看看上面的兩個圖片,右邊的圖片應用了kde,是不是像給第一幅圖用了海飛絲一樣,瞬間順滑了很多,也更加直觀的展示了資料的分佈和趨勢。下面咱們來看看kde用於bivariate的情況

first_150_reviews[first_150_reviews.price<200][['price','points']].dropna().sample(5000).sort_index().plot.scatter(x='price',y='points')
sns.kdeplot(first_150_reviews[first_150_reviews.price<200][['price','points']].dropna().sample(5000))

 

 第一個圖片是一般的scatter,第二幅圖是kde,越靠近圖形中間的位置,出現的概率越大。 至於哪一個好,那一牛逼,你們自己心裡有一把尺,不用我說了吧。哈哈

  •  box plot and violin plot

現在介紹最後一種常見的圖形,其實是兩種圖,但是他們本質一樣,分別是box plot和violin plot。咱們先看建立它們的程式碼和執行結果然後在分析這兩種圖形

df = first_150_reviews[first_150_reviews.variety.isin(first_150_reviews.variety.value_counts().head(5).index)]
sns.boxplot(
        x="variety",
        y = "points",
        data = df
        )


#violin plot
#violin plot cleverly replace the box in the boxplot with a kde for the data, it is more visually enticing
sns.violinplot(
        x='variety',
        y='points',
        data = df)

 

看到上面的五顏六色的圖形,是不是心裡一萬隻曹尼瑪,哈哈,心想什麼玩意兒。待我慢慢來分析,首先看看左邊的圖形box plot,最下面的一條線是每一個variaty相對應points的最小值,中間box有三條橫線,分別對應著該variaty下面points的25%,median,75%的值,然後box上面的最頂上的一個橫線代表著該variaty下points的最大值。右邊的violin plot其實就是對box plot的kde,更能反映出資料的分佈情況。他們之間的對比可以看下面這個經典的圖

 

 

總結:這節的資料視覺化的內容很雜,其實如果想把資料視覺化玩的轉,最重要的的捷徑就是理解資料。關於視覺化的API我個人認為是最簡單的API,而且不多,建議大家都能理解透徹。雖然視覺化的內容不難,但是有很多圖形很像,但是要知道他們的不同,例如bar chart 和histogram,box plot和violin plot 等等,雖然看著相似,但其實是不同的。就像開頭說的,這裡主要是寫的是pandas和seaborn的視覺化的方法,實際中還經常需要用到底層一點的matplotlib,這裡我就不細說了,如果上面的內容能消化,以大家的能力看matplotlib的API 應該也不是問題的