数据分析时,首先应对数据进行清洗,这里将数据清洗分为重复值处理、缺失值处理、异常值处理三个部分,重复值处理可删除重复的字段,缺失值处理可以用线性插值、填充为0或用均值填充等,异常值处理用描述性分析、散点图、箱形图、直方图查找异常并处理。
本文使用超市商品交易数据,详细介绍重复值处理、缺失值处理、异常值处理的方法,并实际运用数据进行演示,代码操作如下所示。
数据处理
#导入数据 import pandas as pd df=pd.read_csv(r"C:\Users\尚天强\Desktop\超市商品交易.csv",engine="python",encoding="utf-8-sig") df.head()
![](https://pic1.zhimg.com/80/v2-bcfd1fd142e72ed5c245d4143c56247c_720w.webp)
1、重复值处理
首先对重复值计数。
df.duplicated().value_counts()
![](https://pic1.zhimg.com/80/v2-1d1ecb15cc50b45a27d264057da85438_720w.webp)
用drop_duplicates的方法对某几列下面的重复行删除,subset:以某列作为基准列,判断是否重复;keep: 保留哪个字段,fisrt参数保留首次出现的数值;inplace: 是否替换当前数据,True选择替换当前数据。
df.drop_duplicates(subset=["商品码"],keep='first',inplace=True) df.duplicated().value_counts()
![](https://pic4.zhimg.com/80/v2-4a22d859c76a23f1eb3e7094516bcc97_720w.webp)
2、缺失值处理
通过isnull函数看一下是否有空值,结果是有空值的地方显示为True,没有的显示为False。
df.head(11).isnull()
![](https://pic2.zhimg.com/80/v2-f281f734269151b017135b42e136dee9_720w.webp)
使用info查看各个字段的属性,标记的部分为缺失的部分。
df.info()
![](https://pic3.zhimg.com/80/v2-dd54d7afe13cd54e9d80d9a9856d85fe_720w.webp)
通过isnull().any()查看每一列是否有空值,True返回缺失值。
df.isnull().any()
![](https://pic1.zhimg.com/80/v2-0721f28f86325954e6c1bdf4af3ea4bc_720w.webp)
用df.isnull().values==True来定位哪几行是有空值的。
df[df.isnull().values==True]
![](https://pic2.zhimg.com/80/v2-3689ab908eb78772f3db1b761af403f1_720w.webp)
how='any'只要有一个缺失值就删除,axis=0,删除的是行,默认删除的是行,inplace=True替换原始数据。
df.dropna(how='any', axis=0,inplace=True) df.info()
![](https://pic1.zhimg.com/80/v2-f0da83fda96d46185ddd25a860cb4b9c_720w.webp)
fillna(0)用0对缺失值进行填充。
df1=df[df.isnull().values==True] df1.fillna(0)
![](https://pic1.zhimg.com/80/v2-b13b49d861adaec4d0a586e202ced738_720w.webp)
limit用来限定填充的数量。
df1.fillna(0,limit=3)
![](https://pic3.zhimg.com/80/v2-fe66bb0ee20c8cfff6279b4e04aaf45a_720w.webp)
{ }对不同的列填充不同的值,其中键作为列,值作为缺失值填充的值。
df1.fillna({"售价":0 ,"成交价":0 ,"进价": "#N/A"})
![](https://pic4.zhimg.com/80/v2-9d7bc2eb69d83e8410926e144440cd97_720w.webp)
method方法使用ffill,表示用前一个值作为填充的值。
df1.fillna(method="ffill")
![](https://pic1.zhimg.com/80/v2-e2b29552a5b735dae08afd654772accc_720w.webp)
median方法使用中位数的值进行填充。
df1.fillna(df1.median())
![](https://pic3.zhimg.com/80/v2-59f3e0473c1bbfd19dfaa41bf32afaf6_720w.webp)
interpolate表示线性插值。
df[df.isnull().values==True].interpolate() #线性插值
![](https://pic4.zhimg.com/80/v2-b1f8193038b2a22a17ddc862845a62e7_720w.webp)
3、异常值处理
describe( )对统计字段进行描述性分析,从平均值、标准差,看数据的波动情况,最大值查看数据的极值。
df[['售价','进价']].describe()
![](https://pic4.zhimg.com/80/v2-e622ac9ec2fd1f49910e6e470b5683b7_720w.webp)
做出散点图,查看数据中异常的点,图中标记的点就是异常的点。
from matplotlib import pyplot as plt plt.rcParams["font.sans-serif"]='SimHei' #解决中文乱码问题 plt.scatter(df["售价"], df["进价"]) plt.title("散点图",loc = "center") plt.show()
![](https://pic1.zhimg.com/80/v2-47c574def7c5cf97085eb329830dbc80_720w.webp)
做出箱线图,反映原始数据分布的特征。
plt.subplot(1,2,1) plt.boxplot(df["数量"],labels = ["数量"]) plt.subplot(1,2,2) plt.boxplot(df["售价金额"],labels = ["售价金额"]) plt.show()
![](https://pic2.zhimg.com/80/v2-1ffed4b3a816df8658ad85b956ea542d_720w.webp)
做售价金额的折线图,售价金额呈波动趋势。
plt.plot(df["售价金额"])
![](https://pic4.zhimg.com/80/v2-e1131c8834302d624a2e927bebcb95a3_720w.webp)
用箱形图的办法,超过了上四分位1.5倍四分位距或下四分位1.5倍距离都算异常值,用中位数填充。
import numpy as np a = df["售价金额"].quantile(0.75) b = df["售价金额"].quantile(0.25) c = df["售价金额"] c[(c>=(a-b)*1.5+a)|(c<=b-(a-b)*1.5)]=np.nan c.fillna(c.median(),inplace=True) c.describe()
![](https://pic1.zhimg.com/80/v2-ee15ca053168c8d3b0157e298609e468_720w.webp)
用标准差和均值,定义超过4倍就算异常值,同样用中位数填充。
a = df["售价金额"].mean()+df["售价金额"].std()*4 b = df["售价金额"].mean()-df["售价金额"].std()*4 c = df["售价金额"] c[(c>=a)|(c<=b)]=np.nan c.fillna(c.median(),inplace=True) c.describe()
![](https://pic4.zhimg.com/80/v2-d4924e4ee72d96b464c51712cd62a583_720w.webp)
正态性检验,发现售价金额呈右偏分布,表明售价金额并不是正态分布。
import seaborn as sns sns.distplot(df['售价金额']) #解决负号无法正常显示问题 plt.rcParams["axes.unicode_minus"]= False plt.show()
![](https://pic3.zhimg.com/80/v2-5c3b621a9fc447679f4ef54f56a79346_720w.webp)