如何七周成為數(shù)據(jù)分析師22:用pandas進行數(shù)據(jù)分析實戰(zhàn)
本文是《如何七周成為數(shù)據(jù)分析師》的第二十二篇教程,如果想要了解寫作初衷,可以先行閱讀七周指南。溫馨提示:如果您已經(jīng)熟悉Python,大可不必再看這篇文章,或只挑選部分。
大家學習Python,不練習怎么行?
這次依舊使用網(wǎng)絡(luò)抓取的數(shù)據(jù)分析師的招聘薪資作為練習數(shù)據(jù)。在早期我們已經(jīng)用它進行了Excel、BI可視化、SQL三方面的實戰(zhàn)訓練,想必大家已經(jīng)很熟悉了,我不再贅述。
主要內(nèi)容是進行數(shù)據(jù)讀取,數(shù)據(jù)概述,數(shù)據(jù)清洗和整理,分析和可視化。按照本教程,相信大家的Pandas會上到一個新臺階,遇到文中沒有提及的錯誤,通過搜索引擎解決吧。
首先載入我們的練習數(shù)據(jù)。
在pandas中,常用的載入函數(shù)是read_csv。除此之外還有read_excel和read_table,table可以讀取txt。若是服務器相關(guān)的部署,則還會用到read_sql,直接訪問數(shù)據(jù)庫,但它必須配合mysql相關(guān)包。
read_csv擁有諸多的參數(shù),encoding是最常用的參數(shù)之一,它用來讀取csv格式的編碼。這里使用了gb2312,該編碼常見于windows,如果報錯,可以嘗試utf-8。
sep參數(shù)是分割符,有些csv文件用逗號分割列,有些是分號,有些是\t,這些都需要具體設(shè)置。header參數(shù)為是否使用表頭作為列名,默認是。names參數(shù)可以為列設(shè)置額外的名字,比如csv中的表頭是中文,但是在pandas中最好轉(zhuǎn)換成英文。
上述是主要的參數(shù),其他參數(shù)有興趣可以學習。一般來說,csv的數(shù)據(jù)都是干凈的,excel文件則有合并單元格這種惡心的玩意,盡量避免。
現(xiàn)在有了數(shù)據(jù)df,首先對數(shù)據(jù)進行快速的瀏覽。
這里列舉出了數(shù)據(jù)集擁有的各類字段,一共有6876個,其中companyLabelList,businessZones,secondType,positionLables都存在為空的情況。公司id和職位id為數(shù)字,其他都是字符串。
因為數(shù)據(jù)集的數(shù)據(jù)比較多,如果我們只想瀏覽部分的話,可以使用head函數(shù),顯示頭部的數(shù)據(jù),默認5,也可以自由設(shè)置參數(shù),如果是尾部數(shù)據(jù)則是tail。
數(shù)據(jù)集中,最主要的臟數(shù)據(jù)是薪資這塊,后續(xù)我們要拆成單獨的兩列。
看一下是否有重復的數(shù)據(jù)。
unique函數(shù)可以返回唯一值,數(shù)據(jù)集中positionId是職位ID,值唯一。配合len函數(shù)計算出唯一值共有5031個,說明有多出來的重復值。
使用drop_duplicates清洗掉。
drop_duplicates函數(shù)通過subset參數(shù)選擇以哪個列為去重基準。keep參數(shù)則是保留方式,first是保留第一個,刪除后余重復值,last還是刪除前面,保留最后一個。duplicated函數(shù)功能類似,但它返回的是布爾值。
接下來加工salary薪資字段。目的是計算出薪資下限以及薪資上限。
薪資內(nèi)容沒有特殊的規(guī)律,既有小寫k,也有大小K,還有「k以上」這種蛋疼的用法,k以上只能上下限默認相同。
這里需要用到pandas中的apply。它可以針對DataFrame中的一行或者一行數(shù)據(jù)進行操作,允許使用自定義函數(shù)。
我們定義了個word_cut函數(shù),它查找「-」符號所在的位置,并且截取薪資范圍開頭至K之間的數(shù)字,也就是我們想要的薪資上限。apply將word_cut函數(shù)應用在salary列的所有行。
「k以上」這類臟數(shù)據(jù)怎么辦呢?find函數(shù)會返回-1,如果按照原來的方式截取,是word[:-2],不是我們想要的結(jié)果,所以需要加一個if判斷。
因為python大小寫敏感,我們用upper函數(shù)將k都轉(zhuǎn)換為K,然后以K作為截取。這里不建議用「以上」,因為有部分臟數(shù)據(jù)不包含這兩字。
將bottomSalary轉(zhuǎn)換為數(shù)字,如果轉(zhuǎn)換成功,說明所有的薪資數(shù)字都成功截取了。
薪資上限topSalary的思路也相近,只是變成截取后半部分。
在word_cout函數(shù)增加了新的參數(shù)用以判斷返回bottom還是top。apply中,參數(shù)是添加在函數(shù)后面,而不是里面的。這點需要注意。
接下來求解平均薪資。
數(shù)據(jù)類型轉(zhuǎn)換為數(shù)字,這里引入新的知識點,匿名函數(shù)lamba。很多時候我們并不需要復雜地使用def定義函數(shù),而用lamdba作為一次性函數(shù)。
lambda x: ******* ,前面的lambda x:理解為輸入,后面的星號區(qū)域則是針對輸入的x進行運算。案例中,因為同時對top和bottom求平均值,所以需要加上x.bottomSalary和x.topSalary。word_cut的apply是針對Series,現(xiàn)在則是DataFrame。
axis是apply中的參數(shù),axis=1表示將函數(shù)用在行,axis=1則是列。
這里的lambda可以用(df_duplicates.bottomSalary +?df_duplicates.topSalary)/2替代。
到此,數(shù)據(jù)清洗的部分完成。切選出我們想要的內(nèi)容進行后續(xù)分析(大家可以選擇更多數(shù)據(jù))。
先對數(shù)據(jù)進行幾個描述統(tǒng)計。
value_counts是計數(shù),統(tǒng)計所有非零元素的個數(shù),以降序的方式輸出Series。數(shù)據(jù)中可以看到北京招募的數(shù)據(jù)分析師一騎絕塵。
我們可以依次分析數(shù)據(jù)分析師的學歷要求,工作年限要求等。
針對數(shù)據(jù)分析師的薪資,我們用describe函數(shù)。
它能快速生成各類統(tǒng)計指標。數(shù)據(jù)分析師的薪資的平均數(shù)是17k,中位數(shù)是15k,兩者相差不大,最大薪資在75k,應該是數(shù)據(jù)科學家或者數(shù)據(jù)分析總監(jiān)檔位的水平。標準差在8.99k,有一定的波動性,大部分分析師薪資在17+—9k之間。
一般分類數(shù)據(jù)用value_counts,數(shù)值數(shù)據(jù)用describe,這是最常用的兩個統(tǒng)計函數(shù)。
說了這么多文字,還是不夠直觀,我們用圖表說話。
pandas自帶繪圖函數(shù),它是以matplotlib包為基礎(chǔ)封裝,所以兩者能夠結(jié)合使用。
%matplotlib inline是jupyter自帶的方式,允許圖表在cell中輸出。plt.style.use(‘ggplot’)使用R語言中的ggplot2配色作為繪圖風格,純粹為了好看。
用hist函數(shù)很方便的就繪制除出直方圖,比excel快多了。圖表列出了數(shù)據(jù)分析師薪資的分布,因為大部分薪資集中20k以下,為了更細的粒度。將直方圖的寬距繼續(xù)縮小。
數(shù)據(jù)分布呈雙峰狀,因為原始數(shù)據(jù)來源于招聘網(wǎng)站的爬取,薪資很容易集中在某個區(qū)間,不是真實薪資的反應(10~20k的區(qū)間,以本文的計算公式,只會粗暴地落在15k,而非均勻分布)。
數(shù)據(jù)分析的一大思想是細分維度,現(xiàn)在觀察不同城市、不同學歷對薪資的影響。箱線圖是最佳的觀測方式。
圖表的標簽出了問題,出現(xiàn)了白框,主要是圖表默認用英文字體,而這里的都是中文,導致了沖突。所以需要改用matplotlib。
首先加載字體管理包,設(shè)置一個載入中文字體的變量,不同系統(tǒng)的路徑不一樣。boxplot是我們調(diào)用的箱線圖函數(shù),column選擇箱線圖的數(shù)值,by是選擇分類變量,figsize是尺寸。
ax.get_xticklabels獲取坐標軸刻度,即無法正確顯示城市名的白框,利用set_fontpeoperties更改字體。于是獲得了我們想要的箱線圖。改變字體還有其他方法,大家可以網(wǎng)上搜索關(guān)鍵字「matplotlib 中文字體」,都有相應教程。
從圖上我們看到,北京的數(shù)據(jù)分析師薪資高于其他城市,尤其是中位數(shù)。上海和深圳稍次,廣州甚至不如杭州。
從學歷看,博士薪資遙遙領(lǐng)先,雖然在top區(qū)域不如本科和碩士,這點我們要后續(xù)分析。大專學歷稍有弱勢。
工作年限看,薪資的差距進一步拉大,畢業(yè)生和工作多年的不在一個梯度。雖然沒有其他行業(yè)的數(shù)據(jù)對比,但是可以確定,數(shù)據(jù)分析師的職場上升路線還是挺光明的。
到目前為止,我們了解了城市、年限和學歷對薪資的影響,但這些都是單一的變量,現(xiàn)在想知道北京和上海這兩座城市,學歷對薪資的影響。
在by傳遞多個值,箱線圖的刻度自動變成元組,也就達到了橫向?qū)Ρ鹊淖饔茫ㄟ@方法其實并不好,以后會講解其他方式)。這種方法并不適宜元素過多的場景。從圖上可以看到,不同學歷背景下,北京都是稍優(yōu)于上海的,北京愿意花費更多薪資吸引數(shù)據(jù)分析師,而在博士這個檔次,也是一個大幅度的跨越。我們不妨尋找其中的原因。
在pandas中,需要同時用到多個維度分析時,可以用groupby函數(shù)。它和SQL中的group by差不多,能將不同變量分組。
上圖是標準的用法,按city列,針對不同城市進行了分組。不過它并沒有返回分組后的結(jié)果,只返回了內(nèi)存地址。這時它只是一個對象,沒有進行任何的計算,現(xiàn)在調(diào)用groupby的count方法。
它返回的是不同城市的各列計數(shù)結(jié)果,因為沒有NaN,每列結(jié)果都是相等的?,F(xiàn)在它和value_counts等價。
換成mean,計算出了不同城市的平均薪資。因為mean方法只針對數(shù)值,而各列中只有avgSalary是數(shù)值,于是返回了這個唯一結(jié)果。
groupby可以傳遞一組列表,這時得到一組層次化的Series。按城市和學歷分組計算了平均薪資。
后面再調(diào)用unstack方法,進行行列轉(zhuǎn)置,這樣看的就更清楚了。在不同城市中,博士學歷最高的薪資在深圳,碩士學歷最高的薪資在杭州。北京綜合薪資最好。這個分析結(jié)論有沒有問題呢?不妨先看招聘人數(shù)。
這次換成count,我們在groupby后面加一個avgSalary,說明只統(tǒng)計avgSalary的計數(shù)結(jié)果,不用混入相同數(shù)據(jù)。圖上的結(jié)果很明確了,要求博士學歷的崗位只有6個,所謂的平均薪資,也只取決于公司開出的價碼,波動性很強,畢竟這只是招聘薪資,不代表真實的博士在職薪資。這也解釋了上面幾個圖表的異常。
groupby是不是和數(shù)據(jù)透視表比較像?pandas其實有專門的數(shù)據(jù)透視函數(shù),在另外一方面,groupby確實能完成不少透視工作。
接下來計算不同公司招聘的數(shù)據(jù)分析師數(shù)量,并且計算平均數(shù)。
這里使用了agg函數(shù),同時傳入count和mean方法,然后返回了不同公司的計數(shù)和平均值兩個結(jié)果。所以前文的mean,count,其實都省略了agg。agg除了系統(tǒng)自帶的幾個函數(shù),它也支持自定義函數(shù)。
上圖用lamba函數(shù),返回了不同公司中最高薪資和最低薪資的差值。agg是一個很方便的函數(shù),它能針對分組后的列數(shù)據(jù)進行豐富多彩的計算。但是在pandas的分組計算中,它也不是最靈活的函數(shù)。
現(xiàn)在我們有一個新的問題,我想計算出不同城市,招聘數(shù)據(jù)分析師需求前5的公司,應該如何處理?agg雖然能返回計數(shù)也能排序,但它返回的是所有結(jié)果,前五還需要手工計算。能不能直接返回前五結(jié)果?當然可以,這里再次請出apply。
自定義了函數(shù)topN,將傳入的數(shù)據(jù)計數(shù),并且從大到小返回前五的數(shù)據(jù)。然后以city聚合分組,因為求的是前5的公司,所以對companyShortName調(diào)用topN函數(shù)。
同樣的,如果我想知道不同城市,各職位招聘數(shù)前五,也能直接調(diào)用topN。
可以看到,雖說是數(shù)據(jù)分析師,其實有不少的開發(fā)工程師,數(shù)據(jù)產(chǎn)品經(jīng)理等。這是抓取下來數(shù)據(jù)的缺點,它反應的是不止是數(shù)據(jù)分析師,而是數(shù)據(jù)領(lǐng)域。不同城市的需求不一樣,北京的數(shù)據(jù)產(chǎn)品經(jīng)理看上去要比上海高。
agg和apply是不同的,雖然某些方法相近,比如求sum,count等,但是apply支持更細的粒度,它能按組進行復雜運算,將數(shù)據(jù)拆分合并,而agg則必須固定為列。
運用group by,我們已經(jīng)能隨意組合不同維度。接下來配合group by作圖。
多重聚合在作圖上面沒有太大差異,行列數(shù)據(jù)轉(zhuǎn)置不要混淆即可。
上述的圖例我們都是用pandas封裝過的方法作圖,如果要進行更自由的可視化,直接調(diào)用matplotlib的函數(shù)會比較好,它和pandas及numpy是兼容的。plt已經(jīng)在上文中調(diào)用并且命名
上圖將上海和北京的薪資數(shù)據(jù)以直方圖的形式進行對比。因為北京和上海的分析師人數(shù)相差較遠,所以無法直接對比,需要用normed參數(shù)轉(zhuǎn)化為密度。設(shè)置alpha透明度,它比箱線圖更直觀。
另外一種分析思路是對數(shù)據(jù)進行深加工。我們將薪資設(shè)立出不同的level
cut的作用是分桶,它也是數(shù)據(jù)分析常用的一種方法,將不同數(shù)據(jù)劃分出不同等級,也就是將數(shù)值型數(shù)據(jù)加工成分類數(shù)據(jù),在機器學習的特征工程中應用比較多。cut可以等距劃分,傳入一個數(shù)字就好。這里為了更好的區(qū)分,我傳入了一組列表進行人工劃分,加工成相應的標簽。
用lambda轉(zhuǎn)換百分比,然后作堆積百分比柱形圖(matplotlib好像沒有直接調(diào)用的函數(shù))。這里可以較為清晰的看到不同等級在不同地區(qū)的薪資占比。它比箱線圖和直方圖的好處在于,通過人工劃分,具備業(yè)務含義。0~3是實習生的價位,3~6是剛畢業(yè)沒有基礎(chǔ)的新人,整理數(shù)據(jù)那種,6~10是有一定基礎(chǔ)的,以此類推。
現(xiàn)在只剩下最后一列數(shù)據(jù)沒有處理,標簽數(shù)據(jù)。
現(xiàn)在的目的是統(tǒng)計數(shù)據(jù)分析師的標簽。它只是看上去干凈的數(shù)據(jù),元素中的[]是無意義的,它是字符串的一部分,和數(shù)組沒有關(guān)系。
你可能會想到用replace這類函數(shù)。但是它并不能直接使用。df_clean.positionLables.replace會報錯,為什么呢?因為df_clean.positionLables是Series,并不能直接套用replace。apply是一個好方法,但是比較麻煩。
這里需要str方法。
str方法允許我們針對列中的元素,進行字符串相關(guān)的處理,這里的[1:-1]不再是DataFrame和Series的切片,而是對字符串截取,這里把[]都截取掉了。如果漏了str,就變成選取Series第二行至最后一行的數(shù)據(jù),切記。
使用完str后,它返回的仍舊是Series,當我們想要再次用replace去除空格。還是需要添加str的。現(xiàn)在的數(shù)據(jù)已經(jīng)干凈不少。
positionLables本身有空值,所以要刪除,不然容易報錯。再次用str.split方法,把元素中的標簽按「,」拆分成列表。
這里是重點,通過apply和value_counts函數(shù)統(tǒng)計標簽數(shù)。因為各行元素已經(jīng)轉(zhuǎn)換成了列表,所以value_counts會逐行計算列表中的標簽,apply的靈活性就在于此,它將value_counts應用在行上,最后將結(jié)果組成一張新表。
這里的運算速度會有點慢,別擔心
用unstack完成行列轉(zhuǎn)換,看上去有點怪,因為它是統(tǒng)計所有標簽在各個職位的出現(xiàn)次數(shù),絕大多數(shù)肯定是NaN。
將空值刪除,并且重置為DataFrame,此時level_0為標簽名,level_1為df_index的索引,也可以認為它對應著一個職位,0是該標簽在職位中出現(xiàn)的次數(shù),之前我沒有命名,所以才會顯示0。部分職位的標簽可能出現(xiàn)多次,這里忽略它。
最后用groupby計算出標簽出現(xiàn)的次數(shù)。到這里,已經(jīng)計算出我們想要的結(jié)果。除了這種方法,也可以使用for循環(huán),大家可以試著練習一下,效率會慢不少。這種寫法的缺點是占用內(nèi)存較大,拿空間換時間,具體取舍看大家了。
加載wordcloud,anaconda沒有,自行下載吧。清洗掉引號,設(shè)置詞云相關(guān)的參數(shù)。因為我是在jupyter中顯示圖片,所以需要額外的配置figsize,不然wide和height的配置無效。wordcloud也兼容pandas,所以直接將結(jié)果傳入,然后顯示圖片,去除坐標。大功告成。
把最后結(jié)果的圖片右鍵另存為,發(fā)到朋友圈紀念一下吧,哈哈哈哈。
如果大家不妨花些時間做下面的練習:
- 不同職位的詞云圖有沒有差異?
- 不同薪資不同年限,他們崗位的標簽詞云會不會有差異?
- 不同薪資等級,和工作年限、職位的關(guān)系是怎么樣的?
- 以上的代碼,有沒有更優(yōu)化的實現(xiàn)方式?
- 薪資的上下限拆分,能不能用lambda方法?
到目前為止,我們進行的分析均是利用多維和可視化,多練習也就掌握了。其實它和excel沒有多大區(qū)別,只是python能夠更快地應付更多更復雜的數(shù)據(jù),當然新人在開始的效率不會高。
因為時間關(guān)系,更多的函數(shù)留到下次課程,下次課程也是最后一次了。
相關(guān)閱讀
互聯(lián)網(wǎng)數(shù)據(jù)分析能力的養(yǎng)成,需一份七周的提綱
如何七周成為數(shù)據(jù)分析師01:常見的Excel函數(shù)全部涵蓋在這里了
如何七周成為數(shù)據(jù)分析師02:Excel技巧大揭秘
如何七周成為數(shù)據(jù)分析師03:手把手教你Excel實戰(zhàn)
如何七周成為數(shù)據(jù)分析師:Excel技巧之甘特圖繪制(項目管理)
如何七周成為數(shù)據(jù)分析師:Excel技巧之打造多級菜單
如何七周成為數(shù)據(jù)分析師04:數(shù)據(jù)可視化之經(jīng)典圖表合集
如何七周成為數(shù)據(jù)分析師05:數(shù)據(jù)可視化之打造升職加薪的報表
如何七周成為數(shù)據(jù)分析師06:數(shù)據(jù)可視化之手把手打造BI
如何七周成為數(shù)據(jù)分析師07:快速掌握麥肯錫的分析思維
如何七周成為數(shù)據(jù)分析師08:如何建立數(shù)據(jù)分析的思維框架?
如何七周成為數(shù)據(jù)分析師09:寫給新人的數(shù)據(jù)庫指南
如何七周成為數(shù)據(jù)分析師10:SQL,從入門到熟練
如何七周成為數(shù)據(jù)分析師11:SQL,從熟練到掌握
如何七周成為數(shù)據(jù)分析師12:解鎖數(shù)據(jù)分析的正確姿勢(上)
如何七周成為數(shù)據(jù)分析師13:解鎖數(shù)據(jù)分析的正確姿勢(下)
如何七周成為數(shù)據(jù)分析師14:概率論的入門指南
如何七周成為數(shù)據(jù)分析師15:讀了本文,你就懂了概率分布
如何七周成為數(shù)據(jù)分析師16:數(shù)據(jù)分析必須懂的假設(shè)檢驗
如何七周成為數(shù)據(jù)分析師17:最全的運營數(shù)據(jù)指標解讀
如何七周成為數(shù)據(jù)分析師18:Python的新手教程
如何七周成為數(shù)據(jù)分析師19:Python的數(shù)據(jù)結(jié)構(gòu)
如何七周成為數(shù)據(jù)分析師20:了解和掌握Python的函數(shù)
如何七周成為數(shù)據(jù)分析師21:Python分析之numpy和pandas入門
#專欄作家#
秦路,微信公眾號ID:tracykanc,人人都是產(chǎn)品經(jīng)理專欄作家。
本文由 @秦路?原創(chuàng)發(fā)布于人人都是產(chǎn)品經(jīng)理。未經(jīng)許可,禁止轉(zhuǎn)載。
老師,麻煩可以發(fā)一下練習數(shù)據(jù)嘛,找了您的公眾號也沒有的
文中的聯(lián)系數(shù)據(jù)從哪里下載呀
敲到上面第一段程序,大家應該會有個疑問,pd.read_csv()中的filepath(文件目錄)怎么調(diào)用,其實可以先定義個變量再引用。
例:
>>>filep=’D:\\文檔\\BI練習\\BI\\DataAnalyst.csv’ #雙斜杠為第一個’\’是作為轉(zhuǎn)義符號,第二個’\’才是目錄中真正的\
>>> df=pd.read_csv(filep,encoding=’gb2312′)
>>>df
看不到圖片的同學可以在網(wǎng)頁按F12,在上方菜單點擊Console,后在可以輸入的地方輸入我寫得這段代碼重新加載圖片:
代碼:
$(“p”).find(“img”).each(function(){
var srcs=$(this).attr(“src”);
$(this).attr(“src”,srcs.split(“!”)[0])
});
復制粘貼后請把這網(wǎng)站自動轉(zhuǎn)換掉的中文符號例如:單引號、雙引號、括號,換成英文的,不然起不了作用
卡住了……bottomsalary到新的cut_word函數(shù)之后如何賦值?
干貨滿滿啊
終于把這章一步步打了一遍
不不.人多。我編程也沒問題,學到統(tǒng)計學,看那些公式,有點卡住了
堅持到現(xiàn)在的只有3人了嗎 ??
axis=1表示將函數(shù)用在行,axis=1則是列? 到底是行還是列?
文中的練習題哪里下載呢
卡頓