数据分析——快递电商

一、任务目标

1、任务

总体目的------对账

本项目解决同时使用多个快递发货,部分隔离区域出现不同程度涨价等情形下,如何快速准确核对账单的问题。

1、在订单表中新增一列【运费差异核对】来表示订单运费实际有多少差异,结果为数值。

2、将整个核对过程包装为一个OrderCheck类,方便后续直接调用它进行数据核对。

二、数据形式

1、图像呈现

账单形式

邮寄费(不同公司)

2、文字描述

一个excel文件中有四个表,第一张是账单形式,后面是不同公司的计费方式

每个公司的信息不同(如送达地址的描述、包裹重量单位等),需要统一

三、分析步骤

1、导入数据

3.1.1存在问题

问题一:

由于原数据表中有空格,或最后有总计、数据源等不规则信息导致的,需要进行处理

问题二:

用describe()查看数值信息,发现只有邮资是纯数值,则需要对其他属性的数据进行数值转换

本数据源中,理应只有包裹重量和实际邮资是数值

但由于包裹重量的最后一行是单位(整个表最后的统计部分),不能被统计为数值

3.1.2解决方案

1、处理空行和空值

思路1:用loc定位删除空行

缺点:若新加入表,则行索引会改变,定位也就改变了

思路2:删除重复值

因为有三行空值,可先删除重复的空行

缺点:前面有数据的部分也许也会有重复值,容易导致数据缺失

思路3:统计每一行空值,判断需要删除的行

2、数据类型转换

3.1.3

语法扩展

2、数据处理

3.2.1计算运费

方法一:for循环算每一行

分析:根据地区、快递公司、重量计算运费

问题1:地区不统一

每个表的"地区"描述形式不一样

处理1:

1、读入所有表

2、统一各个表的名称

一张表:

reaname(,inplace=True)

多张表:

问题2:内容不统一

每个表省份的内容不一样

处理2:

问题3:单位不统一

每个表首重续重的写法不同,需要统一

处理3:

问题4:时间是object型,而非数值型

不能直接用于时间的比较和计算,需要转换

处理4:

进一步分析

1、取出所需数据

2、计算每一行的运费

一个小问题,关于money的取值

方法二:apply()算某一行

暂未开发

3、数据分析

3.3.1将计算结果放入一个列表

3.3.2将所需数据加入表中

4、封装类

5、运行检查得结论

1、调用

2、检查是否成功

3、数据异常

4、 核对后的数据

5、 存在差异的数据

四、总体代码

python 复制代码
import pandas as pd 
import warnings
warnings.filterwarnings('ignore')
datas = pd.read_excel('./data_check_transport_fee.xlsx', sheet_name=None)
datas.keys()


# 各个表的名称处理
for k in datas.keys():
    datas[k].columns = ['省份' if '省' in i or '地' in i else i for i in datas[k].columns]


# 各个表的省份名称处理 广东省---->广东 
for k in datas.keys():
    datas[k]['省份'] = datas[k]['省份'].str[:2]


#把每张表拿出来
data = datas['账单明细']
st = datas['申通报价']
sf = datas['顺丰报价']
db = datas['德邦报价']


# 空行处理
data = data[data.isna().sum(axis=1)<5]
data.shap


# 筛选有缺失的数据
ind = data.isna().sum(axis=1)>0
data[ind ]


# 包裹在重量转为数值
data['包裹重量'] = data['包裹重量'].astype(float)


# 修改首重续重列名称
st.rename(columns={'首重(1KG)':'首重', '续重(/KG)':'续重'}, inplace=True)
sf.rename(columns={'首重(1kg)':'首重', '续重(1kg)':'续重'}, inplace=True)


# 修改时间格式
data['发货时间'] = pd.to_datetime(data['发货时间'] )


money_list = []
for province,area,ways,weight,times in data[['省份', '区市', '物流方式','包裹重量','发货时间']].values:
    weight = weight/1000 # 重量单位转换
    if ways=='申通快递':
        if weight<=1: # 首重
            money = st.loc[st['省份']==province, '首重']
        else: # 续重
            money = st.loc[st['省份']==province, '首重']+(weight-1)*st.loc[st['省份']==province, '续重']
        if times>pd.to_datetime('2020-03-31') and area=='武汉市':
            money += 0.5
    elif ways=='德邦快递':
        if weight<=1:
            money = db.loc[db['省份']==province, '1公斤']
        elif 1<weight<=2:
            money = db.loc[db['省份']==province, '2公斤']
        elif 2<weight<=3:
            money = db.loc[db['省份']==province, '3公斤']
        elif 3<weight<=4:
            money = db.loc[db['省份']==province, '4公斤']
        elif 4<weight<=5:
            money = db.loc[db['省份']==province, '5公斤']
        else: 
            money = db.loc[db['省份']==province, '5公斤'] + (weight-5)*db.loc[db['省份']==province, '5公斤以上续']
        
    elif ways=='顺丰寄付':
        if weight<=1: # 首重
            money = sf.loc[sf['省份']==province, '首重']
        else: # 续重
            money = sf.loc[sf['省份']==province, '首重']+(weight-1)*sf.loc[sf['省份']==province, '续重']
    else: # 顺丰到付
        money = pd.Series(0)
    try:
        money_list.append(money.values[0])
    except:
        money_list.append(-999)


#把数据加入表中
data['运费差异核对'] = money_list
data['差异'] = data['实际邮资'] - data['运费差异核对']


#定义类和函数
# 定义一OrderCheck, 返回异常数据、核对异常的数据、核对正常数据
class OrderCheck():
    def __init__(self, root):
        self.root = root
        self.data, self.st, self.sf, self.db = self.prepare_data()
        
    def prepare_data(self,):
        datas = pd.read_excel(self.root, sheet_name=None)
        ## 各个表的名称处理
        for k in datas.keys():
            datas[k].columns = ['省份' if '省' in i or '地' in i else i for i in datas[k].columns]
        ## 各个表的省份名称处理 广西壮族自治区-->广西 
        for k in datas.keys():
            datas[k]['省份'] = datas[k]['省份'].str[:2]
        data = datas['账单明细']
        st = datas['申通报价']
        sf = datas['顺丰报价']
        db = datas['德邦报价']
        ## 空行处理
        data = data[data.isna().sum(axis=1)<5]
        ## 包裹在重量转为数值
        data['包裹重量'] = data['包裹重量'].astype(float)
        ## 修改首重续重列名称
        st.rename(columns={'首重(1KG)':'首重', '续重(/KG)':'续重'}, inplace=True)
        sf.rename(columns={'首重(1kg)':'首重', '续重(1kg)':'续重'}, inplace=True)
        # 修改时间格式
        data['发货时间'] = pd.to_datetime(data['发货时间'] )
        return data,st,sf,db
    
    def get_bad_data(self): # 返回异常数据
        # 筛选有缺失的数据
        ind = self.data.isna().sum(axis=1)>0
        return self.data[ind]
        
    def check(self):
        data, st, sf, db = self.prepare_data()
        money_list = []
        for province,area,ways,weight,times in data[['省份', '区市', '物流方式','包裹重量','发货时间']].values:
            weight = weight/1000 # 重量单位转换
            if ways=='申通快递':
                if weight<=1: # 首重
                    money = st.loc[st['省份']==province, '首重']
                else: # 续重
                    money = st.loc[st['省份']==province, '首重']+(weight-1)*st.loc[st['省份']==province, '续重']
                if times>pd.to_datetime('2020-03-31') and area=='武汉市':
                    money += 0.5
            elif ways=='德邦快递':
                if weight<=1:
                    money = db.loc[db['省份']==province, '1公斤']
                elif 1<weight<=2:
                    money = db.loc[db['省份']==province, '2公斤']
                elif 2<weight<=3:
                    money = db.loc[db['省份']==province, '3公斤']
                elif 3<weight<=4:
                    money = db.loc[db['省份']==province, '4公斤']
                elif 4<weight<=5:
                    money = db.loc[db['省份']==province, '5公斤']
                else: 
                    money = db.loc[db['省份']==province, '5公斤'] + (weight-5)*db.loc[db['省份']==province, '5公斤以上续']

            elif ways=='顺丰寄付':
                if weight<=1: # 首重
                    money = sf.loc[sf['省份']==province, '首重']
                else: # 续重
                    money = sf.loc[sf['省份']==province, '首重']+(weight-1)*sf.loc[sf['省份']==province, '续重']
            else: # 顺丰到付
                money = pd.Series(0)
            try:
                money_list.append(money.values[0])
            except:
                money_list.append(-999)
        data['运费差异核对'] = money_list
        data['差异'] = data['实际邮资'] - data['运费差异核对']
        return data 



#调用一下
che = OrderCheck('./data_check_transport_fee.xlsx')

#检查路径和是否成功
che.root 
che.st

#查看异常数据
che.get_bad_data()

#查看核对数据
check_data = che.check()

#查看差异存在的数据
check_data[check_data['差异']==0]

五、总结

5.1难点总结

1、异常值处理

询问业务、手动填补、try

2、名称、内容、单位、数值类型的统一

3、重量计算

用定位实现,要注意取不到最后一行的需要+1

4、类的书写和函数定义

取值需要多尝试,要清楚的判断数值类型,输出类型,用value或多套data,或者分开取

5.2方案总结

5.2.1思维总结

1、对于订单、账单等含有多种数值、涉及计算的数据源,需要多次用info()查看数据类型,确保类型为纯数值,方便后续处理

2、拿到数据源后,要根据目标or要得到的分析结果,判断表中的有效信息数据为哪些,并取出来

3、找表之间的关系时,想到表连接,或内容匹配(如:河北省与河北,都有河北二字,就取相同值)

5.2.2方法总结

1、数值转换

2、空值处理

isna()

3、将数据加入列表再加入表

4、数值获取

········太多了都在上面了

相关推荐
databook12 小时前
Manim实现闪光轨迹特效
后端·python·动效
Juchecar13 小时前
解惑:NumPy 中 ndarray.ndim 到底是什么?
python
用户83562907805113 小时前
Python 删除 Excel 工作表中的空白行列
后端·python
Json_13 小时前
使用python-fastApi框架开发一个学校宿舍管理系统-前后端分离项目
后端·python·fastapi
RestCloud13 小时前
数据传输中的三大难题,ETL 平台是如何解决的?
数据分析·api
数据智能老司机20 小时前
精通 Python 设计模式——分布式系统模式
python·设计模式·架构
数据智能老司机21 小时前
精通 Python 设计模式——并发与异步模式
python·设计模式·编程语言
数据智能老司机21 小时前
精通 Python 设计模式——测试模式
python·设计模式·架构
数据智能老司机21 小时前
精通 Python 设计模式——性能模式
python·设计模式·架构
c8i21 小时前
drf初步梳理
python·django