实战项目:物流行业数据分析

1、数据来源:某企业销售的6中商品所对应的送货及用户反馈数据

解决问题:

  1. 配送服务是否存在问题
  2. 是否存在有潜力的销售区域
  3. 商品是否存在质量问题

结论

  1. 货品4-西北,货品2-马来西亚,这两条线路存在较大问题,急需提升时效

  2. 货品2在华东地区还有较大的市场空间,适合加大投入;同时货品2在西北配送时效长,用户拒收率高,从成本角度考虑,应该减少投入

  3. 货品1、2、4质量存在问题,建议扩大抽检范围,增大质检力度

2、分析过程如下

一、数据清洗

  1. 重复值、缺失值、格式调整
  2. 异常值处理(比如:销售金额存在等于0的,属于异常)

二、数据规整
比如:增加一项辅助列:月份

三、数据分析并可视化

import os
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = 'SimHei'  ##显示中文字符

一、数据清洗

  1. 重复值、缺失值、格式调整
data = pd.read_csv('./Data/wuliu_data1/data_wuliu.csv', encoding='gbk')#encoding='utf-8'获取失败
data.info()   
---  ------  --------------  -----  
 0   订单号     1159 non-null   object 
 1   订单行     1161 non-null   int64  
 2   销售时间    1161 non-null   object 
 3   交货时间    1161 non-null   object 
 4   货品交货状况  1159 non-null   object 
 5   货品      1161 non-null   object 
 6   货品用户反馈  1161 non-null   object 
 7   销售区域    1161 non-null   object 
 8   数量      1157 non-null   float64
 9   销售金额    1161 non-null   object 

通过info()可以看出,包含10列数据,名字、数据量、格式等,可以得出:

  1. 订单号、货品交货情况、数量:存在缺失值,但是缺失量不大,可以删除
  2. 订单行,对分析无关紧要,没有实质意义,可以考虑删除
  3. 销售金额格式有问题(万元|元,逗号问题),数据类型需要转换为int|float
#删除重复记录,遇到重复保留第一行,删除后代替源数据
data.drop_duplicates(keep='first',inplace=True)
#删除缺失值(有na的整行数据,axis=0,how='any'默认)
data.dropna(axis=0,how='any',inplace=True)
#删除‘订单行’这一列:第二次运行删除操作会报错
data.drop(columns=['订单行'],inplace=True,axis=1)
#更新索引:drop=True:把原来的索引index列删除,重置index,原来的索引因为删除了行数据变乱
data.reset_index(drop=True,inplace=True)
data
订单号销售时间交货时间货品交货状况货品货品用户反馈销售区域数量销售金额
0P0963112016-7-302016-9-30晚交货货品3质量合格华北2.01052,75元
1P0968262016-8-302016-10-30按时交货货品3质量合格华北10.011,50万元
2P0974352016-7-302016-9-30按时交货货品1返修华南2.06858,77元
3P0974462016-11-262017-1-26晚交货货品3质量合格华北15.0129,58元
4P0974462016-11-262017-1-26晚交货货品3拒货华北15.032,39元
..............................
1141P2999012016-12-152017-3-15按时交货货品6质量合格马来西亚2.0200,41元
1142P3029562016-12-222017-3-22按时交货货品2拒货华东20.079,44元
1143P3038012016-12-152017-3-15按时交货货品2质量合格华东1.0194,08元
1144P3072762016-12-222017-3-22按时交货货品6质量合格马来西亚1.032,18元
1145P3141652016-12-202017-3-20按时交货货品2质量合格华东1.01720,92元

1146 rows × 9 columns

#取出‘销售金额’列,对每个数据进行清洗,自定义map函数处理万元|元
#如果python已知函数不能满足我们的需求,就使用自定义函数:map、apply
#编写自定义过滤函数:1.删除逗号,2.转成float:如果是万元则删除万元再*10000;否则,删除元
def data_deal(number):
    if number.find('万元') != -1:#找到带有万元的,取出数字,去掉逗号,转成float,*10000
        #number[:number.find('万元')]去掉万元
        #number[:,number.find('万元')].replace(',','')将逗号替换为空
        number_new = float(number[:number.find('万元')].replace(',',''))*10000
        pass
    else: #找到带有元的,删除元,删除逗号,转成float
        if number.find('元') != -1:
            number_new = float(number.replace('元','').replace(',',''))
        pass
    return number_new

data['销售金额'] = data['销售金额'].map(data_deal)
data
订单号销售时间交货时间货品交货状况货品货品用户反馈销售区域数量销售金额
0P0963112016-7-302016-9-30晚交货货品3质量合格华北2.0105275.0
1P0968262016-8-302016-10-30按时交货货品3质量合格华北10.011500000.0
2P0974352016-7-302016-9-30按时交货货品1返修华南2.0685877.0
3P0974462016-11-262017-1-26晚交货货品3质量合格华北15.012958.0
4P0974462016-11-262017-1-26晚交货货品3拒货华北15.03239.0
..............................
1141P2999012016-12-152017-3-15按时交货货品6质量合格马来西亚2.020041.0
1142P3029562016-12-222017-3-22按时交货货品2拒货华东20.07944.0
1143P3038012016-12-152017-3-15按时交货货品2质量合格华东1.019408.0
1144P3072762016-12-222017-3-22按时交货货品6质量合格马来西亚1.03218.0
1145P3141652016-12-202017-3-20按时交货货品2质量合格华东1.0172092.0

1146 rows × 9 columns

  1. 异常值处理
data.describe()
数量销售金额
count1146.0000001.146000e+03
mean76.0693721.223488e+05
std589.4164861.114599e+06
min1.0000000.000000e+00
25%1.0000002.941500e+03
50%1.0000009.476500e+03
75%4.0000003.576775e+04
max11500.0000003.270000e+07
  • 销售金额最小值为0,有异常值
#1.销售金额==0,采用删除方法,因为数据量很小
data = data[data['销售金额']!=0]
data.describe()
#2.销售金额和数量存在严重的右偏现象,在电商领域2/8法则:20%的人贡献了80%的效率,少数人贡献了大多数的订单
#  很正常,无需处理
数量销售金额
count1145.0000001.145000e+03
mean76.1349341.224557e+05
std589.6698611.115081e+06
min1.0000005.100000e+01
25%1.0000002.946000e+03
50%1.0000009.486000e+03
75%4.0000003.577300e+04
max11500.0000003.270000e+07

二、数据规整

  • 增加一项辅助列:月份

    • 配送服务是否存在问题——每个月配送服务的满意度
    • 是否存在尚有潜力的销售区域——根据月份绘制本月销售量的图,看月份和销售量的关系
  • 在数据中,从销售时间里提取月份,两种方法:

    • 字符串截取:.substr(data[‘销售时间’,6,2])
    • 将该列转化为datetime格式,直接month提取月份。
data['销售时间'] = pd.to_datetime(data['销售时间'])
data['月份'] = data['销售时间'].apply(lambda x: x.month)
data
订单号销售时间交货时间货品交货状况货品货品用户反馈销售区域数量销售金额月份
0P0963112016-07-302016-9-30晚交货货品3质量合格华北2.0105275.07
1P0968262016-08-302016-10-30按时交货货品3质量合格华北10.011500000.08
2P0974352016-07-302016-9-30按时交货货品1返修华南2.0685877.07
3P0974462016-11-262017-1-26晚交货货品3质量合格华北15.012958.011
4P0974462016-11-262017-1-26晚交货货品3拒货华北15.03239.011
.................................
1141P2999012016-12-152017-3-15按时交货货品6质量合格马来西亚2.020041.012
1142P3029562016-12-222017-3-22按时交货货品2拒货华东20.07944.012
1143P3038012016-12-152017-3-15按时交货货品2质量合格华东1.019408.012
1144P3072762016-12-222017-3-22按时交货货品6质量合格马来西亚1.03218.012
1145P3141652016-12-202017-3-20按时交货货品2质量合格华东1.0172092.012

1145 rows × 10 columns

三、数据分析并可视化

1. 配送服务是否存在问题——按时交货率

  • 月份维度
  • 销售区域维度
  • 货品维度
  • 货品和销售区域维度
a.月份维度分析按时交货率
#有的‘货品交货状况’内容,开头含有空格,需要删除首位空格 **.strip()**
data['货品交货状况'] = data['货品交货状况'].str.strip()
data1 = data.groupby(['月份','货品交货状况']).size().unstack()#按月份和货币交货状况分类,.size()计算数量
#.unstack() 可以使输出表格更直观,方便后面计算
data1['按时交货率'] = data1['按时交货']/ (data1['按时交货']+data1['晚交货'])
data1
货品交货状况按时交货晚交货按时交货率
月份
7189130.935644
8218350.861660
912290.931298
10238310.884758
11101250.801587
12146180.890244
  • 分析结果:从按时交货率来看,第四季度低于第三季度,猜测可能是气候原因造成的
b.销售区域维度分析按时交货率
data2 = data.groupby(['销售区域','货品交货状况']).size().unstack()
data2['按时交货率'] = data2['按时交货']/ (data2['按时交货']+data2['晚交货'])
print(data1.sort_values(by='按时交货率', ascending=False))
货品交货状况  按时交货  晚交货     按时交货率
月份                         
7        189   13  0.935644
9        122    9  0.931298
12       146   18  0.890244
10       238   31  0.884758
8        218   35  0.861660
11       101   25  0.801587
  • 分析结果:西北存在突出的延时交货问题,急需解决
c.货品维度分析按时交货率
data3 = data.groupby(['货品', '货品交货状况']).size().unstack()
data3['按时交货率'] = data3['按时交货'] / (data3['按时交货']+data3['晚交货'])
print(data3.sort_values(by='按时交货率', ascending=False))
货品交货状况  按时交货  晚交货     按时交货率
货品                         
货品5      183    4  0.978610
货品6      309    7  0.977848
货品1       27    2  0.931034
货品3      212   26  0.890756
货品2      269   48  0.848580
货品4       14   44  0.241379
  • 分析结果:货品4晚交货非常严重,其余货品相对正常
d.货品和销售区域结合分析按时交货率
data4 = data.groupby(['货品','销售区域','货品交货状况']).size().unstack()
data4['按时交货率'] = data4['按时交货'] / (data4['按时交货']+data4['晚交货'])
print(data4.sort_values(by='按时交货率',ascending=False))
货品交货状况     按时交货   晚交货     按时交货率
货品  销售区域                       
货品5 泰国    183.0   4.0  0.978610
货品6 马来西亚  309.0   7.0  0.977848
货品1 华北     14.0   1.0  0.933333
    华南     10.0   1.0  0.909091
货品3 华北    212.0  26.0  0.890756
货品2 华东    268.0  39.0  0.872964
货品4 西北     14.0  44.0  0.241379
货品2 马来西亚    1.0   9.0  0.100000
货品1 西北      3.0   NaN       NaN
  • 分析结果:

销售区域:最差在西北地区,货品有1和4,主要是货品4送货过晚导致的;

货品角度:最差的是货品2,主要送往华东和马来西亚,主要是马来西亚的送货较晚导致。

2. 是否存在尚有潜力的销售区域——货品的销售数量

  • 月份维度
  • 销售区域维度
  • 月份和销售区域维度
a.月份维度分析货品销售数量
  • 每个月,每个商品的销售情况
data1 = data.groupby(['月份','货品'])['数量'].sum().unstack()
data1
data1.plot(kind='line')
<AxesSubplot:xlabel='月份'>

在这里插入图片描述

  • 结果分析:货品2在10月和12月份,销量猛增。原因猜测有二:1。公司加大营销力度 2.开发了新的市场(在研究区域维度确定)
b. 销售区域维度分析货品销售数量
data2 = data.groupby(['货品', '销售区域'])['数量'].sum().unstack()
data2
销售区域华东华北华南泰国西北马来西亚
货品
货品1NaN2827.0579.0NaN11.0NaN
货品253811.0NaNNaNNaNNaN1510.0
货品3NaN9073.5NaNNaNNaNNaN
货品4NaNNaNNaNNaN5229.0NaN
货品5NaNNaNNaN5733.0NaNNaN
货品6NaNNaNNaNNaNNaN8401.0
  • 结果分析:从销售区域看,每种货品销售区域为1~3个,货品1有3个销售区域,货品2有两个销售区域,其余货品均有1个销售区域
c. 月份和销售区域
data3 = data.groupby(['月份','销售区域','货品'])['数量'].sum().unstack() 
data3['货品2'].unstack() #只能查看最后分组的指标
销售区域华东华北华南泰国西北马来西亚
月份
7489.0NaNNaNNaNNaN2.0
81640.0NaNNaNNaNNaN1503.0
93019.0NaNNaNNaNNaN1.0
1028420.0NaNNaNNaNNaNNaN
112041.0NaNNaNNaNNaN1.0
1218202.0NaNNaNNaNNaN3.0
  • 结果分析:
    1.前面遇到的问题,货品2在10月和12月份销量激增,还是发生在原有销售区域(华东),没有扩展新的销路
    2.同样,分析出在7,8,9,11月份销量数量还有很大提升空间,需要适当加大营销力度。

3. 商品是否存在质量问题——货品用户反馈

  • 月份维度
  • 销售区域维度
  • 月份和销售区域维度

注:字符串字段记得在统计之前删除首位空格,.str.strip()

a. 从货品和销售地区维度进行分析
data['货品用户反馈'] = data['货品用户反馈'].str.strip()  #取出首位空格
data1 = data.groupby(['货品', '销售区域'])['货品用户反馈'].value_counts().unstack()
# 计算拒收率
data1['拒货率'] = data1['拒货'] / data1.sum(axis=1)#按行进行求和汇总
data1['返修率'] = data1['返修'] / data1.sum(axis=1)
data1['合格率'] = data1['质量合格'] / data1.sum(axis=1)
data1.sort_values(['合格率', '返修率', '拒货率'], ascending=False)#先按合格率排序,再按返修率,拒货率; 降序
货品用户反馈拒货质量合格返修拒货率返修率合格率
货品销售区域
货品3华北31.0188.019.00.1302520.0797880.789219
货品6马来西亚56.0246.014.00.1772150.0442790.777936
货品5泰国14.0144.029.00.0748660.1550180.769108
货品2华东72.0184.051.00.2345280.1659970.598568
货品1华南5.04.02.00.4545450.1746030.343963
西北NaN1.02.0NaN0.6666670.272727
华北NaN3.012.0NaN0.8000000.189873
货品4西北NaN9.049.0NaN0.8448280.152945
货品2马来西亚6.01.03.00.6000000.2830190.091886
data1
货品用户反馈拒货质量合格返修拒货率返修率合格率
货品销售区域
货品1华北NaN3.012.0NaN0.8000000.189873
华南5.04.02.00.4545450.1746030.343963
西北NaN1.02.0NaN0.6666670.272727
货品2华东72.0184.051.00.2345280.1659970.598568
马来西亚6.01.03.00.6000000.2830190.091886
货品3华北31.0188.019.00.1302520.0797880.789219
货品4西北NaN9.049.0NaN0.8448280.152945
货品5泰国14.0144.029.00.0748660.1550180.769108
货品6马来西亚56.0246.014.00.1772150.0442790.777936

结果分析:

  • 货品3,6,5合格率均较高,返修率比较低,说明质量还可以

  • 货品1,2,4合格率较低,返修率较高,质量存在一定问题,需要改善

  • 货品2在马来西亚的拒货率较高,结合按时收货率来看,货品2在马来西亚的按时收货率也很低——可以猜测马来西亚人对货品的时效性要求较高,如果达不到,则往往考虑拒绝收货。

  • 那么是否要减小对马来西亚的投入呢?增大对华东地区的投入?

    • 考虑到货品2主要在华东地区销售量大,可以考虑增大在华东地区的投资,适当减小对马来西亚的投入
  • 4
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 15
    评论
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值