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


    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
    • 2
    • 3
    • 4
    • 5

    一、数据清洗

    1. 重复值、缺失值、格式调整
    data = pd.read_csv('./Data/wuliu_data1/data_wuliu.csv', encoding='gbk')#encoding='utf-8'获取失败
    data.info()   
    
    • 1
    • 2
    ---  ------  --------------  -----  
     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 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    通过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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    订单号销售时间交货时间货品交货状况货品货品用户反馈销售区域数量销售金额
    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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    data
    
    • 1
    订单号销售时间交货时间货品交货状况货品货品用户反馈销售区域数量销售金额
    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()
    
    • 1
    数量销售金额
    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%的效率,少数人贡献了大多数的订单
    #  很正常,无需处理
    
    • 1
    • 2
    • 3
    • 4
    • 5
    数量销售金额
    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)
    
    • 1
    • 2
    data
    
    • 1
    订单号销售时间交货时间货品交货状况货品货品用户反馈销售区域数量销售金额月份
    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()
    
    • 1
    • 2
    data1 = data.groupby(['月份','货品交货状况']).size().unstack()#按月份和货币交货状况分类,.size()计算数量
    #.unstack() 可以使输出表格更直观,方便后面计算
    data1['按时交货率'] = data1['按时交货']/ (data1['按时交货']+data1['晚交货'])
    data1
    
    • 1
    • 2
    • 3
    • 4
    货品交货状况按时交货晚交货按时交货率
    月份
    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))
    
    • 1
    • 2
    • 3
    货品交货状况  按时交货  晚交货     按时交货率
    月份                         
    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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 分析结果:西北存在突出的延时交货问题,急需解决
    c.货品维度分析按时交货率
    data3 = data.groupby(['货品', '货品交货状况']).size().unstack()
    data3['按时交货率'] = data3['按时交货'] / (data3['按时交货']+data3['晚交货'])
    print(data3.sort_values(by='按时交货率', ascending=False))
    
    • 1
    • 2
    • 3
    货品交货状况  按时交货  晚交货     按时交货率
    货品                         
    货品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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 分析结果:货品4晚交货非常严重,其余货品相对正常
    d.货品和销售区域结合分析按时交货率
    data4 = data.groupby(['货品','销售区域','货品交货状况']).size().unstack()
    data4['按时交货率'] = data4['按时交货'] / (data4['按时交货']+data4['晚交货'])
    print(data4.sort_values(by='按时交货率',ascending=False))
    
    • 1
    • 2
    • 3
    货品交货状况     按时交货   晚交货     按时交货率
    货品  销售区域                       
    货品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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 分析结果:

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

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

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

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

    在这里插入图片描述

    • 结果分析:货品2在10月和12月份,销量猛增。原因猜测有二:1。公司加大营销力度 2.开发了新的市场(在研究区域维度确定)
    b. 销售区域维度分析货品销售数量
    data2 = data.groupby(['货品', '销售区域'])['数量'].sum().unstack()
    data2
    
    • 1
    • 2
    销售区域华东华北华南泰国西北马来西亚
    货品
    货品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() #只能查看最后分组的指标
    
    • 1
    • 2
    销售区域华东华北华南泰国西北马来西亚
    月份
    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()  #取出首位空格
    
    • 1
    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)#先按合格率排序,再按返修率,拒货率; 降序
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    货品用户反馈拒货质量合格返修拒货率返修率合格率
    货品销售区域
    货品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
    货品用户反馈拒货质量合格返修拒货率返修率合格率
    货品销售区域
    货品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主要在华东地区销售量大,可以考虑增大在华东地区的投资,适当减小对马来西亚的投入
  • 相关阅读:
    【设计模式】适配器模式:攻敌三分,自留七分,以超兽武装的例子来谈谈适配器模式
    torch.cuda.is_available() 解决方案
    计算机毕业设计选什么题目好?springboot 旅游网站
    gin框架初识
    【JVS低代码开发平台】支持纯手工配置的数据加工、处理、展现的数据仓库
    SqlServer_idea连接问题
    Zookeeper初步
    【Python深度学习】Python全栈体系(三十二)
    vue的内置指令、vue生命周期、自定义(过滤器、指令、插件)、非单文件组件
    知识产权贯标适合哪些企业做?
  • 原文地址:https://blog.csdn.net/S1406793/article/details/127797048