0. 如何入門數(shù)據(jù)分析

關(guān)注沙漠之鷹的同學(xué)一定看過沙漠君寫得很多篇數(shù)據(jù)分析文章,比如分析房價,車價,預(yù)測機動車搖號這些話題。其實文章中所有的分析都使用了Python和它非常強大的數(shù)據(jù)分析庫Pandas。一些機器學(xué)習(xí)和預(yù)測的功能則用到了sklearn庫。掌握了這些工具,就能應(yīng)對絕大多數(shù)的分析需求。

紙上得來終覺淺,即使你看了很多書和代碼,也未必比得上多接觸例子多敲一些代碼,三四個中等規(guī)模(約一兩百行代碼的)的案例就能讓你有整體的把握。至于數(shù)據(jù)采集,沙漠之鷹有開源的數(shù)據(jù)抓取工具Hawk,網(wǎng)上也有眾多如何獲取數(shù)據(jù)的教程,因此本文不再詳述。

系列文章分為三個部分:

  • 1) 查詢與統(tǒng)計

  • 2) 可視化和高級用法

  • 3) 分類和預(yù)測(估計會分為幾篇文章)

好了,廢話不多說,進(jìn)入正題。

1. 找到好的問題

好的問題其實比答案更重要。人認(rèn)識問題,分為四種級別:

  1. 我們知道自己知道的(房價在漲)

  2. 知道自己不知道的(可度量的信息,如房價平均漲幅)

  3. 不知道自己知道的(如證明搖號系統(tǒng)漏洞)

  4. 不知道自己不知道的(最有價值,蘊含著最大的機會)

沙漠君期待于尋找3-4層級的問題,可是多數(shù)情況只能在第1和第2檔上徘徊。當(dāng)你發(fā)現(xiàn)一個問題之后,還需要思考3個問題:

  • 我是否找到了一個值得解決的問題?

  • 我是否提出了一個足夠好的解決方案

  • 我真的想去解決這個問題嗎?

最后的動機往往反映了你能解決該問題的最大極限,很多人也許僅僅是完成任務(wù),因此有了一點成果便停滯不前,錯過了最大的金礦。數(shù)據(jù)的質(zhì)量比數(shù)量更重要,如果不知道什么樣的數(shù)據(jù)更重要,即使擁有更多的數(shù)據(jù)也只會造成嘔吐。數(shù)據(jù)分析需要專注,需要從紛繁的圖表和信息中找到問題核心。

通常來說,人們對變化的指標(biāo)更感興趣,因此比率和增長幅度比靜態(tài)的數(shù)據(jù)更有說服力。而變化又分長短期,不同維度得出的結(jié)論往往全然不同。相關(guān)性很好,因果性更佳。有了因果性,便有了改變未來的能力。

下圖展示了數(shù)據(jù)分析的一般流程(圖片來自網(wǎng)絡(luò)):

seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營銷培訓(xùn)

統(tǒng)計的三大核心:分組(map),聚合(reduce),排序(sort)。它們用的是如此普遍,因此MapReduce管道框架成了數(shù)據(jù)分析的標(biāo)準(zhǔn),也非常適合做多機并行化。分組和排序很好理解,聚合指的是對各組內(nèi)容做求和,分組等。

絕大部分?jǐn)?shù)據(jù)分析操作,都可以通過查詢,分組,聚合,排序四個元素進(jìn)行級聯(lián)組合進(jìn)行。因此掌握這四大天王,應(yīng)付一般的場景就都無問題了。 (這應(yīng)該是這篇文章最重要的一句話了)

2. 查詢和過濾

DataFrame是pandas的核心數(shù)據(jù)結(jié)構(gòu),可以理解為Excel里的二維矩陣,它更高級,能表達(dá)3維或更高維的數(shù)據(jù),支持多索引。在內(nèi)存中存取,效率極高,絕大多數(shù)操作都和DataFrame相關(guān)。維度為2的DataFrame,行(column)和列(row)的axis分別為0和1。可以針對某些列做索引(index),高維DataFrame是相當(dāng)少見的。

2.1 查詢

下面的表展示了Pandas對索引的介紹:

符號說明例子
[]列值索引df['房價'] ,df[['房價','車價']]
loc行值索引df.loc[0], df['2013':'2015']
iloc行號索引df.iloc[0], df.iloc[2:10]
ix行索引df.ix[0], df.ix[2:10]

時間也是比較重要的index,比較好用的是Timestamp,接受2016-12-24這種字符串,字符串到時間轉(zhuǎn)換代碼如下:

weather.index= weather[u'日期'].map(lambda x:Timestamp(x))

Pandas的索引功能非常強大,補充如下:

  • 1) loc也能支持先行后列的查詢:df.loc['20130101':'20130103' , ['A','B']],類似的如iloc

  • 2) 個人感覺ix的有些冗余,和ixiloc類似

所有索引都支持字符串和數(shù)組,以及切片(slice)用于指定范圍,索引還能傳遞一個bool類型的lambda表達(dá)式,或返回和其shape一致的bool數(shù)組
這種用法可以用在過濾上,這非常重要,我們再給幾個例子:

2.2 過濾

過濾有兩方面需求:找出特定數(shù)據(jù)進(jìn)行針對性分析,或

  • 針對特定數(shù)據(jù)做分析,

  • 過濾異常值。

異常值非常重要,應(yīng)該細(xì)致分析導(dǎo)致它們產(chǎn)生的原因,如果真是異常值,應(yīng)該提早過濾,否則做聚合時會嚴(yán)重影響結(jié)果,如天價的房價。

先討論按行過濾:非空過濾,過濾掉col列為空的內(nèi)容:

df=df[!data.col.isnull()]

字符串過濾:

db[db.city.str.contains(u'市')]

若需要對df對某個鍵去重:

qq['id'].unique()

isin能判斷單元格中的值是否在給定的數(shù)組內(nèi),若希望對多個列做過濾,Pandas提供了現(xiàn)成的方法df.filter,還支持正則。還能進(jìn)行邏輯操作,實現(xiàn)更復(fù)雜的需求。

2.3 遍歷

有了索引和列操作,為何還要有遍歷?因為遍歷更加靈活,當(dāng)然性能相對會差一些:

函數(shù)遍歷目標(biāo)lambda參數(shù)說明
map一列的cellcell最為常見
apply列/行列或行的Seriesaxis:不填寫cell,1:行,2:列
applymapcellcellelement-wise最為靈活
iterrows行遍歷提供行號見備注
iteritems列遍歷提供列名見備注
itertuples行遍歷提供index見備注

map, apply,applymap是只返回單元格或行列本身的,參數(shù)都是lambda,本節(jié)假設(shè)讀者對python的lambda表達(dá)式有足夠的了解。

但這樣不能實現(xiàn)如“奇數(shù)偶數(shù)行做分別作不同處理的需求,則這三個函數(shù)就無能為力。因此就有后面iterrows等三個函數(shù)。如iterrows,它會將行號和行迭代出來,從而方便自定義邏輯,示例如下:

for i,row in data.iterrows():
    pass

2.4 求值和合并

一張表可能很難包含所有的信息,因此需要計算新值(求值)或join其他表(合并),但Pandas本身的Join并不好用,經(jīng)常出錯。

如果某個屬性可以通過計算獲得,可對各個列當(dāng)做變量來處理,由于內(nèi)部使用了C++和numpy加速,效率遠(yuǎn)比for循環(huán)更高,下面是處理房價的一個例子:總價/單價,并做小數(shù)點截?。?/p>

table['面積']= np.round(table['總價']*10000/table['單價'])

numpy提供了絕大多數(shù)常見的函數(shù)算子,能滿足大部分需求。下面是合并:

  • 橫向合并(需保證行數(shù)一致)- 橫向合并 df = pd.concat([data_train, dummies_Cabin])

  • 刪除列 df.drop(['Pclass', 'Name', 'Sex')]

  • 縱向合并(join操作)

    data.merge(right=prop_rates, how='inner',left_on='Property_Area',right_index=True, sort=False)

如果不加參數(shù),則可以自動通過列名合并。join的參數(shù)比較復(fù)雜,建議直接參考Pandas官方文檔。

3. 分組,排序,聚合

排序,分組和聚合的組合都有無數(shù)種,這在技術(shù)層面不難。但如果要寫報告,避免大而全,因為客戶的注意力很容易浪費在沒有意義的圖表上。將客戶真正關(guān)心的搞出來,行業(yè)背景分析,用戶畫像,競品監(jiān)測,銷售行為分析...如果是寫通俗文章,多問幾個人,你想要知道什么。

由于分組是基礎(chǔ),我們先介紹分組:

3.1 分組

分組就是按照一個或多個鍵,將數(shù)據(jù)分為幾個組的過程。你可以直接傳列名做分組,df.groupby('column_name')

也可以傳遞相同行數(shù)的Series甚至DataFrame。下面的例子是按日期里的年做分組:

df2.groupby(df2.日期.map(lambda x:x.year))

Pandas也能支持傳遞多個列的數(shù)組,除了切片以外,能在索引上使用的基本都能在group,sort上使用,一致性的API上手非常容易。

值得注意的是,由于時間索引分組比較困難,例如每五個月一組,可以用針對TimeStamp特定優(yōu)化的方案,如resample:

下面計算了北京按年平均的AQI:

db[db.city==u'北京'][u'平均值'].resample('12M').aqi.mean()

3.2 排序

Pandas的排序非常之快,大部分操作都能在瞬間完成。排序分為兩類:

對一般數(shù)據(jù)排序

一般排序,直接用sort即可,傳遞lambda,列名或多個列,或長度一致的Series,這與groupby等其他API一致,此處從略。

可指定ascending=True|False來指定升序,降序。

對分組后數(shù)據(jù)排序

groupby之后的數(shù)據(jù),和一般的DataFrame不同,而像個字典(dict)。對鍵排序,需使用sort_index,值排序,需使用sort_values。

3.3 聚合

聚合可將分組后的數(shù)據(jù)按需求重新打平。如求每個分組的最大值(max),最小值(min),或數(shù)量等,例如:

df2.groupby(df2.日期.map(lambda x:x.year)).size()

我們來寫幾個例子大家說說是什么意思:

car.groupby(car.年月.map(lambda x:x.month)).銷量.sum().plot(kind='bar',title='汽車市場月度銷量匯總')

將汽車數(shù)據(jù)按照月份分組,按銷量求和。然后繪制直方圖:

Pandas支持直接將聚合結(jié)果繪圖輸出(雖然丑但是方便?。乱还?jié)我們將詳細(xì)介紹它的使用細(xì)節(jié)。

這條語句統(tǒng)計了廣西省東風(fēng)MPV的各車型總體銷量情況,并按數(shù)量降序:

df[(df.省=='廣西') & (df.車型分類=='MPV') & (df.品牌=='東風(fēng)')].groupby('車型').size().sort_values(ascending=False)

3.4 數(shù)據(jù)透視表

如果我想一次性地針對多種分組方式實行多種聚合策略,有沒有更方便的API? 答案是數(shù)據(jù)透視表(pivot_table)。Excel也有該功能,異常強大,有了它,一般需求幾乎都能實現(xiàn)。

有篇文章講的非常詳細(xì),此處就不班門弄斧了,參考:

http://python.jobbole.com/81212/

下面是同時按Name rep manager分組,按價格分別以總價和數(shù)量聚合,并將空值填為0.

pd.pivot_table(df,index=["Name","Rep","Manager"],values=["Price"],aggfunc=[np.sum,len],fill_value=0)

pivot之后,生成的DataFrame是multiindex的,處理起來稍顯繁瑣,用xs可將某個子index的數(shù)據(jù)“提升”出來,例如:

df_pivot.xs(('12AM新坐標(biāo)',2011))

至于更復(fù)雜的訪問和采樣,可配合loc和PD.IndexSlice, 可自行查看官方文檔。

4. 總結(jié)

Pandas本身異常強大,功能非常繁雜,筆者僅僅掌握了其中非常小的一部分。但是對于一般的需求都能通過簡單的操作組合出來。API的一致性非常重要,Pandas(包括numpy等)都繼承了Python的優(yōu)良特性,因此只要能舉一反三,就能進(jìn)步神速。

文章不能太長,否則就沒人看得完了。不過相信我,掌握文中說的用法,基本上就足夠混口飯吃了。因為寫SQL的速度和靈活性是遠(yuǎn)遠(yuǎn)不及Pandas語法的。下一篇是數(shù)據(jù)可視化,我們來討論如何做可視化,還有對應(yīng)的Python庫。

有任何問題,歡迎交流。


作者:熱情的沙漠 
出處:http://www.cnblogs.com/buptzym/ 
本文版權(quán)歸作者和博客園共有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責(zé)任的權(quán)利。 

http://www.cnblogs.com/buptzym/p/7144122.html