#簡介#
本篇是數(shù)據(jù)清洗的一點經(jīng)驗總結(jié),涉及到以下功能:預(yù)覽撩炊、異常值處理外永、數(shù)據(jù)類型轉(zhuǎn)換、字符串操作拧咳、選取行列伯顶、通過定義函數(shù)實現(xiàn)規(guī)則判斷等,依然是代碼+注釋+總結(jié)骆膝。
任務(wù)目標:將開放收入表里的各種數(shù)據(jù)進行預(yù)處理祭衩,以滿足分析要求。
目標拆解:逢山開路阅签,遇水架橋掐暮,直到數(shù)據(jù)符合可用標準。
#代碼展示#
#僅展示思路政钟,代碼做了簡化
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)
#定義函數(shù)實現(xiàn)規(guī)則判斷
def? pro(a):
????????if "內(nèi)蒙古" in a or "山西" in a:
????????????????return "晉蒙戰(zhàn)區(qū)"
? ? ? ? ?elif? a? in? list1:
? ? ? ? ? ? ? ? ? return a
? ? ? ? ? else:
? ? ? ? ? ? ? ? ? ?return "其他"
csvlist=[]
cur_path=os.getcwd()
walk(cur_path)
list1=["北京戰(zhàn)區(qū)","河北戰(zhàn)區(qū)","山東戰(zhàn)區(qū)","天津戰(zhàn)區(qū)","晉蒙戰(zhàn)區(qū)","其他"]
for????doc????in????csvlist:
????????????df=pd.read_csv(doc,encoding="gbk")
????????????df=df[df["自營外單"].isin([0])][["月份","客戶名稱","始發(fā)一級戰(zhàn)區(qū)","商家渠道名稱","自營外單","外單內(nèi)部B商家","單量","重量","收入","成本"]]
????????????df.head(10)
????????????df.dtypes()
????????????df.info()
? ? ? ? ? ? df["商家渠道名稱"]=df["商家渠道名稱"].astype(str)
????????????df=df[~df["商家渠道名稱"].str.contains("冷鏈|生鮮|醫(yī)藥")]
????????????df["歸屬戰(zhàn)區(qū)"]=df.apply(lambdadf:pro(df.始發(fā)一級戰(zhàn)區(qū)),axis=1)
????????????df[["收入","成本"]].fillna(0)
????????????df.groupby([["月份","始發(fā)一級戰(zhàn)區(qū)"]]).sum().reset_index()
????????????df["單均收入"]=df[["收入","單量"]].apply(lambdadf:df["收入"]/df["單量"],axis=1)
????????????df["單公斤收入"]=df[["收入","重量"]].apply(lambdadf:df["收入"]/df["重量"],axis=1)
????????????columns=["月份","始發(fā)一級戰(zhàn)區(qū)","單量","重量","收入","單均收入","單公斤收入"]
????????????df.to_csv("匯總數(shù)據(jù).csv",columns=columns,encoding="gbk")
#代碼拆解#
遍歷文件夾路克、讀取csv部分與上一篇相同,此處不做贅述锥涕。
數(shù)據(jù)預(yù)覽
df.head(10)????#預(yù)覽前10行數(shù)據(jù)
df.dtypes()????#顯示每個字段的數(shù)據(jù)類型
df.info()????#顯示每個字段的信息衷戈,包含位數(shù)狭吼、數(shù)據(jù)類型等
df.shape()????#顯示數(shù)據(jù)文件的行列形狀;另层坠,numpy創(chuàng)建數(shù)組時支持reshape()改變行列結(jié)構(gòu)
異常值處理
重復(fù)值去重,缺失值填充刁笙,偏離值調(diào)整
重復(fù)值去重:
df.drop_duplicates(subset=[],keep='first',inplace=False)
#subset參數(shù)為選定的列破花,keep參數(shù)決定保留的值,inplace決定是否替代
缺失值處理:
df[].isnull()#判斷是否為缺失值疲吸,輸出一列True or False布爾型
df.dropna()#去除缺失值座每,此時去除的是數(shù)據(jù)表中的整行,可通過調(diào)整參數(shù)實現(xiàn)其他功能
df.dropna(how="all",axis=1)#去除所有值為空的列,axis參數(shù)決定行列
df.fillna(0)#以0填充缺失值
關(guān)于fillna()函數(shù)的各參數(shù)摘悴,@Denver_Liao 的這篇文章寫的很詳細:https://blog.csdn.net/weixin_39549734/article/details/81221276
如何處理缺失值更合理的問題需要具體情況具體分析峭梳;偏離值的調(diào)整涉及到更深層次的統(tǒng)計學(xué)知識,限于所知不做討論;
數(shù)據(jù)類型轉(zhuǎn)換
對行列的值進行操作時葱椭,會對列的數(shù)據(jù)類型有要求捂寿。比如如果某一列有多種數(shù)據(jù)類型,pandas讀取csv時會進行報錯孵运,此時就需要指定讀取列的數(shù)據(jù)類型秦陋。
轉(zhuǎn)換數(shù)據(jù)類型的方式主要有兩種:使用庫的函數(shù)轉(zhuǎn)換或者通過自定義函數(shù)轉(zhuǎn)換
通過astype函數(shù)和pandas自帶函數(shù)
df.dtypes()#查看字段數(shù)據(jù)類型
df[].astype(str)#轉(zhuǎn)換為字符串
df[].astype(float)#轉(zhuǎn)換為浮點數(shù)(要求為全數(shù)字的字符串,不能包含特殊字符)
df[].astype(int)#轉(zhuǎn)換為整數(shù)
pd.to_numeric(df["收入"],errors="coerce").fillna(0)#轉(zhuǎn)換為數(shù)字型治笨,無法識別字符串;errors參數(shù)可選填"coerce"(填充為空值NaN)驳概、"ignore"(忽略,輸出原值)或"raise"(報錯)
pd.to_datetime(df[['Month','Day','Year']])#將年月日進行合并
通過自定義函數(shù)
定義函數(shù)法:
def? convert(a):
????????b=a.replace(r'[^\w\s]+','')
? ? ? ? returnfloat(b)#將列a中的特殊符號去除旷赖,然后轉(zhuǎn)換為float浮點數(shù)顺又,需要string庫支持
快捷方法:利用apply函數(shù)等
df["單量"]=df["單量"].str.replace(r'[^\w\s]+','').astype("int")
df["金額"].apply(lambdax:x.replace("¥","")).astype("float64")
關(guān)于數(shù)據(jù)類型轉(zhuǎn)換,這篇博客寫的不錯:https://www.cnblogs.com/onemorepoint/p/9404753.html
本文未對時間日期類數(shù)據(jù)類型的轉(zhuǎn)換進行討論等孵,日后有機會再補一篇
字符串操作
對字符串的拆分合并待榔、調(diào)整替換等
val.split(',')對val按,拆分流济;
pieces = [x.strip() for x in val.split(',')]split和strip用于清除空格锐锣;
字符串替換見數(shù)據(jù)類型轉(zhuǎn)換replace部分
選取行列
df=df[df["自營外單"].isin([0])][["月份","客戶名稱","收入","成本"]]
#后半段為篩選條件,選取"自營外單"字段值為0、特定列名的部分绳瘟;將其賦值給df實現(xiàn)替換雕憔;
#bool判斷條件部分暫時只能寫一個,如果寫兩個糖声,如df[df["自營外單"].isin([0])][df["外單內(nèi)部B商家"].isin([0])]會報邏輯錯誤
df[].isin(["a","b"])#函數(shù)用于選擇特定列值中包含a或者b的行
df=df[~df["商家渠道名稱"].str.contains("冷鏈|生鮮|醫(yī)藥")]#通過str.contains()函數(shù)篩選包含關(guān)鍵字字符串的行斤彼,“或”以“|”符號表示;
df=df[df["自營外單"]=="0"]#以布爾值進行判斷蘸泻;
df.iloc[[0:5],[0:5]]#選取6×6范圍內(nèi)的單元格琉苇,前為行后為列,只有:表示全選
自定義函數(shù)規(guī)則判斷
很簡單有效的方法悦施,展示幾個例子:
list1=["北京戰(zhàn)區(qū)","河北戰(zhàn)區(qū)","山東戰(zhàn)區(qū)","天津戰(zhàn)區(qū)","晉蒙戰(zhàn)區(qū)","其他"]
def????pro(a):
????????if? "內(nèi)蒙古"? in? a? or? "山西"? in a:
????????????????return? "晉蒙戰(zhàn)區(qū)"
????????elif? a in list1:
????????????????return a
? ? ? ? ?else:
????????????????return "其他"
#用于規(guī)避0/0的bug:
def? div(a,b):
????????if? b==0 or a==0:
????????????????return 0
? ? ? ? else:
????????????????return? a/b
自定義函數(shù)實現(xiàn)規(guī)則是個很有效的手段并扇,應(yīng)用起來也很簡單方便,通過apply&lambda函數(shù)就可以實現(xiàn)抡诞;如df["歸屬戰(zhàn)區(qū)"] = df.apply(lambda df:pro(df.始發(fā)一級戰(zhàn)區(qū)),axis=1),如果參數(shù)為某一列穷蛹,需要以 df.列名 設(shè)置參數(shù)
以上就是本次的分享了,零零散散扯了很多昼汗,希望能讓大家少走些彎路~
CSDN同作者肴熏,博文連接https://blog.csdn.net/z1272578750/article/details/104008047