如何七周成為數據分析師22:用pandas進行數據分析實戰

13 評論 37609 瀏覽 64 收藏 30 分鐘

本文是《如何七周成為數據分析師》的第二十二篇教程,如果想要了解寫作初衷,可以先行閱讀七周指南。溫馨提示:如果您已經熟悉Python,大可不必再看這篇文章,或只挑選部分。

大家學習Python,不練習怎么行?

這次依舊使用網絡抓取的數據分析師的招聘薪資作為練習數據。在早期我們已經用它進行了Excel、BI可視化、SQL三方面的實戰訓練,想必大家已經很熟悉了,我不再贅述。

主要內容是進行數據讀取,數據概述,數據清洗和整理,分析和可視化。按照本教程,相信大家的Pandas會上到一個新臺階,遇到文中沒有提及的錯誤,通過搜索引擎解決吧。

image.png

首先載入我們的練習數據。

在pandas中,常用的載入函數是read_csv。除此之外還有read_excel和read_table,table可以讀取txt。若是服務器相關的部署,則還會用到read_sql,直接訪問數據庫,但它必須配合mysql相關包。

read_csv擁有諸多的參數,encoding是最常用的參數之一,它用來讀取csv格式的編碼。這里使用了gb2312,該編碼常見于windows,如果報錯,可以嘗試utf-8。

sep參數是分割符,有些csv文件用逗號分割列,有些是分號,有些是\t,這些都需要具體設置。header參數為是否使用表頭作為列名,默認是。names參數可以為列設置額外的名字,比如csv中的表頭是中文,但是在pandas中最好轉換成英文。

上述是主要的參數,其他參數有興趣可以學習。一般來說,csv的數據都是干凈的,excel文件則有合并單元格這種惡心的玩意,盡量避免。

現在有了數據df,首先對數據進行快速的瀏覽。

image.png

這里列舉出了數據集擁有的各類字段,一共有6876個,其中companyLabelList,businessZones,secondType,positionLables都存在為空的情況。公司id和職位id為數字,其他都是字符串。

image.png

因為數據集的數據比較多,如果我們只想瀏覽部分的話,可以使用head函數,顯示頭部的數據,默認5,也可以自由設置參數,如果是尾部數據則是tail。

image.png

數據集中,最主要的臟數據是薪資這塊,后續我們要拆成單獨的兩列。

看一下是否有重復的數據。

image.png

unique函數可以返回唯一值,數據集中positionId是職位ID,值唯一。配合len函數計算出唯一值共有5031個,說明有多出來的重復值。

使用drop_duplicates清洗掉。

image.png

drop_duplicates函數通過subset參數選擇以哪個列為去重基準。keep參數則是保留方式,first是保留第一個,刪除后余重復值,last還是刪除前面,保留最后一個。duplicated函數功能類似,但它返回的是布爾值。

接下來加工salary薪資字段。目的是計算出薪資下限以及薪資上限。

image.png

薪資內容沒有特殊的規律,既有小寫k,也有大小K,還有「k以上」這種蛋疼的用法,k以上只能上下限默認相同。

這里需要用到pandas中的apply。它可以針對DataFrame中的一行或者一行數據進行操作,允許使用自定義函數。

image.png

我們定義了個word_cut函數,它查找「-」符號所在的位置,并且截取薪資范圍開頭至K之間的數字,也就是我們想要的薪資上限。apply將word_cut函數應用在salary列的所有行。

「k以上」這類臟數據怎么辦呢?find函數會返回-1,如果按照原來的方式截取,是word[:-2],不是我們想要的結果,所以需要加一個if判斷。

image.png

因為python大小寫敏感,我們用upper函數將k都轉換為K,然后以K作為截取。這里不建議用「以上」,因為有部分臟數據不包含這兩字。

image.png

將bottomSalary轉換為數字,如果轉換成功,說明所有的薪資數字都成功截取了。

薪資上限topSalary的思路也相近,只是變成截取后半部分。

image.png

在word_cout函數增加了新的參數用以判斷返回bottom還是top。apply中,參數是添加在函數后面,而不是里面的。這點需要注意。

接下來求解平均薪資。

image.png

數據類型轉換為數字,這里引入新的知識點,匿名函數lamba。很多時候我們并不需要復雜地使用def定義函數,而用lamdba作為一次性函數。

lambda x: ******* ,前面的lambda x:理解為輸入,后面的星號區域則是針對輸入的x進行運算。案例中,因為同時對top和bottom求平均值,所以需要加上x.bottomSalary和x.topSalary。word_cut的apply是針對Series,現在則是DataFrame。

axis是apply中的參數,axis=1表示將函數用在行,axis=1則是列。

這里的lambda可以用(df_duplicates.bottomSalary +?df_duplicates.topSalary)/2替代。

到此,數據清洗的部分完成。切選出我們想要的內容進行后續分析(大家可以選擇更多數據)。

image.png

先對數據進行幾個描述統計。

image.png

value_counts是計數,統計所有非零元素的個數,以降序的方式輸出Series。數據中可以看到北京招募的數據分析師一騎絕塵。

我們可以依次分析數據分析師的學歷要求,工作年限要求等。

針對數據分析師的薪資,我們用describe函數。

image.png

它能快速生成各類統計指標。數據分析師的薪資的平均數是17k,中位數是15k,兩者相差不大,最大薪資在75k,應該是數據科學家或者數據分析總監檔位的水平。標準差在8.99k,有一定的波動性,大部分分析師薪資在17+—9k之間。

一般分類數據用value_counts,數值數據用describe,這是最常用的兩個統計函數。

說了這么多文字,還是不夠直觀,我們用圖表說話。

pandas自帶繪圖函數,它是以matplotlib包為基礎封裝,所以兩者能夠結合使用。

image.png

%matplotlib inline是jupyter自帶的方式,允許圖表在cell中輸出。plt.style.use(‘ggplot’)使用R語言中的ggplot2配色作為繪圖風格,純粹為了好看。

image.png

用hist函數很方便的就繪制除出直方圖,比excel快多了。圖表列出了數據分析師薪資的分布,因為大部分薪資集中20k以下,為了更細的粒度。將直方圖的寬距繼續縮小。

image.png

數據分布呈雙峰狀,因為原始數據來源于招聘網站的爬取,薪資很容易集中在某個區間,不是真實薪資的反應(10~20k的區間,以本文的計算公式,只會粗暴地落在15k,而非均勻分布)。

數據分析的一大思想是細分維度,現在觀察不同城市、不同學歷對薪資的影響。箱線圖是最佳的觀測方式。

image.png

圖表的標簽出了問題,出現了白框,主要是圖表默認用英文字體,而這里的都是中文,導致了沖突。所以需要改用matplotlib。

image.png

首先加載字體管理包,設置一個載入中文字體的變量,不同系統的路徑不一樣。boxplot是我們調用的箱線圖函數,column選擇箱線圖的數值,by是選擇分類變量,figsize是尺寸。

ax.get_xticklabels獲取坐標軸刻度,即無法正確顯示城市名的白框,利用set_fontpeoperties更改字體。于是獲得了我們想要的箱線圖。改變字體還有其他方法,大家可以網上搜索關鍵字「matplotlib 中文字體」,都有相應教程。

從圖上我們看到,北京的數據分析師薪資高于其他城市,尤其是中位數。上海和深圳稍次,廣州甚至不如杭州。

image.png

從學歷看,博士薪資遙遙領先,雖然在top區域不如本科和碩士,這點我們要后續分析。大專學歷稍有弱勢。

image.png

工作年限看,薪資的差距進一步拉大,畢業生和工作多年的不在一個梯度。雖然沒有其他行業的數據對比,但是可以確定,數據分析師的職場上升路線還是挺光明的。

到目前為止,我們了解了城市、年限和學歷對薪資的影響,但這些都是單一的變量,現在想知道北京和上海這兩座城市,學歷對薪資的影響。

image.png

在by傳遞多個值,箱線圖的刻度自動變成元組,也就達到了橫向對比的作用(這方法其實并不好,以后會講解其他方式)。這種方法并不適宜元素過多的場景。從圖上可以看到,不同學歷背景下,北京都是稍優于上海的,北京愿意花費更多薪資吸引數據分析師,而在博士這個檔次,也是一個大幅度的跨越。我們不妨尋找其中的原因。

在pandas中,需要同時用到多個維度分析時,可以用groupby函數。它和SQL中的group by差不多,能將不同變量分組。

image.png

上圖是標準的用法,按city列,針對不同城市進行了分組。不過它并沒有返回分組后的結果,只返回了內存地址。這時它只是一個對象,沒有進行任何的計算,現在調用groupby的count方法。

image.png

它返回的是不同城市的各列計數結果,因為沒有NaN,每列結果都是相等的?,F在它和value_counts等價。

image.png

換成mean,計算出了不同城市的平均薪資。因為mean方法只針對數值,而各列中只有avgSalary是數值,于是返回了這個唯一結果。

image.png

groupby可以傳遞一組列表,這時得到一組層次化的Series。按城市和學歷分組計算了平均薪資。

image.png

后面再調用unstack方法,進行行列轉置,這樣看的就更清楚了。在不同城市中,博士學歷最高的薪資在深圳,碩士學歷最高的薪資在杭州。北京綜合薪資最好。這個分析結論有沒有問題呢?不妨先看招聘人數。

image.png

這次換成count,我們在groupby后面加一個avgSalary,說明只統計avgSalary的計數結果,不用混入相同數據。圖上的結果很明確了,要求博士學歷的崗位只有6個,所謂的平均薪資,也只取決于公司開出的價碼,波動性很強,畢竟這只是招聘薪資,不代表真實的博士在職薪資。這也解釋了上面幾個圖表的異常。

groupby是不是和數據透視表比較像?pandas其實有專門的數據透視函數,在另外一方面,groupby確實能完成不少透視工作。

接下來計算不同公司招聘的數據分析師數量,并且計算平均數。

image.png

這里使用了agg函數,同時傳入count和mean方法,然后返回了不同公司的計數和平均值兩個結果。所以前文的mean,count,其實都省略了agg。agg除了系統自帶的幾個函數,它也支持自定義函數。

image.png

 

上圖用lamba函數,返回了不同公司中最高薪資和最低薪資的差值。agg是一個很方便的函數,它能針對分組后的列數據進行豐富多彩的計算。但是在pandas的分組計算中,它也不是最靈活的函數。

現在我們有一個新的問題,我想計算出不同城市,招聘數據分析師需求前5的公司,應該如何處理?agg雖然能返回計數也能排序,但它返回的是所有結果,前五還需要手工計算。能不能直接返回前五結果?當然可以,這里再次請出apply。

image.png

自定義了函數topN,將傳入的數據計數,并且從大到小返回前五的數據。然后以city聚合分組,因為求的是前5的公司,所以對companyShortName調用topN函數。

同樣的,如果我想知道不同城市,各職位招聘數前五,也能直接調用topN。

image.png

可以看到,雖說是數據分析師,其實有不少的開發工程師,數據產品經理等。這是抓取下來數據的缺點,它反應的是不止是數據分析師,而是數據領域。不同城市的需求不一樣,北京的數據產品經理看上去要比上海高。

agg和apply是不同的,雖然某些方法相近,比如求sum,count等,但是apply支持更細的粒度,它能按組進行復雜運算,將數據拆分合并,而agg則必須固定為列。

運用group by,我們已經能隨意組合不同維度。接下來配合group by作圖。

image.png

多重聚合在作圖上面沒有太大差異,行列數據轉置不要混淆即可。

image.png

上述的圖例我們都是用pandas封裝過的方法作圖,如果要進行更自由的可視化,直接調用matplotlib的函數會比較好,它和pandas及numpy是兼容的。plt已經在上文中調用并且命名

image.png

上圖將上海和北京的薪資數據以直方圖的形式進行對比。因為北京和上海的分析師人數相差較遠,所以無法直接對比,需要用normed參數轉化為密度。設置alpha透明度,它比箱線圖更直觀。

另外一種分析思路是對數據進行深加工。我們將薪資設立出不同的level

image.png

cut的作用是分桶,它也是數據分析常用的一種方法,將不同數據劃分出不同等級,也就是將數值型數據加工成分類數據,在機器學習的特征工程中應用比較多。cut可以等距劃分,傳入一個數字就好。這里為了更好的區分,我傳入了一組列表進行人工劃分,加工成相應的標簽。

image.png

用lambda轉換百分比,然后作堆積百分比柱形圖(matplotlib好像沒有直接調用的函數)。這里可以較為清晰的看到不同等級在不同地區的薪資占比。它比箱線圖和直方圖的好處在于,通過人工劃分,具備業務含義。0~3是實習生的價位,3~6是剛畢業沒有基礎的新人,整理數據那種,6~10是有一定基礎的,以此類推。

現在只剩下最后一列數據沒有處理,標簽數據。

image.png

現在的目的是統計數據分析師的標簽。它只是看上去干凈的數據,元素中的[]是無意義的,它是字符串的一部分,和數組沒有關系。

你可能會想到用replace這類函數。但是它并不能直接使用。df_clean.positionLables.replace會報錯,為什么呢?因為df_clean.positionLables是Series,并不能直接套用replace。apply是一個好方法,但是比較麻煩。

這里需要str方法。

image.png

str方法允許我們針對列中的元素,進行字符串相關的處理,這里的[1:-1]不再是DataFrame和Series的切片,而是對字符串截取,這里把[]都截取掉了。如果漏了str,就變成選取Series第二行至最后一行的數據,切記。

image.png

使用完str后,它返回的仍舊是Series,當我們想要再次用replace去除空格。還是需要添加str的?,F在的數據已經干凈不少。

positionLables本身有空值,所以要刪除,不然容易報錯。再次用str.split方法,把元素中的標簽按「,」拆分成列表。

image.png

這里是重點,通過apply和value_counts函數統計標簽數。因為各行元素已經轉換成了列表,所以value_counts會逐行計算列表中的標簽,apply的靈活性就在于此,它將value_counts應用在行上,最后將結果組成一張新表。

這里的運算速度會有點慢,別擔心

image.png

用unstack完成行列轉換,看上去有點怪,因為它是統計所有標簽在各個職位的出現次數,絕大多數肯定是NaN。

image.png

將空值刪除,并且重置為DataFrame,此時level_0為標簽名,level_1為df_index的索引,也可以認為它對應著一個職位,0是該標簽在職位中出現的次數,之前我沒有命名,所以才會顯示0。部分職位的標簽可能出現多次,這里忽略它。

image.png

最后用groupby計算出標簽出現的次數。到這里,已經計算出我們想要的結果。除了這種方法,也可以使用for循環,大家可以試著練習一下,效率會慢不少。這種寫法的缺點是占用內存較大,拿空間換時間,具體取舍看大家了。

image.png

加載wordcloud,anaconda沒有,自行下載吧。清洗掉引號,設置詞云相關的參數。因為我是在jupyter中顯示圖片,所以需要額外的配置figsize,不然wide和height的配置無效。wordcloud也兼容pandas,所以直接將結果傳入,然后顯示圖片,去除坐標。大功告成。

把最后結果的圖片右鍵另存為,發到朋友圈紀念一下吧,哈哈哈哈。

如果大家不妨花些時間做下面的練習:

  • 不同職位的詞云圖有沒有差異?
  • 不同薪資不同年限,他們崗位的標簽詞云會不會有差異?
  • 不同薪資等級,和工作年限、職位的關系是怎么樣的?
  • 以上的代碼,有沒有更優化的實現方式?
  • 薪資的上下限拆分,能不能用lambda方法?

到目前為止,我們進行的分析均是利用多維和可視化,多練習也就掌握了。其實它和excel沒有多大區別,只是python能夠更快地應付更多更復雜的數據,當然新人在開始的效率不會高。

因為時間關系,更多的函數留到下次課程,下次課程也是最后一次了。

相關閱讀

互聯網數據分析能力的養成,需一份七周的提綱

如何七周成為數據分析師01:常見的Excel函數全部涵蓋在這里了

如何七周成為數據分析師02:Excel技巧大揭秘

如何七周成為數據分析師03:手把手教你Excel實戰

如何七周成為數據分析師:Excel技巧之甘特圖繪制(項目管理)

如何七周成為數據分析師:Excel技巧之打造多級菜單

如何七周成為數據分析師04:數據可視化之經典圖表合集

如何七周成為數據分析師05:數據可視化之打造升職加薪的報表

如何七周成為數據分析師06:數據可視化之手把手打造BI

如何七周成為數據分析師07:快速掌握麥肯錫的分析思維

如何七周成為數據分析師08:如何建立數據分析的思維框架?

如何七周成為數據分析師09:寫給新人的數據庫指南

如何七周成為數據分析師10:SQL,從入門到熟練

如何七周成為數據分析師11:SQL,從熟練到掌握

如何七周成為數據分析師12:解鎖數據分析的正確姿勢(上)

如何七周成為數據分析師13:解鎖數據分析的正確姿勢(下)

如何七周成為數據分析師14:概率論的入門指南

如何七周成為數據分析師15:讀了本文,你就懂了概率分布

如何七周成為數據分析師16:數據分析必須懂的假設檢驗

如何七周成為數據分析師17:最全的運營數據指標解讀

如何七周成為數據分析師18:Python的新手教程

如何七周成為數據分析師19:Python的數據結構

如何七周成為數據分析師20:了解和掌握Python的函數

如何七周成為數據分析師21:Python分析之numpy和pandas入門

#專欄作家#

秦路,微信公眾號ID:tracykanc,人人都是產品經理專欄作家。

本文由 @秦路?原創發布于人人都是產品經理。未經許可,禁止轉載。

更多精彩內容,請關注人人都是產品經理微信公眾號或下載App
評論
評論請登錄
  1. 老師,麻煩可以發一下練習數據嘛,找了您的公眾號也沒有的

    來自浙江 回復
  2. 文中的聯系數據從哪里下載呀

    來自浙江 回復
  3. 敲到上面第一段程序,大家應該會有個疑問,pd.read_csv()中的filepath(文件目錄)怎么調用,其實可以先定義個變量再引用。
    例:
    >>>filep=’D:\\文檔\\BI練習\\BI\\DataAnalyst.csv’ #雙斜杠為第一個’\’是作為轉義符號,第二個’\’才是目錄中真正的\
    >>> df=pd.read_csv(filep,encoding=’gb2312′)
    >>>df

    來自廣東 回復
    1. 看不到圖片的同學可以在網頁按F12,在上方菜單點擊Console,后在可以輸入的地方輸入我寫得這段代碼重新加載圖片:
      代碼:
      $(“p”).find(“img”).each(function(){
      var srcs=$(this).attr(“src”);

      $(this).attr(“src”,srcs.split(“!”)[0])
      });

      來自廣東 回復
    2. 復制粘貼后請把這網站自動轉換掉的中文符號例如:單引號、雙引號、括號,換成英文的,不然起不了作用

      來自廣東 回復
  4. 卡住了……bottomsalary到新的cut_word函數之后如何賦值?

    來自廣東 回復
    1. 干貨滿滿啊

      回復
    2. 終于把這章一步步打了一遍

      回復
  5. 不不.人多。我編程也沒問題,學到統計學,看那些公式,有點卡住了

    回復
  6. 堅持到現在的只有3人了嗎 ??

    來自廣東 回復
  7. axis=1表示將函數用在行,axis=1則是列? 到底是行還是列?

    來自北京 回復
  8. 文中的練習題哪里下載呢

    來自北京 回復
  9. 卡頓

    回復