python数据分析&办公自动化实战(三):数据预处理/数据清洗

#简介#

本篇是数据清洗的一点经验总结,涉及到以下功能:预览、异常值处理、数据类型转换、字符串操作、选取行列、通过定义函数实现规则判断等,依然是代码+注释+总结

任务目标:将开放收入表里的各种数据进行预处理,以满足分析要求。

目标拆解:逢山开路,遇水架桥,直到数据符合可用标准。

#代码展示#

#仅展示思路,代码做了简化

import os,sys

import numpy as np

import pandas as pd

import openpyxl 

import csv

import xlwt

#遍历文件夹,输出文件夹下所有的文件路径及名称

def walk(path):

        if not os.path.exists(path):

                return -1

        for root,dirs,names in os.walk(path):

                for filename in names:

                        if os.path.splitext(filename)[1]=='.csv':

                                docs=os.path.join(root,filename)

                                print(docs)

                                csvlist.append(docs)

#定义函数实现规则判断

def  pro(a):

        if "内蒙古" in a or "山西" in a:

                return "晋蒙战区"

         elif  a  in  list1:

                  return a

          else:

                   return "其他"

csvlist=[]

cur_path=os.getcwd()

walk(cur_path)

list1=["北京战区","河北战区","山东战区","天津战区","晋蒙战区","其他"]

for    doc    in    csvlist:

            df=pd.read_csv(doc,encoding="gbk")

            df=df[df["自营外单"].isin([0])][["月份","客户名称","始发一级战区","商家渠道名称","自营外单","外单内部B商家","单量","重量","收入","成本"]]

            df.head(10)

            df.dtypes()

            df.info()

            df["商家渠道名称"]=df["商家渠道名称"].astype(str)

            df=df[~df["商家渠道名称"].str.contains("冷链|生鲜|医药")]

            df["归属战区"]=df.apply(lambdadf:pro(df.始发一级战区),axis=1)

            df[["收入","成本"]].fillna(0)

            df.groupby([["月份","始发一级战区"]]).sum().reset_index()

            df["单均收入"]=df[["收入","单量"]].apply(lambdadf:df["收入"]/df["单量"],axis=1)

            df["单公斤收入"]=df[["收入","重量"]].apply(lambdadf:df["收入"]/df["重量"],axis=1)

            columns=["月份","始发一级战区","单量","重量","收入","单均收入","单公斤收入"]

            df.to_csv("汇总数据.csv",columns=columns,encoding="gbk")

#代码拆解#

遍历文件夹、读取csv部分与上一篇相同,此处不做赘述。

数据预览

df.head(10)    #预览前10行数据

df.dtypes()    #显示每个字段的数据类型

df.info()    #显示每个字段的信息,包含位数、数据类型等

df.shape()    #显示数据文件的行列形状;另,numpy创建数组时支持reshape()改变行列结构

异常值处理

重复值去重,缺失值填充,偏离值调整

重复值去重:

df.drop_duplicates(subset=[],keep='first',inplace=False)

#subset参数为选定的列,keep参数决定保留的值,inplace决定是否替代

缺失值处理:

df[].isnull()#判断是否为缺失值,输出一列True or False布尔型

df.dropna()#去除缺失值,此时去除的是数据表中的整行,可通过调整参数实现其他功能

df.dropna(how="all",axis=1)#去除所有值为空的列,axis参数决定行列

df.fillna(0)#以0填充缺失值

关于fillna()函数的各参数,@Denver_Liao 的这篇文章写的很详细:https://blog.csdn.net/weixin_39549734/article/details/81221276

如何处理缺失值更合理的问题需要具体情况具体分析;偏离值的调整涉及到更深层次的统计学知识,限于所知不做讨论;

数据类型转换

对行列的值进行操作时,会对列的数据类型有要求。比如如果某一列有多种数据类型,pandas读取csv时会进行报错,此时就需要指定读取列的数据类型。

转换数据类型的方式主要有两种:使用库的函数转换或者通过自定义函数转换

通过astype函数和pandas自带函数

df.dtypes()#查看字段数据类型

df[].astype(str)#转换为字符串

df[].astype(float)#转换为浮点数(要求为全数字的字符串,不能包含特殊字符)

df[].astype(int)#转换为整数

pd.to_numeric(df["收入"],errors="coerce").fillna(0)#转换为数字型,无法识别字符串;errors参数可选填"coerce"(填充为空值NaN)、"ignore"(忽略,输出原值)或"raise"(报错)

pd.to_datetime(df[['Month','Day','Year']])#将年月日进行合并

通过自定义函数

定义函数法:

def  convert(a):

        b=a.replace(r'[^\w\s]+','')

        returnfloat(b)#将列a中的特殊符号去除,然后转换为float浮点数,需要string库支持

快捷方法:利用apply函数等

df["单量"]=df["单量"].str.replace(r'[^\w\s]+','').astype("int")

df["金额"].apply(lambdax:x.replace("¥","")).astype("float64")

关于数据类型转换,这篇博客写的不错:https://www.cnblogs.com/onemorepoint/p/9404753.html

本文未对时间日期类数据类型的转换进行讨论,日后有机会再补一篇

字符串操作

对字符串的拆分合并、调整替换等

val.split(',')对val按,拆分;

pieces = [x.strip() for x in val.split(',')]split和strip用于清除空格;

字符串替换见数据类型转换replace部分

选取行列

df=df[df["自营外单"].isin([0])][["月份","客户名称","收入","成本"]]

#后半段为筛选条件,选取"自营外单"字段值为0、特定列名的部分;将其赋值给df实现替换;

#bool判断条件部分暂时只能写一个,如果写两个,如df[df["自营外单"].isin([0])][df["外单内部B商家"].isin([0])]会报逻辑错误

df[].isin(["a","b"])#函数用于选择特定列值中包含a或者b的行

df=df[~df["商家渠道名称"].str.contains("冷链|生鲜|医药")]#通过str.contains()函数筛选包含关键字字符串的行,“或”以“|”符号表示;

df=df[df["自营外单"]=="0"]#以布尔值进行判断;

df.iloc[[0:5],[0:5]]#选取6×6范围内的单元格,前为行后为列,只有:表示全选

自定义函数规则判断

很简单有效的方法,展示几个例子:

list1=["北京战区","河北战区","山东战区","天津战区","晋蒙战区","其他"]

def    pro(a):

        if  "内蒙古"  in  a  or  "山西"  in a:

                return  "晋蒙战区"

        elif  a in list1:

                return a

         else:

                return "其他"

#用于规避0/0的bug:

def  div(a,b):

        if  b==0 or a==0:

                return 0

        else:

                return  a/b

自定义函数实现规则是个很有效的手段,应用起来也很简单方便,通过apply&lambda函数就可以实现;如df["归属战区"] = df.apply(lambda df:pro(df.始发一级战区),axis=1),如果参数为某一列,需要以 df.列名 设置参数

以上就是本次的分享了,零零散散扯了很多,希望能让大家少走些弯路~

CSDN同作者,博文连接https://blog.csdn.net/z1272578750/article/details/104008047

你可能感兴趣的:(python数据分析&办公自动化实战(三):数据预处理/数据清洗)