Python数据分析第5天 - 深入浅出pandas¶

In [19]:
# %load hello.py
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

plt.rcParams['font.sans-serif'].insert(0, 'SimHei')
plt.rcParams['axes.unicode_minus'] = False
%config InlineBackend.figure_format = 'svg'
In [3]:
jobs = pd.read_csv('wenjian/new_jobs.csv')
In [8]:
print(f"""
招聘信息:{jobs.job_name.count()}
职位数量:{jobs.pos_count.sum()}
平均薪资:{jobs.salary.mean().round(2)}
城市数量:{jobs.city.nunique()}
""")
招聘信息:3822
职位数量:13483
平均薪资:16.98
城市数量:9

In [18]:
temp0 = jobs.groupby('city').pos_count.agg(['sum','max','count'])   # groupby分组
In [20]:
temp0.sort_values(by='sum',ascending=False,inplace=True)  # ascending 从小到大排序  
In [19]:
temp0
Out[19]:
sum max count
city
上海 2151 6 589
北京 2067 6 584
南京 1291 6 371
广州 1611 6 460
成都 911 6 248
杭州 1774 6 517
武汉 947 6 273
深圳 2092 6 607
西安 639 6 173
In [21]:
temp1 = jobs.groupby('city').pos_count.sum()
In [22]:
temp1.sort_values(ascending=False,inplace=True)
temp1
Out[22]:
city
上海    2151
深圳    2092
北京    2067
杭州    1774
广州    1611
南京    1291
武汉     947
成都     911
西安     639
Name: pos_count, dtype: int64
In [51]:
plt.cm.summer
Out[51]:
summer
summer colormap
under
bad
over
In [57]:
index = np.linspace(0.25,0.95,9)
colors = plt.cm.summer(index)
In [61]:
temp1.plot(
    figsize =(8,5),
    kind='bar',
    xlabel='',
    color=colors,
    title="每个城市的岗位数量"
)
plt.ylim(0,2500)
plt.xticks(rotation=0)

for i in range(temp1.size):
    plt.text(i,temp1.iloc[i]+20,temp1.iloc[i],ha='center')

plt.show()
No description has been provided for this image
In [79]:
temp2 =jobs.groupby('city').salary.agg(['mean','max','min']).round(1)
temp2.rename(columns={'mean':'平均薪资','max':'最高薪资','min':'最低薪资'},inplace=True)
temp2.sort_values(by='平均薪资',ascending=False,inplace=True)
In [80]:
temp2.plot(
    figsize =(8,4),
    kind='bar',
    y='平均薪资',
    color=plt.cm.Oranges(index),
    title='每个城市的平均薪资',
    legend=False,
    xlabel='',
)
plt.ylim(0,25)
plt.xticks(rotation=0)

avg_salary = temp2.平均薪资
for i in range(avg_salary.size):
    plt.text(i,avg_salary.iloc[i]+0.3,avg_salary.iloc[i],ha='center')

plt.show()
No description has been provided for this image
In [ ]:
#统计不同学历 岗位数量占比
In [83]:
temp3 = jobs.groupby('edu').pos_count.sum()
In [93]:
temp3.plot(
    figsize=(5,5),
    kind='pie',
    ylabel='',
    autopct='%.2f%%',             #自动计算并显示百分比格式
    pctdistance=0.85,             #距离圆心的距离 
    wedgeprops={'width':0.38}     #变成环状饼图
)
plt.show()
No description has been provided for this image
In [ ]:
#工作年限占比
In [96]:
temp4 = jobs.groupby('year').pos_count.sum()
temp4
Out[96]:
year
1-3年    3851
1年以内     635
3-5年    5122
5年以上    1549
应届生      277
经验不限    2049
Name: pos_count, dtype: int64
In [97]:
temp4.plot(
    figsize=(5,5),
    kind='pie',
    ylabel='',
    autopct='%.2f%%',             #自动计算并显示百分比格式
    pctdistance=0.85,             #距离圆心的距离 
    wedgeprops={'width':0.38}     #变成环状饼图
)
plt.show()
No description has been provided for this image
In [105]:
keywords = input('请输入公司名称:')
jobs[jobs.company_name.str.contains(keywords)][['city','company_name','salary','year','edu']].rename(
    columns={'company_name':'公司名称','salary':'工资','year':'工作年限','edu':'学历','city':'城市'}
).sort_values(by=['城市','工资'],ascending=[True,False])
Out[105]:
城市 公司名称 工资 工作年限 学历
2248 上海 通联数据 27.5 3-5年 本科
2271 上海 达观数据 25.0 3-5年 本科
2251 上海 达观数据 22.5 经验不限 本科
2385 上海 上海源石数据 22.5 3-5年 大专
2750 上海 哈步数据 22.5 3-5年 本科
... ... ... ... ... ...
2874 深圳 惠群商业数据 7.0 1年以内 本科
3281 深圳 前海数据 4.0 应届生 本科
3789 西安 廷山大数据 9.5 经验不限 本科
3746 西安 熊赳赳数据科技 4.5 经验不限 学历不限
3777 西安 麦仓数据 4.5 经验不限 大专

90 rows × 5 columns

In [119]:
jobs['year'] = jobs.year.astype('category').cat.reorder_categories(
    ['应届生','1年以内','经验不限','1-3年','3-5年','5年以上'])
jobs['edu'] = jobs.edu.astype('category').cat.reorder_categories(
    ['学历不限','大专','本科','研究生'])
In [ ]:
temp5 = jobs.groupby(['edu','year'],as_index=False).salary.mean().round(1)
#temp5.pivot(index='edu',columns='year',values='salary')
pd.pivot(temp5,index='edu',columns='year',values='salary')
In [129]:
temp6 = jobs.pivot_table(
    index='edu',
    columns='year',
    values='salary',
    aggfunc='mean',
    observed=True,
    fill_value=0
).round(1)
temp6
Out[129]:
year 应届生 1年以内 经验不限 1-3年 3-5年 5年以上
edu
学历不限 11.5 6.0 11.0 11.7 17.7 20.8
大专 6.7 7.0 7.4 9.5 15.6 26.2
本科 7.0 9.0 12.4 13.4 20.9 28.1
研究生 8.3 13.5 15.4 17.9 25.9 31.3
In [154]:
plt.imshow(
    temp6,
    cmap='Greens'
)
plt.xticks(np.arange(6),labels=temp6.columns)
plt.yticks(np.arange(4),labels=temp6.index)
ref_vales = np.quantile(temp6.values,0.75)

for x in range(temp6.index.size):
    for y in range(temp6.columns.size):
        value = temp6.iat[x,y]
        color = 'white' if value > ref_vales else 'black'  #判断值给不同的颜色
        plt.text(y,x,value,ha='center',va='center',color=color)
plt.colorbar()
plt.show()
No description has been provided for this image
In [150]:
import seaborn as sns
In [156]:
sns.heatmap(
    temp6,
    cmap='Greens',
    annot=True,
    fmt='.1f'
           
)
plt.xlabel('')
plt.ylabel('')
plt.yticks(rotation=0)
plt.show()
No description has been provided for this image

案例 2020销售数据¶

In [7]:
def make_tag(price):
    if price < 300 :return '低端'
    elif price < 800 :return '中端'
    return '高端'
In [30]:
data = pd.read_excel('wenjian/2020年销售数据.xlsx',sheet_name='data')
data
Out[30]:
销售日期 销售区域 销售渠道 销售订单 品牌 售价 销售数量 直接成本 销售代表
0 2020-01-01 上海 拼多多 200101007627 八匹马 99 83 3351 S00982
1 2020-01-01 上海 抖音 200101005623 八匹马 219 29 1016 S00871
2 2020-01-01 上海 天猫 200101004554 八匹马 169 85 6320 S00871
3 2020-01-01 上海 天猫 200101009600 八匹马 169 14 485 S00272
4 2020-01-01 上海 天猫 200101007986 皮皮虾 249 61 2452 S00272
... ... ... ... ... ... ... ... ... ...
1940 2020-12-30 北京 京东 201230004052 花花姑娘 269 26 1560 S00344
1941 2020-12-30 福建 实体 201230007101 八匹马 79 97 3028 S00677
1942 2020-12-31 福建 实体 201231009600 花花姑娘 269 55 2277 S00604
1943 2020-12-31 福建 抖音 201231003362 八匹马 59 59 852 S00272
1944 2020-12-31 福建 天猫 201231003844 八匹马 99 27 435 S00272

1945 rows × 9 columns

In [122]:
reps = pd.read_excel('wenjian/2020年销售数据.xlsx',sheet_name='reps')
sx = pd.merge(data,reps,how='inner',left_on='销售代表',right_on='工号')
sx['销售额'] = sx.售价 * sx.销售数量
sx['毛利润'] = sx.销售额 - sx.直接成本
sx['价位'] = sx.售价.map(make_tag).astype('category').cat.reorder_categories(
    ['低端','中端','高端'])
sx['月份'] = sx.销售日期.dt.strftime('%m月')
#sx.drop(columns='工号',inplace=True)
sx.head(3)
Out[122]:
销售日期 销售区域 销售渠道 销售订单 品牌 售价 销售数量 直接成本 销售代表 工号 姓名 销售额 毛利润 价位 月份
0 2020-01-01 上海 拼多多 200101007627 八匹马 99 83 3351 S00982 S00982 李欢 8217 4866 低端 01月
1 2020-01-01 上海 抖音 200101005623 八匹马 219 29 1016 S00871 S00871 刘旭 6351 5335 低端 01月
2 2020-01-01 上海 天猫 200101004554 八匹马 169 85 6320 S00871 S00871 刘旭 14365 8045 低端 01月
In [ ]:
# 统计销售额,毛利润,毛利率,订单数量,销售数量,AOV,人效
In [38]:
总销售额 = sx.销售额.sum()
毛利润 = sx.毛利润.sum()
毛利率 = 毛利润/总销售额
总订单数量 = sx.销售订单.nunique()
总销售数量 = sx.销售数量.sum()
AOV = 总销售额 / 总订单数量
人效 = 总销售额 / sx.销售代表.nunique()
In [42]:
print(f'''
总销售额 = ¥{总销售额:,}元
毛利润 = ¥{毛利润:,}元
毛利率 = {毛利率:.2%}
总订单数量 = {总订单数量:,}单
总销售数量 = {总销售数量:,}件
AOV = ¥{AOV:,.0f}元
人效 = ¥{人效:,.0f}元
''')
总销售额 = ¥39,772,087元
毛利润 = ¥27,926,715元
毛利率 = 70.22%
总订单数量 = 1,940单
总销售数量 = 107,403件
AOV = ¥20,501元
人效 = ¥2,840,863元

In [ ]:
#统计每个月的销售额和月环比
In [45]:
temp1 = sx.groupby('月份').销售额.sum().to_frame()
temp1['月环比'] = temp1.销售额.pct_change()
temp1.style.format(
    formatter={
        '销售额':'{:,}',
        '月环比':'{:.2%}'
    },
    na_rep='-----'
).background_gradient(cmap='Reds')
Out[45]:
  销售额 月环比
月份    
01月 5,409,855 -----
02月 4,608,455 -14.81%
03月 4,164,972 -9.62%
04月 3,996,770 -4.04%
05月 3,239,005 -18.96%
06月 2,817,936 -13.00%
07月 3,501,304 24.25%
08月 2,948,189 -15.80%
09月 2,632,960 -10.69%
10月 2,375,385 -9.78%
11月 2,385,283 0.42%
12月 1,691,973 -29.07%
In [ ]:
 
In [81]:
temp1.plot(
    figsize =(10,4.5),   #图表尺寸
    kind='line',         #类型
    y='销售额',          #Y轴数据
    xlabel='',           #X轴标签
    legend=False,        #图例
    title='每个月份销售额', 
    marker='>',
    linestyle='--'         #线条样式
)
plt.ylim(0,6000000)
plt.ticklabel_format(axis='y',style='plain')
plt.xticks(np.arange(12),labels=temp1.index)
plt.grid(axis='y',linestyle='--',alpha=0.25)

y1= temp1.销售额
y2= temp1.月环比
for x in range(1,y2.size):
    plt.text(x,y1.iloc[x]+200000,f'{y2.iloc[x]:.2%}',ha='center')
plt.show()
No description has been provided for this image
In [ ]:
#统计各品牌销售额贡献占比
In [87]:
temp2 = sx.groupby('品牌').销售额.sum()
temp2
Out[87]:
品牌
八匹马      5334646
啊哟喂       693159
壁虎       4678979
皮皮虾      7892271
花花姑娘    21173032
Name: 销售额, dtype: int64
In [108]:
temp2.plot(
    figsize=(5,5),
    kind='pie',
    ylabel='',
    autopct='%.2f%%',
    pctdistance=0.82,
    explode=[0,0,0,0.1,0],
    wedgeprops={'width':0.38,'edgecolor':'w'}
)
plt.show()
No description has been provided for this image
In [86]:
temp3 = sx.groupby('销售渠道').销售额.sum()
temp3
Out[86]:
销售渠道
京东      7694468
天猫     13711818
实体      5194293
抖音      4782905
拼多多     8388603
Name: 销售额, dtype: int64
In [90]:
temp3.plot(
    figsize=(5,5),
    kind='pie',
    ylabel='',
    autopct='%.2f%%',
    pctdistance=0.82,
    wedgeprops={'width':0.38}
)
plt.show()
No description has been provided for this image
In [111]:
#统计各销售区域月度销售额
temp4 = pd.pivot_table(
    sx,
    index='销售区域',
    columns='月份',
    values='销售额',
    aggfunc='sum',
    fill_value=0,
    # margins=True,    #小计
    # margins_name= '总计' #小计改名字
)
In [119]:
temp4.T.plot(
    figsize=(8,4),
    kind='bar',
    stacked=True,
    xlabel="",
)
plt.xticks(rotation=0)
plt.show()
No description has been provided for this image
In [ ]:
# 统计各渠道各品牌的销售数量
In [141]:
temp5=pd.pivot_table(
    sx,
    index='销售渠道',
    columns='品牌',
    values='销售数量',
    aggfunc='sum',
    observed=True
    
)
temp6 = temp5.div(temp5.sum(axis=1),axis=0)
temp6.plot(
    kind='bar',
    stacked=True
)
plt.xticks(rotation=0)
plt.show()
No description has been provided for this image
In [ ]:
# 统计各价位产品每个月的销售数量
In [128]:
temp6=pd.pivot_table(
    sx,
    index='价位',
    columns='月份',
    values='销售数量',
    aggfunc='sum',
    observed=True
)
temp6.T.plot(
    figsize=(8,4),
    kind='line',
    stacked=True,
    xlabel="",
)
plt.xticks(rotation=0)
plt.show()
No description has been provided for this image
In [ ]:
# 统计业绩最好的三个销售代表 (TOP N)
In [157]:
temp7 = sx.groupby(['销售代表','姓名']).销售额.sum().to_frame()
#temp7.sort_values(ascending=False).head(3)
temp7.nlargest(3,'销售额').reset_index(level=1).style.hide()  #最大的N个  
Out[157]:
姓名 销售额
李华志 3860877
王梅梅 3592423
刘旭 3515728
In [ ]:
# 统计每个月业绩最好的三个销售代表 
In [182]:
# temp8 = sx.groupby(['月份','销售代表','姓名']).销售额.sum()
# temp8.groupby('月份').nlargest(3)

temp8 = sx.groupby(['月份','销售代表','姓名']).销售额.sum().to_frame()
temp8['排名'] = temp8.groupby('月份').rank('dense',ascending=False).astype('i8')
temp8.query('排名 <=3').reset_index().sort_values(by=['月份','排名']).set_index(['月份'])
Out[182]:
销售代表 姓名 销售额 排名
月份
01月 S00710 李华志 675065 1
01月 S00604 赵治国 652302 2
01月 S00871 刘旭 558124 3
02月 S00710 李华志 740887 1
02月 S00169 冯兰 517864 2
02月 S00133 王梅梅 435794 3
03月 S00757 王默 449747 1
03月 S00169 冯兰 402668 2
03月 S00982 李欢 390944 3
04月 S00677 李平 537014 1
04月 S00344 张彩 445697 2
04月 S00133 王梅梅 411993 3
05月 S00677 李平 592075 1
05月 S00133 王梅梅 417171 2
05月 S00710 李华志 294061 3
06月 S00757 王默 429097 1
06月 S00169 冯兰 290356 2
06月 S00378 蔡中平 273828 3
07月 S00272 周小敏 556611 1
07月 S00133 王梅梅 432678 2
07月 S00710 李华志 412358 3
08月 S00363 吴国华 322931 1
08月 S00604 赵治国 317701 2
08月 S00169 冯兰 310072 3
09月 S00272 周小敏 350258 1
09月 S00871 刘旭 327426 2
09月 S00133 王梅梅 289976 3
10月 S00272 周小敏 309373 1
10月 S00169 冯兰 226022 2
10月 S00871 刘旭 224994 3
11月 S00188 杨明轩 345742 1
11月 S00344 张彩 265178 2
11月 S00871 刘旭 238296 3
12月 S00871 刘旭 238091 1
12月 S00363 吴国华 227479 2
12月 S00378 蔡中平 208448 3