一、項目背景
本次練習使用的數據集為美國城市巴爾的摩2016年公務員工資的數據集,將通過數據可視化和數據描述性分析等手段,分析其工資分布情況。
二、數據來源
本次使用的數據集可以從 https://catalog.data.gov/dataset/baltimore-city-employee-salaries-fy2016該網站進行下載。
其中,一共有13818條數據,7個字段,分別為:
- Name(姓名)
- JobTitle(職位名稱)
- AgencyID(工號)
- Agency(單位)
- HireDate(入職日期)
- AnnualSalary(年薪)
- GrossPay(總薪資-稅前)
三、定義問題
本次練習將圍繞工資數據集進行。分別會以下問題展現(xiàn)分析:
- 年薪的總體分布情況
- 年薪最高的職務,人數最多的職位
- 公務人員入職日期的情況
四、數據清洗與整理
# 設置notebook cell多行輸出
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = 'all' #默認為'last'
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import os
import warnings
os.chdir(r'E:\python_learn\train') # 設置相對路徑
warnings.filterwarnings('ignore') # 設置忽略警告
plt.style.use('ggplot') # 設置matplotlib的整體風格
file_name = 'Baltimore_City_Employee_Salaries_FY2016.csv'
salary = pd.read_csv(file_name)
salary.head()

# 查看數據結構
salary.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 13818 entries, 0 to 13817
Data columns (total 7 columns):
Name 13818 non-null object
JobTitle 13818 non-null object
AgencyID 13818 non-null object
Agency 13818 non-null object
HireDate 13818 non-null object
AnnualSalary 13818 non-null object
GrossPay 13546 non-null object
dtypes: object(7)
memory usage: 755.8+ KB
從返回的數據信息和結構信息可知,HireDate、AnnualSalary和GrossPay這3個字段的數據類型與實際不符,AnnualSalary和GrossPay字段的數據含有特殊符號,并且GrossPay字段部分數據缺失。
因此接下來要對存在問題的字段進行以下的清洗和整理工作:
- GrossPay字段的缺失數據處理
- AnnualSalary和GrossPay字段刪除特殊符號
- AnnualSalary和GrossPay str → numeric
- HireDate str → datetime
- JobTitle、Agency str → category
# 缺失值判斷及處理
salary.isna().sum()
salary.isna().sum().sum()
# 缺失數據比例較少,可以選擇刪除處理
Name 0
JobTitle 0
AgencyID 0
Agency 0
HireDate 0
AnnualSalary 0
GrossPay 272
dtype: int64
272
salary = salary.dropna()
salary.isna().sum()
salary.isna().sum().sum() # 缺失數據處理完成
Name 0
JobTitle 0
AgencyID 0
Agency 0
HireDate 0
AnnualSalary 0
GrossPay 0
dtype: int64
0
# AnnualSalary和GrossPay字段刪除特殊符號
def f(x):
return x.strip('$') # 刪除$符號
salary['AnnualSalary'] = salary['AnnualSalary'].map(f)
salary['GrossPay'] = salary['GrossPay'].map(f)
salary.head()

# HireDate、AnnualSalary和GrossPay這3個字段轉換為與實際數據相符的數據類型
# AnnualSalary和GrossPay → float
salary['AnnualSalary'] = salary['AnnualSalary'].astype(float)
salary['GrossPay'] = salary['GrossPay'].astype(float)
# HireDate → datetime
salary['HireDate'] = pd.to_datetime(salary['HireDate'])
salary.head()
salary.info() # 查看轉換后的數據結構 → 數據清洗后一共13546條數據

# 異常值檢測
salary_num = salary.iloc[:,5:]
# 箱型圖檢測
color = dict(boxes='DarkGreen', whiskers='DarkOrange', medians='DarkBlue', caps='Gray') # 顏色設置
box = salary_num.plot.box(figsize=(10,6),color=color)
plt.title('Outliers detection box chart',fontsize=14,pad=12)
# 篩出異常值
lst = []
cols = salary_num.columns
for col in cols:
salary_num_col = salary_num[col]
q1 = salary_num_col.quantile(0.25)
q3 = salary_num_col.quantile(0.75)
iqr = q3-q1
ma = q3+iqr*1.5
mi = q1-iqr*1.5
err = salary_num_col[(salary_num_col > ma) | (salary_num_col < mi)]
lst.append(err)
err_data = pd.concat(lst)
print('一共檢測出異常數據%i條!'%(len(err_data)),'\n')
print('異常數據展示前10條 \n',err_data.head(10))
Text(0.5, 1.0, 'Outliers detection box chart')
一共檢測出異常數據343條!
異常數據展示前10條
306 132600.0
448 130100.0
803 127500.0
849 132200.0
1183 130200.0
1336 138200.0
1352 157100.0
1658 127500.0
1938 166320.0
2193 129587.0
dtype: float64

鑒于不清楚異常值的產生原因,以及對美國公務人員的工資制度等信息不清楚,暫不對異常數據進行處理。
五、數據探索
5.1總體情況
# 人數
number_salary = salary['AgencyID'].count()
print('數據集涵蓋的樣本數為:%i'%number_salary)
數據集涵蓋的樣本數為:13546
# 單位
def s(x):
return x.split('(')[0]
salary['Agency'] = salary['Agency'].map(s) # 按左括號分裂
salary['Agency'] = salary['Agency'].astype('category')
company_count = len(salary['Agency'].cat.categories)
print('數據集涵蓋的單位數為:%i個'%company_count)
數據集涵蓋的單位數為:67個
# 職位
salary['JobTitle'] = salary['JobTitle'].astype('category') # 將JobTitle轉為分類數據
post_count = len(salary['JobTitle'].cat.categories)
print('數據集涵蓋的職位數為:%i個'%post_count)
數據集涵蓋的職位數為:1034個
# 人均年薪
per_salary = salary['AnnualSalary'].sum()/number_salary
print('美國城市巴爾的摩2016年公務員人均年薪為:%.2f 美元'%per_salary)
美國城市巴爾的摩2016年公務員人均年薪為:53507.98 美元
5.2工資總體分布情況
- 年薪總體分布
- 最高年薪
- 年薪最多人數的區(qū)間
# 工資總體分布情況 --->>> 直方圖描述
salary['AnnualSalary'].hist(figsize=(8,6),bins=20,alpha=0.8)
plt.title('AnnualSalary',pad=12)
plt.xlabel('AnnualSalary',fontsize=12,labelpad=10)
plt.ylabel('Number of people',fontsize=12,labelpad=10)

1、從直方圖的分布反映出,年薪的總體分布基本呈正態(tài)分布,但分布向左傾斜,說明美國城市巴爾的摩公務員高工資的職位還是較少。
2、其中,年薪在4-8萬美元之間的公務員占大部分,最高年薪達15萬美元。
5.3工資與職位的分布情況
- 年薪最高的職位
- 人數最多的職位
# 職位工資分布
post_salary = salary.groupby('JobTitle').mean()['AnnualSalary'].sort_values(ascending=False).head(10)
post_salary # 平均年薪排名前10的職位
JobTitle
STATE'S ATTORNEY 238772.0
Police Commissioner 200000.0
Executive Director V 182500.0
MAYOR 171635.0
Executive Director III 171306.5
CITY SOLICITOR 169800.0
DIRECTOR PUBLIC WORKS 169800.0
CITY AUDITOR 163000.0
Deputy Police Commissioner 154900.0
Executive Director I 153905.0
Name: AnnualSalary, dtype: float64
# 柱狀圖描述
post_salary.plot(kind='bar',
colormap='Blues_r',
alpha=0.8,
width=0.8,
figsize=(12,6),
rot=45,
)
plt.ylim([0,300000])
plt.title('Top 10 positions with average annual salary - picture01',fontsize=14,pad=12)
plt.ylabel('Average annual salary',fontsize=12,labelpad=12)
for x,y in zip(range(len(post_salary)),post_salary):
plt.text(x,y+0.5,'%.f'%y,ha='center',va='bottom',fontsize=12,)

# 職位人數分布
post_people = salary.groupby('JobTitle').count()['AgencyID'].sort_values(ascending=False).head(10)
post_people # 人數最多的前10職位
JobTitle
POLICE OFFICER 1756
LABORER (Hourly) 551
EMT Firefighter Suppression 351
RECREATION ARTS INSTRUCTOR 319
OFFICE SUPPORT SPECIALIST III 303
CROSSING GUARD 260
POLICE OFFICER (EID) 251
COMMUNITY AIDE 245
POLICE SERGEANT 235
SEASONAL MAINT AIDE 207
Name: AgencyID, dtype: int64
# 柱狀圖描述
post_people.plot(kind='bar',
colormap='Greens_r',
alpha=0.8,
width=0.8,
figsize=(12,6),
rot=45,
)
plt.ylim([0,2000])
plt.title('Top 10 positions with the largest number of people - Picture02',fontsize=14,pad=12)
for x,y in zip(range(len(post_people)),post_people):
plt.text(x,y,'%.f'%y,ha='center',va='bottom',fontsize=12,)

1、如柱狀圖1所示,年薪最高的職位為STATE'S ATTORNEY(州檢察官),其次為Police Commissioner(警察局長)和Executive Director V(執(zhí)行董事)
2、如柱狀圖2所示,人數最多的職位為POLICE OFFICER(警務人員),其次為LABORER-Hourly(小時勞工)和EMT Firefighter Suppression(消防員)
5.4公務員入職情況
- 公務人員2016年入職分布情況,入職人數最多的月份
# 公務人員2016年入職分布情況
salary['month'] = salary['HireDate'].dt.month # 添加一列月份列
salary.head()
entry_month = salary.groupby('month').count()['AgencyID']
entry_month

# 柱狀圖描述
entry_month.plot(kind='barh',
figsize=(14,8),
colormap='Oranges_r',
alpha=0.8,
width=0.7,
)
plt.title('Employment distribution of public servants in 2016',fontsize=14,pad=12)
plt.xlim([0,1800])
plt.xlabel('Number_of_people',labelpad=12)
for x,y in zip(entry_month,range(len(entry_month))):
plt.text(x,y,'%.f'%x,ha='left',va='center',fontsize=12,)

# 折線圖
entry_month.plot(kind='line',
figsize=(10,6),
colormap='Blues_r',
alpha=0.8,
)
plt.ylabel('Number of people',labelpad=12)
plt.title('Employment distribution of public servants in 2016',fontsize=14,pad=12)
plt.xlim([1,12])
plt.ylim([0,1800])
plt.axhline(y=entry_month.mean(),ls='--',c='r',lw=0.8,alpha=0.5,) #添加人數均值水平直線
plt.text(x=6,y=entry_month.max()+30,s=entry_month.max(),fontdict={'size':14,'color':'r'})
plt.text(x=12+0.1,y=entry_month.mean(),s=round(entry_month.mean()),fontdict={'size':14,'color':'r'})

1、入職人數在月均入職人數1129人附近上下波動。
2、入職人數最多為6月份,共入職1468人,而入職人數最少為2月,其次為4月。
六、總結
1、從數據集所涵蓋數據中,樣本數量為13546,涵蓋67個單位,1034個職位的數據,樣本類別分布是否均衡未知。
2、美國巴爾的摩2016年公務員人均年薪為53507.98美元,其公務員高工資的職位較少,公務員年薪普遍集中在4-8萬美元之間,最高年薪達到15萬美元。
3、其中年薪最高的TOP3職位分別為州檢察官,警察局長和執(zhí)行董事;而人數最多TOP3職位則分別為警務人員,小時勞工和EMT消防員。
4、其入職人數最多為6月份,入職人數最少為2月和4月。