作者:血色的蓮花 | 来源:互联网 | 2023-09-05 10:55
1.重复值处理•数据清洗一般先从重复值和缺失值开始处理•重复值一般采取删除法来处理•但有些重复值不能删除,例如订单明细数据或交易明细数据等df.head(5)#
1. 重复值处理 • 数据清洗一般先从重复值和缺失值开始处理 • 重复值一般采取删除法来处理 • 但有些重复值不能删除,例如订单明细数据或交易明细数据等
df.head(5) #对价格和里程数数据进行处理 # 自定义一个函数 def f(x):if '$' in str(x):x = str(x).strip('$')x = str(x).replace(',','')else:x = str(x).replace(',','')return float(x) df['Price'] = df['Price'] .apply(f) df['Mileage'] = df['Mileage'].apply(f) print ('数据集是否存在重复观测: \n', any(df.duplicated())) df[df.duplicated()] #查看那些数据重复 np.sum(df.duplicated()) #计算重复数量 df.drop_duplicates() #删除所有变量都重复的行, 注意没有加inplace = True df.drop_duplicates(subset= ['Condition','Condition_Desc','Price','Location'],inplace=True) #按照两个变量重复来来去重 df.info()
2. 缺失值处理 • 缺失值首先需要根据实际情况定义 • 可以采取直接删除法 • 有时候需要使用替换法或者插值法 • 常用的替换法有均值替换、前向、后向替换和常数替换
df.apply(lambda x: sum(x.isnull())/len(x),axis= 0) #缺失比例 #删除法 df.dropna() #直接删除法 df.dropna(how='any',axis = 1 ) #只要有缺失,就删除这一列 df.dropna(how='any',axis = 0) #只要有缺失,就删除这一行,等价于df.dropna() #axis = 0 或者 1代表的函数在数据集作用的方向,0代表沿着行的方向,1代表沿着列的方向 df.dropna(axis = 0,how='any',subset=['Condition','Price','Mileage']) # 1代表列,0代表行,只要有缺失,就删除这一行,基于三个变量
在数据分析中,实际上大部分时候都是按照行来进行删除的,很少会基于列来进行删除 列代表的是变量,是否删除删除列很多时候主要取决于缺失比例 使用替换法进行缺失值的填补 替换法
df.head(10) df.Mileage.fillna(df.Mileage.mean()) # 年龄用均值填补 df.Mileage.fillna(df.Mileage.median()) #中位数填补 df[df['Exterior_Color'].isnull()] df.Exterior_Color.fillna(df.Exterior_Color.mode()[0]) #众数填补 df.fillna(20) # 所有缺失用20填补 # 婚姻状况使用众数,年龄使用均值,农户家庭人数使用中位数 df.fillna(value = {'Exterior_Color':df.Exterior_Color.mode()[0],'Mileage':df.Mileage.mean()}) df['Exterior_Color'].fillna(method='ffill') #前向填补 df['Exterior_Color'].fillna(method='bfill') #后向填补
3. 异常值处理 • 指那些偏离正常范围的值,不是错误值 • 异常值出现频率较低,但又会对实际项目分析造成偏差 • 异常值一般用过箱线图法(分位差法)或者分布图(标准差法)来判断 • 异常值往往采取盖帽法或者数据离散化 异常值检测可以使用均值的2倍标准差范围,也可以使用上下4分位数差方法
# 判断年龄有什么异常值 # 剔除户主姓名,户主身份证号和年龄有缺失的样本 df.dropna(axis = 0,how='any',subset=['户主姓名','户主身份证号','age'],inplace = True) #1代表列,0代表行,只要有缺失,就删除这一行,基于三个变量 # 异常值检测之标准差法 xbar = df.Price.mean() xstd = df.Price.std() print('标准差法异常值上限检测:\n',any(df.Price> xbar + 2.5 * xstd)) print('标准差法异常值下限检测:\n',any(df.Price# 异常值检测之箱线图法 Q1 = df.Price.quantile(q = 0.25) Q3 = df.Price.quantile(q = 0.75) IQR = Q3 - Q1 print('箱线图法异常值上限检测:\n',any(df.Price > Q3 + 1.5 * IQR)) print('箱线图法异常值下限检测:\n',any(df.Price df.Price.describe()# 对年龄进行描述性统计 import matplotlib.pyplot as plt %matplotlib inline df.Price.plot(kind ='box') # 导入绘图模块 import matplotlib.pyplot as plt # 设置绘图风格 plt.style.use('seaborn') # 绘制直方图 df.Price.plot(kind = 'hist', bins = 30, density = True) # 绘制核密度图 df.Price.plot(kind = 'kde') # 图形展现 plt.show() # 用99分位数和1分位数替换 #计算P1和P99 P1 =df.Price.quantile(0.01); P99 = df.Price.quantile(0.99) #先创建一个新变量,进行赋值,然后将满足条件的数据进行替换 df['Price_new'] = df['Price'] df.loc[df['Price'] > P99,'Price_new'] = P99 df.loc[df['Price'] df[['Price','Price_new']].describe()
4. 数据离散化 • 数据离散化就是分箱 • 一般常用分箱方法是等频分箱或者等宽分箱 • 一般使用pd.cut或者pd.qcut函数
pandas.cut(x, bins, right=True, labels=None, retbins=False, precision=3, include_lowest=False)
x:类array对象,且必须为一维,待切割的原形式 bins:整数、序列尺度、或间隔索引。如果bins是一个整数,它定义了x宽度范围内的等宽面元数量,但是在这种情况下,x的范围在每个边上被延长1%,以保证包括x的最小值或最大值。如果bin是序列,它定义了允许非均匀bin宽度的bin边缘。在这种情况下没有x的范围的扩展。 right,布尔值。是否是左开右闭区间,right=True,左开右闭,right=False,左闭右开 labels,用作结果箱的标签。必须与结果箱相同长度。如果FALSE,只返回整数指标面元。 retbins,布尔值。是否返回面元 precision,整数。返回面元的小数点几位 include_lowest,布尔值。第一个区间的左端点是否包含 df.head(5) df['Price_bin'] = pd.cut(df['Price_new'],5,labels=range(5)) df['Price_bin'].hist() #自定义分段标准和标签 df['Price_new'].describe() w = [100,1000,5000,10000,20000,50000] df['Price_bin'] = pd.cut(df['Price_new'], bins =w,labels=['低','便宜','划算','中等','高'],right=False) df['Price_bin'].value_counts()
pandas.qcut(x, q, labels=None, retbins=False, precision=3, duplicates=’raise’)
x q,整数或分位数组成的数组。整数比如 4 代表 按照4分位数 进行切割 labels, 用作结果箱的标签。必须与结果箱相同长度。如果FALSE,只返回整数指标面元。 原理都是基于分位数来进行离散化 k = 5 w = [1.0*i/k for i in range(k+1)] df['Price_bin'] = pd.qcut(df['Price_new'],w,labels=range(k)) df['Price_bin'].hist() #或者先计算分位数的值 k = 5 w1 = df['Price_new'].quantile([1.0*i/k for i in range(k+1)])#先计算分位数,在进行分段 w1[0] = w1[0]* 0.95 # 最小值缩小一点 w[-1] = w1[1]* 1.05 # 将最大值增大一点, 目的是为了确保数据在这个范围内 w1 df['Price_bin'] = pd.cut(df['Price_new'],w1,labels=range(k)) df['Price_bin'].hist()