天天看點

資料分析行業薪資的秘密,你想知道的都在這裡(2)

資料分析行業薪資的秘密,你想知道的都在這裡(2)

第二部分:職位資訊清洗及資料提取

資料分析師的收入怎麼樣?哪些因素對于資料分析的薪資影響最大?哪些行業對資料分析人才的需求量最高?我想跳槽,應該選擇大公司大平台還是初創的小公司?按我目前的教育程度,工作經驗,和掌握的工具和技能,能獲得什麼樣水準的薪資呢?

我們使用python抓取了2017年6月26日拉鈎網站内搜尋“資料分析”關鍵詞下的450條職位資訊。通過對這些職位資訊的分析和模組化來給你答案。

本系列文章共分為五個部分,分别是資料分析職位資訊抓取,資料清洗及預處理,資料分析職位分布分析,資料分析薪資影響因素分析,以及資料模組化和薪資預測。這是第二篇:職位資訊清洗及資料提取。

第二篇文章是對擷取的資料進行清洗,預處理和特征提取。在第一篇文章中我們抓取了拉勾網的450條職位資訊及職位描述。但這些資訊無法直接用于資料分析,我們需要對抓取到的資訊進行清洗,規範現有資料的格式,提取資訊中的資料及特征,為後續的資料分析和模組化做準備。下面開始介紹苦逼的

資料清洗流程介紹。

資料清洗前的準備工作

首先是開始前的準備工作,導入所需要的庫檔案,包括常用的numpy和pandas庫用于計算平均薪資以及對字元進行分列等操作,正規表達式re庫用于字元的查找和替換操作,結巴分詞庫jieba用于對職位描述進行分詞操作,自然語言處理nltk庫用于計算職位描述的文字豐富度名額,還有kmeans用于對平均

薪資進行聚類操作。

#導入所需庫檔案 

import re 

import numpy as np 

import pandas as pd 

import jieba as jb 

import jieba.analyse 

import jieba.posseg as pseg 

import nltk 

from sklearn import preprocessing 

from sklearn.cluster import kmeans  

導入我們之前抓取并儲存的資料表,并檢視資料表的次元以及各字段名稱。後面我們會經常使用這些字段名稱。

#導入之前抓取并儲存的資料表 

lagou=pd.dataframe(pd.read_csv('lagou_data_analysis_2017-06-26.csv',header=0,encoding='gbk')) 

#檢視資料表次元及字段名稱 

lagou.columns,lagou.shape  

資料分析行業薪資的秘密,你想知道的都在這裡(2)

職位資訊清洗及預處理

開始對職位資訊的各個字段進行清洗和預處理,主要清洗的内容包括文本資訊提取和處理,内容搜尋和替換,字段内的空格處理,數值資訊提取和計算,英文字母統一大小寫等等。我們将先展示清洗前的原始字段,然後在展示清洗後的新字段内容。

行業字段清洗及處理

第一個清洗的字段是行業字段,抓取到的行業字段比較混亂,有些隻有一個行業名稱,有些則有兩級的行業名稱。我們保留行業字段第一部分的資訊,對有兩部分行業名稱的字段取前一個。

#檢視原始industryfield字段資訊 

lagou[['industryfield']].head()  

資料分析行業薪資的秘密,你想知道的都在這裡(2)

由于行業名稱之間有的以頓号分割,有的以逗号分割,我們先将所有的分隔符統一為逗号,然後對這個字段進行分列。并将分列後的字段重新拼接回原資料表中。

#對industryfield字段進行清洗及分列 

#建立list存儲清洗後的行業字段 

industry=[] 

#将頓号分隔符替換為逗号 

for x in lagou['industryfield']: 

    c=x.replace("、", ",") 

    industry.append(c) 

#替換後的行業資料改為dataframe格式     

industry=pd.dataframe(industry,columns=["industry"]) 

#對行業資料進行分列 

industry_s=pd.dataframe((x.split(',') for x in industry["industry"]),index=industry["industry"].index,columns=['industry_1','industry_2']) 

#将分列後的行業資訊比對回原資料表 

lagou=pd.merge(lagou,industry_s,right_index=true, left_index=true) 

#清除字段兩側空格 

lagou["industry_1"]=lagou["industry_1"].map(str.strip)  

以下是清洗後的行業字段。

#檢視清洗後的行業字段 

lagou[["industry_1","industry_2"]].head() 

資料分析行業薪資的秘密,你想知道的都在這裡(2)

融資階段字段清洗及處理

第二個清洗的字段是融資階段字段,抓取下來的原始資訊中對融資階段進行了雙重辨別,例如成長型(a輪)。由于第一個辨別”成長型”定義比較寬泛,我們提取第二個括号中的辨別。

#檢視清洗前的financestage字段 

lagou[['financestage']].head()  

資料分析行業薪資的秘密,你想知道的都在這裡(2)

首先建立一個字典,将資料表中融資階段的每一條資訊與字典中的key進行查找。如果融資階段資訊中包含字典中的任何一個key,我們就把這個key對應的value記錄下來。

#提取并處理financestage中的融資資訊 

#建立一個字典 

f_dict = {'未融資':'未融資', 

          '天使輪':'天使輪', 

          'a輪':'a輪', 

          'b輪':'b輪', 

          'c輪':'c輪', 

          'd輪':'d輪', 

          '不需要':'不需要融資', 

          '上市公司':'上市公司' 

          } 

#建立list存儲清洗後的資訊 

financestage2=[] 

#逐一提取financestage字段中的每一條資訊 

for i in range(len(lagou['financestage'])): 

    #逐一提取字典中的每一條資訊 

    for (key, value) in f_dict.items(): 

        #判斷financestage字段中是否包含字典中的任意一個key 

        if key in lagou['financestage'][i]: 

            #如何包含某個key,則把對應的value儲存在list中 

            financestage2.append(value) 

#把新儲存的list添加到原資料表中             

lagou["financestage1"]=financestage2  

#檢視清洗後的financestage字段 

lagou[["financestage1"]].head() 

資料分析行業薪資的秘密,你想知道的都在這裡(2)

職位名稱字段清洗及處理

第三個清洗的字段是職位名稱,這裡我們要提取職位裡的title資訊。沒有title資訊的都統一歸為其他。具體方法是将每個職位名稱與現有的title清單逐一判斷,如果職位名稱中含有title關鍵字就被劃分到這個類别下。否則被歸為其他類。

#檢視清洗前的positionname字段 

lagou[['positionname']].head()  

資料分析行業薪資的秘密,你想知道的都在這裡(2)

#提取并處理positionname中的職位資訊 

positionname3=[] 

#對職位名稱進行判斷歸類 

for i in range(len(lagou['positionname'])): 

    if '實習' in lagou['positionname'][i]: 

        positionname3.append("實習") 

    elif '助理' in lagou['positionname'][i]: 

        positionname3.append("助理") 

    elif '專員' in lagou['positionname'][i]: 

        positionname3.append("專員") 

    elif '主管' in lagou['positionname'][i]: 

        positionname3.append("主管") 

    elif '經理' in lagou['positionname'][i]: 

        positionname3.append("經理") 

    elif '專家' in lagou['positionname'][i]: 

        positionname3.append("專家") 

    elif '總監' in lagou['positionname'][i]: 

        positionname3.append("總監") 

    elif '工程師' in lagou['positionname'][i]: 

        positionname3.append("工程師") 

    else: 

        #以上關鍵詞都不包含的職位歸為其他 

        positionname3.append("其他") 

#把新儲存的list添加到原資料表中         

lagou["positionname1"]=positionname3  

#檢視清洗後的positionname字段 

lagou[["positionname1"]].head()  

資料分析行業薪資的秘密,你想知道的都在這裡(2)

薪資範圍字段清洗及處理

第四個清洗的字段是薪資範圍。抓取到的資料中薪資範圍是一個區間值,比較分散,無法直接使用。我們對薪資範圍進行清洗,去掉無關的資訊并隻保留薪資上限和下限兩個數字,然後使用這兩個數字計算出平均薪資值。

#檢視清洗前的salary字段 

lagou[['salary']].head()  

資料分析行業薪資的秘密,你想知道的都在這裡(2)

#提取并計算平均薪資 

#建立list用于存儲資訊 

salary1=[] 

#對salary字段進行清洗 

for i in lagou['salary']: 

    #設定要替換的正規表達式k|k 

    p = re.compile("k|k") 

    #按正規表達式對salary字段逐條進行替換(替換為空) 

    salary_date = p.sub("", i) 

    #完成替換的資訊添加到前面建立的新list中 

    salary1.append(salary_date) 

#将清洗後的字段合并到原資料表中 

lagou['salary1']=salary1 

#對薪資範圍字段進行分列 

salary_s=pd.dataframe((x.split('-') for x in lagou['salary1']),index=lagou['salary1'].index,columns=['s_salary1','e_salary1']) 

#更改字段格式 

salary_s['s_salary1']=salary_s['s_salary1'].astype(int) 

salary_s['e_salary1']=salary_s['e_salary1'].astype(int)  

#計算平均薪資 

#建立list用于存儲平均薪資 

salary_avg=[] 

#逐一提取薪資範圍字段 

for i in range(len(salary_s)): 

#對每一條資訊字段計算平均薪資,并添加到平均薪資list中。 

salary_avg.append((salary_s['s_salary1'][i] + salary_s['e_salary1'][i])/2) 

#将平均薪資拼接到薪資表中 

salary_s['salary_avg']=salary_avg 

#将薪資表與原資料表進行拼接 

lagou=pd.merge(lagou,salary_s,right_index=true, left_index=true)  

#檢視清洗以後的salary_avg字段 

lagou[["salary_avg"]].head()  

資料分析行業薪資的秘密,你想知道的都在這裡(2)

職位資訊中的資料提取

在職位描述字段中,包含了非常詳細和豐富的資訊。比如資料分析人才的能力要求和對各種資料分析工具的掌握程度等。我們對這個字段的一些特征進行名額化,對有價值的資訊進行提取和統計。

職位描述字段中的資料提取

第五個清洗的字段是職位描述,準确的說從職位描述字段中提取資訊。職位描述中包含了大量關于職位資訊,工作内容,和個人能力方面的資訊,非常有價值。但無法直接拿來使用。需要進行資訊提取。我們将對職位描述字段進行三方面的資訊提取。

第一是提取職位描述中對于個人能力的要求,換句話說就是資料分析人員使用工具的能力。我們整理了10個最常見的資料分析工具。來看下每個職位描述中都出行了哪些工具名稱。由于一些工具間存在可替代性,是以每個職位描述中可能會出現多個工具的名稱。沒出現一個工具名稱,我們就會在相應的工具下表示1,如果沒有出現則辨別為0。

#檢視清洗以前的job_detail字段 

lagou[['job_detail']].head()  

資料分析行業薪資的秘密,你想知道的都在這裡(2)

#提取職位描述字段,并對英文統一轉化為小寫 

lagou['job_detail']=lagou['job_detail'].map(str.lower) 

#提取職位描述中的工具名稱 

tools=['sql','python','excel','spss','matlab','sas','r','hadoop','spark','tableau'] 

#建立list用于存儲資料 

tool=np.array([[0 for i in range(len(tools))] for j in range(len((lagou['job_detail'])))]) 

#逐一提取職位描述資訊 

for i in range(len(lagou['job_detail'])): 

    #逐一提取工具名稱 

    for t in tools: 

        #獲得工具名稱的索引位置(第幾個工具) 

        index=tools.index(t) 

        #判斷工具名稱是否出現在職位描述中 

        if t in lagou['job_detail'][i]: 

            #如果出現,在該工具索引位置(列)填1 

            tool[i][index]=1 

        else: 

            #否則在該工具索引位置(列)填0 

            tool[i][index]=0 

#将獲得的資料轉換為dataframe格式             

analytics_tools=pd.dataframe(tool,columns=tools) 

#按行(axis=1)對每個職位描述中出現的工具數量進行求和 

tool_num=analytics_tools.sum(axis=1) 

#将工具數量求和拼接到原資料表中 

analytics_tools["tool_num"]=tool_num 

#将表與原資料表進行拼接 

lagou=pd.merge(lagou,analytics_tools,right_index=true, left_index=true)  

#檢視從job_detail中提取的分析工具資訊 

lagou[['sql','python','excel','spss','matlab','sas','r','hadoop','spark','tableau','tool_num']].head()  

資料分析行業薪資的秘密,你想知道的都在這裡(2)

職位描述所使用的字數統計

第二是計算職位描述所使用的字數,我們猜測初級簡單的工作描述會比較簡單,而進階複雜的工作描述則會更複雜一些。是以職位描述中不同的字數裡也可能隐藏着某種資訊或關聯。

#計算職位描述的字數 

#建立list用于存儲新資料 

jd_num=[] 

    #轉換資料格式(list轉換為str) 

    word_str = ''.join(lagou['job_detail'][i]) 

    #對文本進行分詞 

    word_split = jb.cut(word_str) 

    #使用|分割結果并轉換格式 

    word_split1 = "| ".join(word_split) 

    #設定字元比對正規表達式 

    pattern=re.compile('\w') 

    #查找分詞後文本中的所有字元并指派給word_w 

    word_w=pattern.findall(word_split1) 

    #計算word_w中字元數量并添加到list中 

    jd_num.append(len(word_w)) 

#對字元數量進行歸一化     

min_max_scaler = preprocessing.minmaxscaler() 

min_max_jd_num = min_max_scaler.fit_transform(jd_num) 

#将歸一化的資料添加到原資料表中 

lagou['jd_num']=min_max_jd_num  

#檢視職位描述字數 

jd_num[:10]  

資料分析行業薪資的秘密,你想知道的都在這裡(2)

#檢視歸一化的職位描述字段 

lagou[['jd_num']].head()  

資料分析行業薪資的秘密,你想知道的都在這裡(2)

職位描述的詞彙豐富度統計

第三是計算職位描述中的文字豐富度名額。和前面的字數統計一樣。初級職位所對應的工作會相對簡單,在描述上也會比較簡單。進階職位則可能需要更詳細的和負責的描述。是以文字豐富度名額上也會更高一些。

#計算職位描述文字豐富度 

#建立新list用于存儲資料 

diversity=[] 

    #将文本中的英文統一轉化為小寫 

    word_str=word_str.lower() 

    #查找職位描述中的所有中文字元 

    word_list=re.findall(r'[\u4e00-\u9fa5]', word_str) 

    word_str1=''.join(word_list) 

    word_split = jb.cut(word_str1) 

    #使用空格分割結果并轉換格式 

    word_split1 = " ".join(word_split) 

    #使用nltk對句子進行分詞 

    tokens = nltk.word_tokenize(word_split1) 

    #轉化為text對象 

    text = nltk.text(tokens) 

    #計算職位描述的文字豐富度(唯一詞/所有詞) 

    word_diversity=len(set(text)) / len(text) 

    #将文本詞彙豐富度資料添加到list中 

    diversity.append(word_diversity) 

#将文字豐富度比對到原資料表中    

lagou["diversity"]=diversity  

#檢視職位描述豐富度字段 

lagou[["diversity"]].head() 

資料分析行業薪資的秘密,你想知道的都在這裡(2)

對資料分析的薪資進行聚類

完成清洗和資料提取後,平均薪資已經比薪資範圍要具體的多了,但仍然比較離散。我們對這些平均薪資進行聚類來支援後面的模組化和預測工作。以下是具體的代碼和聚類結果。我們将類别标簽添加到原始資料表中。

#提取平均工作年限,平均薪資和平均公司規模字段 

salary_type = np.array(lagou[['salary_avg']]) 

#進行聚類分析 

clf=kmeans(n_clusters=3) 

#訓練模型 

clf=clf.fit(salary_type) 

#将距離結果标簽合并到原資料表中 

lagou['cluster_label']= clf.labels_ 

#輸出聚類結果 

clf.cluster_centers_  

資料分析行業薪資的秘密,你想知道的都在這裡(2)

聚類後平均薪資被分為三個類别,第1類是薪資均值為19.3k的區間,分類标記為0。第二類是薪資均值為8.2k的區間,分類标記為1,。第三類是薪資均值為32.1的區間,分類标記為3。

#對平均薪資進行聚類預測 

clf.predict(9),clf.predict(25),clf.predict(30)  

資料分析行業薪資的秘密,你想知道的都在這裡(2)

#檢視資料表中的類别辨別字段 

lagou[['salary_avg','cluster_label']].head()  

資料分析行業薪資的秘密,你想知道的都在這裡(2)

檢視清洗及處理後的資料表

到這裡我們完成了對450個職位資訊的字段清洗和資料提取工作。下面我們再來檢視下資料表的次元,名稱以及資料表中的資料。在下一篇文章中我們将使用這個資料表對資料分析職位的分布情況以及薪資的影響因素進行分析,并通過模組化對薪資收入進行預測。

lagou.columns,lagou.shape 

資料分析行業薪資的秘密,你想知道的都在這裡(2)

#檢視清洗完的資料表 

lagou.head() 

資料分析行業薪資的秘密,你想知道的都在這裡(2)

本篇文章我們對抓取到的職位資訊進行了清洗和資料提取。資料清洗是一個苦逼的工作,但卻是分析和模組化過程中必不可少的一個步驟。經過清洗後我們就可以對職位資料進行分析和模組化了,後面的文章中我們将從職位需求分布和薪資影響因素兩個方面進行分析,并在最後對資料分析行業的薪資進行模組化,對薪資分類和具體的薪資值進行預測。

本文作者:王彥平

來源:51cto