数据分析——快递电商

一、任务目标

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、数值获取

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

相关推荐
小康小小涵1 小时前
基于ESP32S3实现无人机RID模块底层源码编译
linux·开发语言·python
lzjava20241 小时前
Python的函数
开发语言·python
Awesome Baron2 小时前
skill、tool calling、MCP区别
开发语言·人工智能·python
云栖笑笑生2 小时前
我把 Python re 模块比喻成摸金手套
数据挖掘
测试员周周2 小时前
【AI测试系统】第4篇:告别硬编码!基于 Markdown + Python 的 Skill 引擎设计:让 AI 测试系统拥有无限扩展的“灵魂”
人工智能·python·测试
武帝为此2 小时前
【Selenium 屏幕截图】
python·selenium·测试工具
念恒123063 小时前
Python(列表进阶)
python·学习
27669582923 小时前
阿里最新acw_sc__v2 分析
开发语言·python·acw_sc__v2·acw_sc__v2逆向·acw_sc__v2算法·acw_sc__v2算法分析·cookie逆向
小飞象—木兮3 小时前
《销售数据分析标准实践手册》:核心内涵与关键指标、落地销售数据分析的全流程···(附相关材料下载)
大数据·人工智能·数据挖掘·数据分析
vortex54 小时前
python 库劫持:原理、利用与防御
python·网络安全·提权