數(shù)據(jù)分析師還吃香嗎?用數(shù)據(jù)告訴你
項(xiàng)目簡介
有人說,這個(gè)時(shí)代,只要站在了風(fēng)口,豬都能飛起來,尤其互聯(lián)網(wǎng)行業(yè),千變?nèi)f化,日異月殊,一不小心就錯(cuò)過了風(fēng)口,如果沒記錯(cuò)的話,前幾年火的是App開發(fā),后來是大數(shù)據(jù),再接著是人工智能,現(xiàn)在則是區(qū)塊鏈,有人甚至用幣圈一日互聯(lián)網(wǎng)十年來形容虛擬幣和區(qū)塊鏈的火爆,如果單從熱點(diǎn)看,大數(shù)據(jù)貌似有點(diǎn)out了,那究竟如何呢?今天就對(duì)拉勾網(wǎng)上的數(shù)據(jù)分析職位的相關(guān)信息來一個(gè)探索性分析。
數(shù)據(jù)集
之所以采用拉勾網(wǎng)(201712)的數(shù)據(jù),是由于在互聯(lián)網(wǎng)垂直招聘領(lǐng)域,拉勾網(wǎng)坐***把交椅,無論是職位數(shù)量還是職位有效性,都優(yōu)于其它渠道。
本次采用的數(shù)據(jù)集主要有以下變量:薪酬下限、薪酬上限、工作地點(diǎn)、經(jīng)驗(yàn)要求、學(xué)歷要求、工作時(shí)間、公司、所處行業(yè)、公司融資情況、投資機(jī)構(gòu)、崗位要求等。
目的
通過實(shí)際數(shù)據(jù)來看看數(shù)據(jù)分析一職的現(xiàn)況如何,薪資是否還有吸引力等,具體來說,探索以下幾個(gè)問題:
- 數(shù)據(jù)分析職位在各城市的需求對(duì)比;
- 數(shù)據(jù)分析師的待遇情況;
- 工作經(jīng)驗(yàn)要求;
- 互聯(lián)網(wǎng)熱點(diǎn)城市的待遇情況;
- 工作經(jīng)驗(yàn)對(duì)待遇的影響;
- 學(xué)歷對(duì)待遇的影響;
- 需要掌握的技能;
- 哪些技能更吃香;
- 不同的經(jīng)驗(yàn)要求是否意味著不同的技能要求。
分析工具
在Jupyter Notebook中以Python3及其pandas、matplotlib、seaborn 和 wordcloud包為主進(jìn)行分析。下面開始正式分析。
數(shù)據(jù)整理
前期準(zhǔn)備工作,由于matplotlib包使用的默認(rèn)字體不支持中文,所以得修改配置,用文本編輯器打開下面命令得到的路徑中的 matplotlibrc文件,將以 font.family和 font.sans-serif開頭的兩行前的注釋符(#)刪掉,并在“font.sans-serif:”后加上SimHei,更改后結(jié)果如 font.sans-serif : SimHei, msyh, DejaVu Sans, ......;再將附帶的字體文件放入matplotlib同級(jí)目錄下的\fonts\ttf目錄中。
- import matplotlib
- print(matplotlib.matplotlib_fname())
接著刪除下面命令得到的用戶目錄中.matplotlib下的所有帶cache的文件及文件夾后重啟 Jupyter Notebook。
- print (matplotlib.get_configdir())
準(zhǔn)備工作完成,下面正式讀取數(shù)據(jù)并整理。
- # python3
- # _*_ coding:utf-8 _*_
- # 導(dǎo)入所需的包
- import numpy as np
- import pandas as pd
- import seaborn as sns
- import matplotlib.pyplot as plt
- from wordcloud import WordCloud
- % matplotlib inline
- matplotlib.rcParams['font.sans-serif'] = ['SimHei']
- # 讀取數(shù)據(jù)
- df = pd.read_excel('la_gou.xlsx')
- # 刪除不需要的變量
- df_clean1 = df.drop(['Index', 'home_page', 'address', 'url', 'date_time'],axis=1)
- # 刪除冗余行
- df_clean = df_clean1.drop_duplicates(['company', 'title', 'description'])
- df_clean=df_clean.reset_index(drop=True)
- df_clean.info()
經(jīng)過處理后的數(shù)據(jù)有16個(gè)變量,1766個(gè)觀測值,其中投資機(jī)構(gòu)(investor)缺失值太多,不過它不是這次分析的重點(diǎn),影響不大。
探索數(shù)據(jù)
一、職位在地域方面的區(qū)別:
- city_series = df_clean['city'].value_counts()
- y_cor = list(city_series.values)
- x_cor = list(np.arange(len(y_cor)))
- city_series.plot(kind='bar', figsize=(18,10), fontsize=15, rot=40);
- for x,y in zip(x_cor,y_cor):
- plt.text(x, y+1, '%s' % y, ha='center', va= 'bottom',fontsize=14);
- plt.title(u'各城市職位數(shù)量', size = 18);
- plt.show();
分析結(jié)果顯示,與以往媒體報(bào)道的北京互聯(lián)網(wǎng)發(fā)展***不同,上海至少在數(shù)據(jù)分析職位方面的需求超過了北京,但也只是略超,同時(shí),深圳與上海和北京相比,需求數(shù)量差距也不是非常大,其次杭州和廣州的需求比較大,且兩者幾乎無差距,再者就是成都有一定需求,其它城市的需求非常少。總體來說與人們對(duì)互聯(lián)網(wǎng)強(qiáng)城市的印象相符。
二、薪資概況:
- # 由于招聘給出的薪資是一個(gè)區(qū)間,故采用其上限和下限間的中值進(jìn)行分析
- df_clean['salary_median'].hist(figsize=(10,6), bins=30, edgecolor='k', grid=False);
- plt.xlabel(u'薪資(千/月)', size=15);
- plt.ylabel(u'頻數(shù)', size=15);
- plt.title(u'薪資分布', size=18);
- plt.xticks(range(0,90,5), size=15);
- plt.yticks(size=15);
- plt.grid(axis='y', alpha=0.2);
從分布看,薪資差異較大,有大量五千到兩萬五之間的職位,超過三萬的***,***有達(dá)到七萬多的,與人們印象不同,并不是每個(gè)數(shù)據(jù)分析師都能"月薪過萬",低于一萬的也有一定比例,但最多的還是一萬五到一萬七的,總的來說,待遇非常吸引人。
三、工作經(jīng)驗(yàn)要求:

- # 應(yīng)屆畢業(yè)生和10年以上人數(shù)很少,將應(yīng)屆畢業(yè)生歸類到一年以下,將10年以上歸類到5-10年,并去掉空格
- for i in df_clean.index:
- df_clean.loc[i,'experience'] = df_clean.loc[i,'experience'].strip()
- if df_clean.loc[i,'experience'] == u'應(yīng)屆畢業(yè)生':
- df_clean.loc[i,'experience'] = u'1年以下'
- if df_clean.loc[i,'experience'] == u'10年以上':
- df_clean.loc[i,'experience'] = u'5-10年'
- experience_freq = df_clean['experience'].value_counts()
- experience_sort = pd.Series([38, 621, 732, 141, 234], index=[u'1年以下',u'1-3年',u'3-5年',u'5-10年',u'不限'])
- experience_sort.plot(kind='bar',figsize=(8,5), fontsize=15, rot=0);
- plt.grid(color='#95a5a6', linewidth=1,axis='y',alpha=0.2)
- plt.xticks(range(5), experience_sort.index, size=15)
- plt.ylabel(u'頻數(shù)', size=15);
絕大部分崗位都要求有工作經(jīng)驗(yàn),3-5年的最多,其次是1-3年的,5-10年的專家級(jí)也有一定需求,還有一些不限經(jīng)驗(yàn)的,可能是忘記填寫或?qū)嵙?xí)之類的。
四、互聯(lián)網(wǎng)熱點(diǎn)城市薪資概況:
- salary_groupby_city = df_clean.groupby('city')['salary_median']
- large_city = city_series[0:6].index
- salary_of_city = []
- for city in large_city:
- salary_value = salary_groupby_city.get_group(city).values #得到各城市對(duì)應(yīng)的薪水的數(shù)組
- salary_of_city.append(salary_value)
- plt.style.use('seaborn-darkgrid')
- matplotlib.rcParams['font.sans-serif'] = ['SimHei']# 對(duì)于有些seaborn的style,必須同時(shí)運(yùn)行此命令,否則還是不顯示中文
- plt.figure(figsize=(10,5));
- plt.boxplot(salary_of_city, boxprops = {'color':'blue'},
- flierprops = {'markerfacecolor':'red','color':'black','markersize':4});
- plt.title(u'互聯(lián)網(wǎng)熱點(diǎn)城市薪資分布', size=18);
- plt.ylabel(u'薪資(千/月)',size=15);
- plt.xticks(np.arange(6)+1,large_city, size=15);
- plt.yticks(size=15);
- plt.grid(color='#95a5a6', linewidth=1,axis='x',alpha=0.2);
從結(jié)果看,北京的月薪中位數(shù)***,在2萬元,其次是上海,在1.75萬左右,深杭在1.5萬左右,廣州成都只有1萬,但薪資***的職位在深圳。
五、工作經(jīng)驗(yàn)對(duì)薪資的影響:
- salary_groupby_experience = df_clean.groupby('experience')['salary_median']
- salary_of_experience = []
- for experience in experience_sort.index:
- salary_value = salary_groupby_experience.get_group(experience).values
- salary_of_experience.append(salary_value)
- plt.figure(figsize=(10,5));
- plt.boxplot(salary_of_experience, boxprops = {'color':'blue'},
- flierprops = {'markerfacecolor':'red','color':'black','markersize':4});
- plt.title(u'不同工作經(jīng)驗(yàn)的薪資待遇', size=18);
- plt.ylabel(u'薪資(千/月)',size=15);
- plt.xticks(np.arange(5)+1,experience_sort.index, size=15);
- plt.yticks(size=15);
- plt.style.use('seaborn-darkgrid');
- matplotlib.rcParams['font.sans-serif'] = ['SimHei'];
- plt.grid(color='#95a5a6', linewidth=1,axis='x',alpha=0.2);
可見經(jīng)驗(yàn)越久,待遇越高,有5年經(jīng)驗(yàn)的薪資中位數(shù)***也有2萬,遠(yuǎn)比傳統(tǒng)行業(yè)高。
六、學(xué)歷對(duì)薪資的影響:

- edu_sort = pd.Series([52,170,1465,78,1], index=[u'不限',u'大專',u'本科',u'碩士',u'博士'])
- salary_groupby_edu = df_clean.groupby('education')['salary_median']
- salary_of_edu = []
- for education in edu_sort.index:
- salary_value = salary_groupby_edu.get_group(education).values
- salary_of_edu.append(salary_value)
- plt.figure(figsize=(10,6));
- plt.boxplot(salary_of_edu, boxprops = {'color':'blue'});
- plt.title(u'不同學(xué)歷的薪資待遇', size=18);
- plt.ylabel(u'薪資(千/月)',size=15);
- plt.xticks(np.arange(5)+1,edu_sort.index, size=15);
- plt.yticks(size=15);
其中不限學(xué)歷的可能由于招聘者忘記選擇,也可能由于其是新興領(lǐng)域,更看重實(shí)際能力而非學(xué)歷,對(duì)于有明確要求的,大專明顯低于本科和碩士,本科和碩士的差距倒不是特別大,只是碩士的起薪要高。
七、工作技能要求:
- # 添加技能列
- import re
- def get_skill(text):
- skill_list = re.findall('([a-zA-Z][0-9a-zA-Z]+|C\#|\.Net|R\d?|A\/B|算法)', text)
- for skill in skill_list:
- if skill.upper() == 'EXCEL' or skill.upper() == 'PPT':
- skill_list[skill_list.index(skill)] = 'office'
- return ','.join(skill_list).upper()
- df_clean['skill'] = df_clean['description'].apply(get_skill)
- # 生成技能字典
- import nltk
- skill_list = []
- for i in df_clean.index:
- if len(df_clean.loc[i, 'skill']) > 0:
- skill_list.extend(df_clean.loc[i, 'skill'].split(','))
- skill_freq = dict(nltk.FreqDist(skill_list))
- # 刪除主要的提取錯(cuò)的鍵值
- del skill_freq['AND']
- del skill_freq['TO']
- del skill_freq['IN']
- del skill_freq['DATA']
- del skill_freq['THE']
- del skill_freq['OF']
- del skill_freq['KPI']
- del skill_freq['APP']
- del skill_freq['WITH']
- del skill_freq['SERVER']
- wc = WordCloud(width=800, height=400, background_color='white').generate_from_frequencies(skill_freq)
- plt.figure(figsize=(8,4));
- plt.imshow(wc);
- plt.axis('off');
- plt.show();
可見,SQL,Office(主要是Excel和PPT)是需求***的,是絕大多數(shù)要求必須掌握的;其次,Python,算法和R的需求也很大,另外SAS,SPSS,Hadoop,Hive的需求也不小。
八、查看主流技能的薪酬平均中值:
- # 選取需求最多的20個(gè)技能
- skill_sort = sorted(skill_freq.items(), key=lambda item:item[1], reverse=True) #對(duì)技能頻數(shù)字典按值從大到小排序
- hot_skill_list = skill_sort[0:20]
- hot_skill_salary_mean = {} # 存放技能中值的均值的字典
- for i in hot_skill_list: # i 為技能和其頻次的列表的元素
- for j in df_clean.index:
- if i[0] in df_clean.loc[j, 'skill']: # 如果技能在數(shù)據(jù)框的技能列中
- if i[0] in hot_skill_salary_mean: # 如果技能在技能中值的均值的字典中
- # 技能鍵的值為原值加上新值
- hot_skill_salary_mean[i[0]] = hot_skill_salary_mean[i[0]] + df_clean.loc[j, 'salary_median']
- else:
- hot_skill_salary_mean[i[0]] = df_clean.loc[j, 'salary_median']
- hot_skill_salary_mean[i[0]] = hot_skill_salary_mean[i[0]] / i[1] # 技能中值的均值為之前計(jì)算的和除以技能頻數(shù)
- hot_skill_salary_mean = sorted(hot_skill_salary_mean.items(), key=lambda item:item[1]) #排序
- hot_skill_salary_mean #排序后返回由含字典元素的元組構(gòu)成的列表
- hot_skill_freq = [] #把前20個(gè)技能的需求頻數(shù)提取出來
- for i in hot_skill_salary_mean:
- hot_skill_freq.append(skill_freq[i[0]])
- hot_skill_freq # 排序會(huì)按其薪酬均值從小到大
- hot_skill_salary_key = [] # 熱門技能名稱列表
- hot_skill_salary_values = [] #熱門技能的中值的均值列表
- for i,j in dict(hot_skill_salary_mean).items():
- hot_skill_salary_key.append(i)
- hot_skill_salary_values.append(j)
- plt.figure(figsize=(10,6));
- plt.scatter(x = np.arange(len(hot_skill_salary_values)), y=hot_skill_salary_values, s=hot_skill_freq);
- plt.xticks(np.arange(len(hot_skill_salary_values)), hot_skill_salary_key, size=15, rotation=40);
- plt.yticks(size=15);
- plt.title('不同技能可以拿到的薪資中位數(shù)的均值', size=18);
- plt.ylabel('千/月', size=15);
- plt.ylim((5,26));
泡泡大小代表了需求量,從結(jié)果看,會(huì)R的薪資***,但這只是高薪的必要條件,而非充分條件,另外算法太低,可能是由于大多數(shù)崗位需求里都提到了算法,進(jìn)而拉低了其均值,如果進(jìn)一步分析,應(yīng)該能得出比較貼合實(shí)際的數(shù)據(jù),或者也可直接將此項(xiàng)剔除,分析其它崗位如深度學(xué)習(xí)機(jī)器學(xué)習(xí)的薪資來得到算法的薪資均值。Java是走向高級(jí)開發(fā)必不可少的路,Hadoop,Spark,Hive仍然是數(shù)據(jù)分析類職位的高薪必備技能。
九、看看主要工作經(jīng)驗(yàn)對(duì)主流技能的要求是否有差別:
- # 生成字典,來存放兩種經(jīng)驗(yàn)對(duì)應(yīng)的主流技能需求數(shù)
- skill_by_exp13 = {}
- skill_by_exp35 = {}
- df_skill_13 = df_clean[df_clean['experience']=='1-3年'][['experience', 'skill']]
- df_skill_35 = df_clean[df_clean['experience']=='3-5年'][['experience', 'skill']]
- for i in hot_skill_salary_key:
- for j in df_skill_13.index:
- if i in df_skill_13.loc[j, 'skill']:
- if i in skill_by_exp13:
- skill_by_exp13[i] = skill_by_exp13[i] + 1
- else:
- skill_by_exp13[i] = 1
- for i in hot_skill_salary_key:
- for j in df_skill_35.index:
- if i in df_skill_35.loc[j, 'skill']:
- if i in skill_by_exp35:
- skill_by_exp35[i] = skill_by_exp35[i] + 1
- else:
- skill_by_exp35[i] = 1
- ind = np.arange(len(skill_by_exp13))
- width = 0.35
- sns.set(context='notebook', style='darkgrid', palette='muted', font='simhei')
- plt.figure(figsize=(12,6));
- plt.grid(color='white', linewidth=1,alpha=0.3);
- plt.bar(ind, pd.Series(skill_by_exp13).values, width, label='1-3年');
- plt.bar(ind + width, pd.Series(skill_by_exp35).values, width, label='3-5年');
- plt.title('不同工作經(jīng)驗(yàn)對(duì)主流技能的需求對(duì)比', size=18);
- plt.xticks(ind+width/2, pd.Series(skill_by_exp13).index, size=15, rotation=40);
- plt.yticks(size=15)
- plt.legend();
幾乎所有主流技能,3-5年工作經(jīng)驗(yàn)的需求量都比1-3年的多,但這很大可能是因?yàn)?-5年的招聘數(shù)本身就比1-3年的多100個(gè)左右,但我注意到,對(duì)Matlab、MySQL、VBA及Tableau的需求兩者相差無幾,VBA方面3-5年的甚至低于1-3年的,這說明3-5年經(jīng)驗(yàn)要求的對(duì)這四種技能的需求不如1-3年的多。
結(jié)論匯總
- 對(duì)數(shù)據(jù)分析一職的需求主要集中在北上廣深杭,其中北京和上海***,深圳需求緊隨其后,廣州和杭州相比上海和北京需求減半,但比起其它城市依然不少。
- 大多數(shù)職位提供的薪資中值在5千到2萬5之間,很少有給出3萬的,但也有極少數(shù)崗位,給出了五六萬的高薪。
- 大多數(shù)崗位要求有工作經(jīng)驗(yàn),要求有3-5年經(jīng)驗(yàn)的最多,其次是1-3年的,不要求或只要求不到一年的很少。
- 互聯(lián)網(wǎng)發(fā)展熱門城市中,北京給出的薪資的中值***,達(dá)到了2萬元,上海緊隨其后,比北京低一兩千,杭州和深圳基本持平,基本在1萬5左右,這有點(diǎn)出人意料,考慮到置業(yè)成本,去杭州貌似比深圳更好,廣州和成都的中值在1萬左右,可見,至少在數(shù)據(jù)方面,杭州的發(fā)展已經(jīng)超過廣州這個(gè)一線城市了。
- 工作經(jīng)驗(yàn)與薪資密切相關(guān),1-3年經(jīng)驗(yàn)的薪資中值大部分超過了1萬,3-5年的都在1萬5以上,而5年以上的,薪資中值都在2萬以上。
- 學(xué)歷方面,碩士對(duì)本科的優(yōu)勢不是很明顯,但下限是肯定高于本科的,大專相比本科劣勢就比較明顯了,薪資低不少,而博士相對(duì)碩士也有很大優(yōu)勢,但需求少。
- 技能方面,office(主要是excel其次少部分PPT)和SQL需求最多,Python、R、算法緊隨其后,Hadoop、SPSS、Hive、SAS、和Spark的需求也不少。
- 對(duì)于拿到高薪的必要條件,R優(yōu)勢***,其次是Java,Linux等,當(dāng)然這些條件并非單一滿足,一般要同時(shí)會(huì)其它高級(jí)技能才能拿到高薪,顯然這已經(jīng)不是基礎(chǔ)的數(shù)據(jù)分析需要的技能了,可能側(cè)重于數(shù)據(jù)挖掘和建模等。
- 要求3-5年經(jīng)驗(yàn)的和要求1-3年經(jīng)驗(yàn)的在技能需求上沒有太大差別,對(duì)于這條結(jié)論不是很有把握,不是太符合邏輯,等日后再詳細(xì)分析。
思考·總結(jié)
通過這次分析,深切的感受到了思路的重要性,如果你對(duì)探索數(shù)據(jù)沒有好奇心,沒有一點(diǎn)自己的想法,那真可謂無處下手,不知道該分析什么,正所謂思路為“道”,工具為“術(shù)”,分析之前,得先給自己提出幾個(gè)想探索的問題,或想驗(yàn)證的假設(shè),當(dāng)然這點(diǎn)不是非得一步到位,也可以循序漸進(jìn),隨著分析的不斷進(jìn)行再開展新的探索。
“術(shù)”方面的工具技能也很重要,有時(shí)候你不知道那個(gè)函數(shù)的用法,不知道那個(gè)參數(shù)的設(shè)置,可能找很久都找不到,比如對(duì)柱狀圖添加文字說明,起初我按照搜索到的方法添加,可就是不出效果,搜了好幾種方法都不行,無奈之下我只得把別人的代碼截圖一行一行敲下來運(yùn)行驗(yàn)證,***發(fā)現(xiàn)是因?yàn)闆]放在一個(gè)cell里這個(gè)低級(jí)原因,當(dāng)然,這個(gè)過程中我又學(xué)到了別的知識(shí)。術(shù)方面還有一點(diǎn)需要說的是,早期seaborn包會(huì)對(duì)matplotlib的圖自動(dòng)美化,但新版改了,不會(huì)自動(dòng)美化,得自己設(shè)置,這方面花了大量時(shí)間搜索,主要是不知道對(duì)應(yīng)的術(shù)語叫什么,只能按文字描述搜索,***發(fā)現(xiàn),圖像的灰底不是顏色,是style,可以用兩種方式設(shè)置,但兩種都不好用,因?yàn)橹灰獙?duì)一個(gè)圖設(shè)置后,那做其它圖時(shí)都會(huì)默認(rèn)采用你設(shè)置的這個(gè)style,而我希望只針對(duì)單個(gè)圖起作用。
項(xiàng)目之外的,我感到主動(dòng)學(xué)習(xí)非常重要,對(duì)于自己不會(huì)的,不要畏懼,也不要偷懶,要相信自己碰到的問題別人也絕對(duì)碰到過,搜一搜,看看別人是怎么解決的,比如對(duì)于技能的提取及詞云的繪制,起初用了結(jié)巴分詞提取,但提取有疏漏,不過沒有大的問題,但繪制詞云時(shí),出來的都是中文詞,基本沒有技能名,我只好去找別的方法,看能不能過濾掉結(jié)巴提取后的中文詞,***發(fā)現(xiàn)何不采用正則重新提取呢,于是進(jìn)行了重新提取,但繪制詞云時(shí)又碰到重復(fù)顯示的問題,同樣的詞以不同大小和顏色顯示好幾次,但詞并沒有問題。***用自定義詞典解決了。
另外就是英語非常重要,有些函數(shù)的參數(shù)太多,以至于官網(wǎng)文檔都沒有詳細(xì)說,它可能是作為一些共用的參數(shù)放在了其它函數(shù)中介紹。***,對(duì)于崗位描述的探索還能進(jìn)一步采用語義分析,得出更明確的要求,因?yàn)橛行┮笫潜仨殱M足的,有些是加分項(xiàng),但水平所限,還不能語義分析,還有就是投資公司,如果數(shù)據(jù)較全也能探索下金融方面這些機(jī)構(gòu)的投資偏好及相互間的裙帶關(guān)系,畢竟,中國的互聯(lián)網(wǎng),誰都繞不開阿里騰訊及其背后的資本。