第5章 数据清理

目录

本文的jupyter notebook版本及数据资料文件下载地址 百度网盘

5.1 数据清理的概述

5.1.1 常见的三种数据问题

  • 缺失值
  • 重复值
  • 异常值

5.1.2 常见三种数据问题的处理办法

  • 缺失值处理:

    • 丢弃有缺失值的数据记录
    • 填充记录的缺失值: 均值填充、中位数填充、众数填充、前值填充、后值填充
    • 插补记录的缺失值。
  • 重复值处理:

    • 删除重复的记录
    • 保留重复的记录
  • 异常值的处理:

    • 删除带异常值的记录
    • 保留带异常值的记录
    • 替换掉记录中的异常值

5.2 缺失值的检测与处理

5.2.1 缺失值的检测

pandas中通常用nan或者是none来代表缺失值。
常用的检测的方法有:

  • isnull(): True则有缺失值
  • notnull():False则有缺失值
  • isna(): True则有缺失值
  • notna(): False则有缺失值
import pandas as pd
import numpy as np

na_df = pd.DataFrame({'A':[1,2,np.NaN,4],
                      'B':[3,4,4,5],
                      'C':[5,6,7,8],
                      'D':[7,5,np.NaN, np.NaN]})
na_df
ABCD
01.0357.0
12.0465.0
2NaN47NaN
34.058NaN
# isnull(): True则有缺失值
na_df.isnull()
ABCD
0FalseFalseFalseFalse
1FalseFalseFalseFalse
2TrueFalseFalseTrue
3FalseFalseFalseTrue
# notnull():False则有缺失值
na_df.notnull()
ABCD
0TrueTrueTrueTrue
1TrueTrueTrueTrue
2FalseTrueTrueFalse
3TrueTrueTrueFalse
#isna(): True则有缺失值
na_df.isna()
ABCD
0FalseFalseFalseFalse
1FalseFalseFalseFalse
2TrueFalseFalseTrue
3FalseFalseFalseTrue
#notna(): False则有缺失值
na_df.notna()
ABCD
0TrueTrueTrueTrue
1TrueTrueTrueTrue
2FalseTrueTrueFalse
3TrueTrueTrueFalse
mr_df = na_df.isna()
na_df
ABCD
01.0357.0
12.0465.0
2NaN47NaN
34.058NaN
mr_df
ABCD
0FalseFalseFalseFalse
1FalseFalseFalseFalse
2TrueFalseFalseTrue
3FalseFalseFalseTrue
na_df[mr_df]
ABCD
0NaNNaNNaNNaN
1NaNNaNNaNNaN
2NaNNaNNaNNaN
3NaNNaNNaNNaN
na_df
ABCD
01.0357.0
12.0465.0
2NaN47NaN
34.058NaN
na_df>3
ABCD
0FalseFalseTrueTrue
1FalseTrueTrueTrue
2FalseTrueTrueFalse
3TrueTrueTrueFalse
na_df[na_df>3]
ABCD
0NaNNaN57.0
1NaN4.065.0
2NaN4.07NaN
34.05.08NaN

5.2.2 缺失值的处理

5.2.2.1 丢弃有缺失值的数据记录

pandas中用dropna() 删除有缺失值的一行或者一列。

语法格式:

DataFrame.dropna(axis=0, how=‘any’, thresh=None, subset=None,inplace=False)

参数说明:

  • axis:表示是否删除包含缺失值的行(axis=0)或列(axis=1)。
  • how:表示删除缺失值的方式('any’表示存在任何一个空值则删除整行或列;‘all’表示所有都是空值时才删除)。
  • thresh:表示保留至少有N个非NaN值的行或列。
  • subset:表示删除指定列的缺失值。
  • inplace:表示是否操作原数据。
na_df
ABCD
01.0357.0
12.0465.0
2NaN47NaN
34.058NaN
#DataFrame.dropna(axis=0, how='any', thresh=None, subset=None,inplace=False)
# axis=0是删除整行
# 默认how=any,则表示有任何一个为nan就删除
na_df.dropna()
ABCD
01.0357.0
12.0465.0
# how=all要所有元素是nan才删除
na_df.dropna(how='all')
ABCD
01.0357.0
12.0465.0
2NaN47NaN
34.058NaN
# axis=1是删除列
na_df.dropna(axis=1)
BC
035
146
247
358
# thresh=3表示至少保留3行或者3列
na_df.dropna(thresh=3)
ABCD
01.0357.0
12.0465.0
34.058NaN
na_df.dropna(axis=1,thresh=3)
ABC
01.035
12.046
2NaN47
34.058
new_df = na_df.dropna()
new_df
ABCD
01.0357.0
12.0465.0
na_df
ABCD
01.0357.0
12.0465.0
2NaN47NaN
34.058NaN
# inplace=True则更改了原dataframe,不返回值
na_df.dropna(inplace=True)
na_df
ABCD
01.0357.0
12.0465.0
import numpy as np
import pandas as pd
 
a = np.ones((11,10))
for i in range(len(a)):
    a[i,:i] = np.nan
d = pd.DataFrame(data=a)
print(d)
      0    1    2    3    4    5    6    7    8    9
0   1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0
1   NaN  1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0
2   NaN  NaN  1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0
3   NaN  NaN  NaN  1.0  1.0  1.0  1.0  1.0  1.0  1.0
4   NaN  NaN  NaN  NaN  1.0  1.0  1.0  1.0  1.0  1.0
5   NaN  NaN  NaN  NaN  NaN  1.0  1.0  1.0  1.0  1.0
6   NaN  NaN  NaN  NaN  NaN  NaN  1.0  1.0  1.0  1.0
7   NaN  NaN  NaN  NaN  NaN  NaN  NaN  1.0  1.0  1.0
8   NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  1.0  1.0
9   NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  1.0
10  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN  NaN
# 设置子集:删除第0、5、6、7列都为空的行
print(d.dropna(axis='index', how='all', subset=[0,5,6,7]))
     0    1    2    3    4    5    6    7    8    9
0  1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0
1  NaN  1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0
2  NaN  NaN  1.0  1.0  1.0  1.0  1.0  1.0  1.0  1.0
3  NaN  NaN  NaN  1.0  1.0  1.0  1.0  1.0  1.0  1.0
4  NaN  NaN  NaN  NaN  1.0  1.0  1.0  1.0  1.0  1.0
5  NaN  NaN  NaN  NaN  NaN  1.0  1.0  1.0  1.0  1.0
6  NaN  NaN  NaN  NaN  NaN  NaN  1.0  1.0  1.0  1.0
7  NaN  NaN  NaN  NaN  NaN  NaN  NaN  1.0  1.0  1.0

5.2.2.2 填充记录的缺失值

pandas中用fillna()进行缺失值的填充

语法格式:

DataFrame.fillna(value=None, method=None, axis=None, inplace=False,
limit=None, downcast=None)

参数说明:

  • method:表示填充的方式,默认值为None。该参数还支持 'pad’或’ffill’和’backfill’或’bfill’几种取值
    • 'pad’或’ffill’表示将最后一个有效值向后传播,也就是说使用缺失值前面的有效值填充缺失值;
    • 'backfill’或’bfill’表示将最后一个有效值向前传播,也就是说使用缺失值后面的有效值填充缺失值。
  • limit:表示可以连续填充的最大数量。
na_df
ABCD
01.0357.0
12.0465.0
2NaN47NaN
34.058NaN
np.mean(na_df['A'])
2.3333333333333335
# 计算A列的非空值的平均值,并保留一位小数
col_a = np.around(np.mean(na_df['A']),1)
col_a
2.3
# 计算D列的非空值的平均值,并保留一位小数
col_d = np.around(np.mean(na_df['D']),1)
col_d
6.0
na_df.fillna(value={'A':col_a,'D':col_d})
ABCD
01.0357.0
12.0465.0
22.3476.0
34.0586.0
# value是一个字典时,对不同列采用不同值进行填充
na_df.fillna(value={'A':1000,'D':9999})
ABCD
01.0357.0
12.0465.0
21000.0479999.0
34.0589999.0
# value是一个变量或标量时,对整个dataframe采用该值填充nan
na_df.fillna(8888)
ABCD
01.0357.0
12.0465.0
28888.0478888.0
34.0588888.0
na_df
ABCD
01.0357.0
12.0465.0
2NaN47NaN
34.058NaN
# method = 'ffill',表示用nan的记录的前一个记录的该列值填充
# 用前值填充时第一行的nan无法填充
na_df.fillna(method='ffill')
ABCD
01.0357.0
12.0465.0
22.0475.0
34.0585.0
# method = 'bfill',表示用nan的记录的后一个记录的该列值填充
# 用后值填充时,最后一行的nan无法填充
na_df.fillna(method='bfill')
ABCD
01.0357.0
12.0465.0
24.047NaN
34.058NaN
5.2.2.3 插补记录的缺失值

pandas中提供了插补缺失值的方法interpolate(),interpolate() 会根据相应的插值方法求得的值进行填充。

语法格式:

DataFrame.interpolate(method=‘linear’, axis=0, limit=None, inplace=False,
limit_direction=None, limit_area=None, downcast=None, **kwargs)

参数说明:

  • method:表示使用的插值方法,该参数支持’linear’(默认值)、‘time’、 ‘index’、‘values’、 ‘nearest’ 、'barycentric’共6种取值,
    • 'linear’代表采用线性插值法进行填充;
    • 'time’代表根据时间长短进行填充;
    • ‘index’、'values’代表采用索引的实际数值进行填充;
    • ‘nearest’代表采用最临近插值法进行填充;’
    • barycentric’代表采用重心坐标插值法进行填充。
  • limit_direction:表示按照指定方向对连续的NaN进行填充。
na_df.interpolate(method='linear')
ABCD
01.0357.0
12.0465.0
23.0475.0
34.0585.0

例子练习

txtData = pd.read_csv("cj.txt",sep="\t")
txtData
学号班级姓名性别英语体育军训数分高代解几
0230802424123080242成龙767877402360
1230802424423080242周怡669175474744
2230802425123080242张波858175454560
3230802424923080242朱浩655080726271
4230802421923080242封印738892614746
5230802420123080242迟培605089717671
6230802434723080243李华676184616578
7230802430723080243陈田767986694069
8230802432623080243余皓666785656171
9230802432023080243李嘉62作弊90606777
10230802434223080243李上初769084606660
11230802431023080243郭窦796784646479
12230802443523080244姜毅涛7771缺考617376
13230802443223080244赵宇747488687071
14230802444623080244周路768077617480
15230802442123080244林建祥727281639075
16230802443323080244李大强797677787070
17230802442823080244李侧通649691696077
18230802440223080244王慧737493707175
19230802442223080244李晓亮856085727283
20230802420123080242迟培605089717671
txtData.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 21 entries, 0 to 20
Data columns (total 10 columns):
 #   Column  Non-Null Count  Dtype 
---  ------  --------------  ----- 
 0   学号      21 non-null     int64 
 1   班级      21 non-null     int64 
 2   姓名      21 non-null     object
 3   性别      21 non-null     object
 4   英语      21 non-null     int64 
 5   体育      21 non-null     object
 6   军训      21 non-null     object
 7   数分      21 non-null     int64 
 8   高代      21 non-null     int64 
 9   解几      21 non-null     int64 
dtypes: int64(6), object(4)
memory usage: 1.8+ KB
df = txtData
df['体育']=pd.to_numeric(df['体育'],errors='coerce')
df['军训']=pd.to_numeric(df['军训'],errors='coerce')
df
学号班级姓名性别英语体育军训数分高代解几
0230802424123080242成龙7678.077.0402360
1230802424423080242周怡6691.075.0474744
2230802425123080242张波8581.075.0454560
3230802424923080242朱浩6550.080.0726271
4230802421923080242封印7388.092.0614746
5230802420123080242迟培6050.089.0717671
6230802434723080243李华6761.084.0616578
7230802430723080243陈田7679.086.0694069
8230802432623080243余皓6667.085.0656171
9230802432023080243李嘉62NaN90.0606777
10230802434223080243李上初7690.084.0606660
11230802431023080243郭窦7967.084.0646479
12230802443523080244姜毅涛7771.0NaN617376
13230802443223080244赵宇7474.088.0687071
14230802444623080244周路7680.077.0617480
15230802442123080244林建祥7272.081.0639075
16230802443323080244李大强7976.077.0787070
17230802442823080244李侧通6496.091.0696077
18230802440223080244王慧7374.093.0707175
19230802442223080244李晓亮8560.085.0727283
20230802420123080242迟培6050.089.0717671
df['体育'].mean()
72.75
df.fillna(value={'体育':df['体育'].mean(),'军训':df['军训'].min()})
学号班级姓名性别英语体育军训数分高代解几
0230802424123080242成龙7678.0077.0402360
1230802424423080242周怡6691.0075.0474744
2230802425123080242张波8581.0075.0454560
3230802424923080242朱浩6550.0080.0726271
4230802421923080242封印7388.0092.0614746
5230802420123080242迟培6050.0089.0717671
6230802434723080243李华6761.0084.0616578
7230802430723080243陈田7679.0086.0694069
8230802432623080243余皓6667.0085.0656171
9230802432023080243李嘉6272.7590.0606777
10230802434223080243李上初7690.0084.0606660
11230802431023080243郭窦7967.0084.0646479
12230802443523080244姜毅涛7771.0075.0617376
13230802443223080244赵宇7474.0088.0687071
14230802444623080244周路7680.0077.0617480
15230802442123080244林建祥7272.0081.0639075
16230802443323080244李大强7976.0077.0787070
17230802442823080244李侧通6496.0091.0696077
18230802440223080244王慧7374.0093.0707175
19230802442223080244李晓亮8560.0085.0727283
20230802420123080242迟培6050.0089.0717671

5.3 重复值处理

  • 删除重复的记录
  • 保留重复的记录

5.3.1 重复值的检测

pandas中使用duplicated()方法来检测数据中的重复值。

语法格式:

DataFrame.duplicated(subset=None, keep=‘first’)

参数说明:

  • subset:表示识别重复项的列索引或列索引序列,默认标识所有的列索引。
  • keep:表示采用哪种方式保留重复项,该参数可以取值为’first’(默认值)、 'last '和 ‘False’.
    • 'first’代表删除重复项,仅保留第一次出现的数据项;
    • 'last '代表删除重复项,仅保留最后一次出现的数据项;
    • 'False’表示所有相同的数据都被标记为重复项。
import pandas as pd
person_info = pd.DataFrame({'name':['刘婷婷','王淼','彭岩','刘华','刘华','周华'],
                            'age':[24,23,29,22,22,27],
                            'height':[162,165,175,175,175,178],
                            'gender':['女','女','男','男','男','男']})
person_info
nameageheightgender
0刘婷婷24162
1王淼23165
2彭岩29175
3刘华22175
4刘华22175
5周华27178
# 检测person_info中是否有重复的行
# subset=None, keep='first'
person_info.duplicated()
0    False
1    False
2    False
3    False
4     True
5    False
dtype: bool
# 检测person_info中是否有重复的行
# subset=None, keep='last'
person_info.duplicated(keep='last')
0    False
1    False
2    False
3     True
4    False
5    False
dtype: bool
# 检测person_info中是否有重复的行
# subset=None, keep=False
person_info.duplicated(keep=False)
0    False
1    False
2    False
3     True
4     True
5    False
dtype: bool
# 检测person_info中是否有重复的行
# subset=['height','gender'], keep=False
person_info.duplicated(subset=['height','gender'],keep=False)
0    False
1    False
2     True
3     True
4     True
5    False
dtype: bool

5.3.2 重复值的处理

重复值的一般处理方式是删除,pandas中使用drop_duplicates()方法删除重复值。

语法格式:

DataFrame.drop_duplicates(subset=None, keep=‘first’, inplace=False,
ignore_index=False)

参数说明:

  • keep:表示采用哪种方式保留重复项,该参数可以取值为’first’(默认值)、 'last ‘和’False’.
    • 'first’代表删除重复项,仅保留第一次出现的数据项;
    • 'last '代表删除重复项,仅保留最后一次出现的数据项;
    • 'False’表示删除所有的重复项。
  • inplace:表示是否放弃副本数据,返回新的数据,默认为False。
  • ignore_index:表示是否对删除重复值后的对象的行索引重新排序,默认为Flase。
person_info
nameageheightgender
0刘婷婷24162
1王淼23165
2彭岩29175
3刘华22175
4刘华22175
5周华27178
# 删除person_info对象的重复值
# subset=None, keep='first', inplace=False,ignore_index=False
person_info.drop_duplicates()
nameageheightgender
0刘婷婷24162
1王淼23165
2彭岩29175
3刘华22175
5周华27178
person_info
nameageheightgender
0刘婷婷24162
1王淼23165
2彭岩29175
3刘华22175
4刘华22175
5周华27178
# 删除person_info对象的重复值
# subset=None, keep='first', inplace=False,ignore_index=True
person_info.drop_duplicates(ignore_index=True)
nameageheightgender
0刘婷婷24162
1王淼23165
2彭岩29175
3刘华22175
4周华27178
# 删除person_info对象的重复值
# subset=None, keep='first', inplace=True,ignore_index=True
person_info.drop_duplicates(inplace=True,ignore_index=True)
person_info
nameageheightgender
0刘婷婷24162
1王淼23165
2彭岩29175
3刘华22175
4周华27178
# 删除person_info对象的重复值
# subset=['height','gender'], keep=False, inplace=False,ignore_index=False
person_info.drop_duplicates(subset=['height','gender'],keep=False,ignore_index=False)
nameageheightgender
0刘婷婷24162
1王淼23165
4周华27178

5.4 异常值的处理:

  • 删除带异常值的记录
  • 保留带异常值的记录
  • 替换掉记录中的异常值

5.4.1 异常值的检测

5.4.1.1 3σ原则

3σ原则,又称为拉依达原则,它是先假设一组检测数据只含有随机误差,对该组数据进行计算处理得到标准偏差,按一定概率确定一个区间,凡是超过这个区间的误差不属于随机误差而是粗大误差,含有粗大误差范围内的数据(视为异常值)应予以剔除

  • 3σ原则并不适用于任意数据集,而只适用于符合或近似正态分布的数据集。
  • 正态分布也称高斯分布,是统计学中十分重要的概率分布,它有两个比较重要的参数:μ和σ,其中μ是遵从正态分布的随机变量(值无法预先确定仅以一定的概率取值的变量)的均值,σ是此随机变量的标准差。
    在这里插入图片描述

实例:3σ原则检测数据data.xlsx里面的异常值

import numpy as np
import pandas as pd

def three_sigma(ser):
    """
    ser参数:被检测的数据,是一个Series
    返回值:异常值及其对应的行索引
    """
    
    # 计算平均值
    mean_data = ser.mean()
    # 计算标准差sigma
    std_data = ser.std()
    
    #小于(均值-3倍标准差) 或者 大于 (均值+3倍标准差)的数值都是异常的
    rule = ((mean_data-3*std_data)>ser) | ((mean_data+3*std_data)<ser)
    
    # 返回异常值的行索引
    index = np.arange(ser.shape[0])[rule]
    # 获取异常值
    outliers = ser.iloc[index]
    return outliers
    
    
# 读data.xlsx
excel_data = pd.read_excel('data.xlsx',index_col=0)
excel_data
value
012.7
19.9
210.2
310.6
48.6
......
99510.3
99610.1
99710.0
9989.3
9999.9

1000 rows × 1 columns

three_sigma(excel_data['value'])
121    13.2
710    13.1
Name: value, dtype: float64
5.4.1.2 箱形图异常值检测。

除了使用3σ原则检测异常值之外,还可以使用箱形图检测异常值。
需要说明的是,箱形图对检测数据没有任何要求,即使不符合正态分布的数据集是能被检测的。
箱形图是一种用于显示一组数据分散情况的统计图,它通常由上边缘、上四分位数、中位数、下四分位数、下边缘和异常值组成。箱形图能直观地反映出一组数据的分散情况,一旦图中出现离群点(远离大多数值的点),就认为该离群点可能为异常值。
在这里插入图片描述

5.4.1.2.1 箱形图的绘制。

为了能够直观地从箱形图中查看异常值,pandas中提供了两个绘制箱形图的函数:plot()boxplot(),其中plot()函数用于根据Series和DataFrame类对象绘制箱形图,该箱形图中默认不会显示网格线; boxplot()函数用于根据DataFrame类对象绘制箱形图,该箱形图中默认会显示网格线。

语法格式:

DataFrame.boxplot(column=None, by=None, ax=None, fontsize=None,
rot=0, grid=True, figsize=None, layout=None, return_type=None,
backend=None, **kwargs)

参数说明:

  • column,默认为None,输入为str 或由str构成的list,其作用是指定要进行箱型图分析的列
  • by,默认为None,str or array-like,其作用为pandas的group by,通过指定by=‘columns’,可进行多组合箱型图分析
  • ax,matplotlib.axes.Axes的对象,没有太大作用
  • fontsize,箱型图坐标轴字体大小
  • rot,箱型图坐标轴旋转角度
  • grid,箱型图网格线是否显示
  • figsize,箱型图窗口尺寸大小
  • layout,必须配合by 一起使用,类似于subplot 的画布分区域功能
  • return_type,指定返回对象的类型,默认为None,可输入的参数为‘axes’,‘dict’,‘both’,当与by一起使用是,返回的对象为Series或array(for return_type = None)
import pandas as pd

# 读data.xlsx
excel_data = pd.read_excel('data.xlsx',index_col=0)
excel_data.boxplot(column='value')
<AxesSubplot:>

在这里插入图片描述

5.4.1.2.2 利用箱形图检测异常值
import pandas as pd
import numpy as np

def box_outliers(ser):
    # 对待检测的数据集进行排序
    new_ser = ser.sort_values()
    # 判断待检测数据集数的个数数偶数还是奇数
    if new_ser.count() %2==0:
        #计算Q3,Q1
        Q3 = new_ser[int(len(new_ser)/2):].median()
        Q1 = new_ser[:int(len(new_ser)/2)].median()
    else:
        #计算Q3,Q1
        Q3 = new_ser[int((len(new_ser)-1)/2):].median()
        Q1 = new_ser[:int((len(new_ser)-1)/2)].median()
        
    #计算IQR
    IQR = round(Q3-Q1,1)
    # 制定异常值规则
    rule = (round(Q3+1.5*IQR,1)<ser)|(round(Q1-1.5*IQR,1)>ser)
    
    # 返回异常值的行索引
    index = np.arange(ser.shape[0])[rule]
    # 获取异常值
    outliers = ser.iloc[index]
    return outliers
                         
# 读data.xlsx
excel_data = pd.read_excel('data.xlsx',index_col=0)
box_outliers(excel_data['value'])
0      12.7
121    13.2
255    12.7
353    13.0
694    12.8
710    13.1
724    12.9
Name: value, dtype: float64

5.4.2 异常值的处理

异常值被检测出来之后,需要进一步确认其是否为真正的异常值,等确认完之后再选用合适的方式进行处理。异常值有3种处理方式,分别为:

  • 保留异常值
  • 删除异常值
  • 替换异常值
5.4.2.1 删除异常值

pandas中提供了删除数据的drop()方法,使用该方法可以根据指定的行标签索引或列标签索引来删除异常值。

语法格式:

DataFrame.drop(labels=None, axis=0, index=None, columns=None, level=None,
inplace=False, errors=‘raise’)

参数说明:

  • labels:表示要删除行标签索引或列标签索引,可以是一个或多个。
  • axis:指定删除行或删除列,其中0或index表示删除行;1或columns表示删除列。
  • index:指定要删除的行。
  • columns:指定要删除的列。
# 根据行索引进行删除
# 前面根据3σ原则检测到的异常的行时121,710行
clean_data = excel_data.drop([121,710])
# 对清理后的干净数据再次使用3σ检测
three_sigma(clean_data['value'])
Series([], Name: value, dtype: float64)
5.4.2.2 替换异常值

pandas中提供了替换值的replace()方法,replace()方法可以对单个或多个值进行替换。

语法格式:

DataFrame.replace(to_replace=None, value=None, inplace=False, limit=None, regex=False, method=‘pad’)

参数说明:

  • to_replace:被替换的值
  • value:替换后的值
  • inplace:是否要改变原数据,False是不改变,True是改变,默认是False
  • limit:控制填充次数
  • regex:是否使用正则,False是不使用,True是使用,默认是False
  • method:填充方式,pad,ffill,bfill分别是向前、向前、向后填充。
# 前面根据箱形图方法检测到的异常的行:
“”“
0      12.7
121    13.2
255    12.7
353    13.0
694    12.8
710    13.1
724    12.9
”“”

# 按值替换
replace_data = excel_data.replace({13.2:10.2,13.1:10.5})
#查看替换后的值
print(replace_data.loc[121])
value    10.2
Name: 121, dtype: float64
print(replace_data.loc[710])
value    10.5
Name: 710, dtype: float64
# 替换后再用箱型图方法检测异常值
box_outliers(replace_data['value'])
0      12.7
255    12.7
353    13.0
694    12.8
724    12.9
Name: value, dtype: float64
5.4.2.3 补充对pandas的.replace()方法详解

0. 准备数据

import requests
import pandas as pd 

html_data = requests.get("http://www.weather.com.cn/textFC/hb.shtml")
html_tables = pd.read_html(html_data.content,header=0)
tqDf = html_tables[5]
tqDf
省/直辖市城市周二(4月19日)白天周二(4月19日)白天.1周二(4月19日)白天.2周二(4月19日)夜间周二(4月19日)夜间.1周二(4月19日)夜间.2Unnamed: 8
0省/直辖市城市天气现象风向风力最高气温天气现象风向风力最低气温NaN
1北京北京西南风 <3级27西南风 3-4级13详情
2北京海淀南风 3-4级27西南风 3-4级13详情
3北京朝阳西南风 <3级27西南风 3-4级11详情
4北京顺义南风 <3级27西南风 3-4级13详情
5北京怀柔西南风 <3级28西南风 <3级10详情
6北京通州西南风 <3级27西南风 3-4级11详情
7北京昌平南风 <3级28北风 <3级11详情
8北京延庆西风 <3级24西风 <3级8详情
9北京丰台西南风 3-4级27西南风 3-4级12详情
10北京石景山南风 3-4级26西南风 <3级12详情
11北京大兴西南风 <3级27西南风 3-4级12详情
12北京房山西南风 <3级27西南风 <3级12详情
13北京密云南风 <3级27东南风 <3级10详情
14北京门头沟南风 3-4级26西南风 <3级12详情
15北京平谷西南风 <3级27南风 <3级11详情
16北京东城西南风 <3级27西南风 3-4级11详情
17北京西城南风 3-4级27西南风 3-4级13详情
tqDf.columns
Index(['省/直辖市', '城市', '周二(4月19日)白天', '周二(4月19日)白天.1', '周二(4月19日)白天.2',
       '周二(4月19日)夜间', '周二(4月19日)夜间.1', '周二(4月19日)夜间.2', 'Unnamed: 8'],
      dtype='object')
5.4.2.3.1 替换全部的某个值

replace的基本结构是:python df.replace(to_replace, value)前面是需要替换的值,后面是替换后的值。

# 将“西南风<3级”替换为“微风”
tqDf.replace("西南风 <3级","微风")
省/直辖市城市周二(4月19日)白天周二(4月19日)白天.1周二(4月19日)白天.2周二(4月19日)夜间周二(4月19日)夜间.1周二(4月19日)夜间.2Unnamed: 8
0省/直辖市城市天气现象风向风力最高气温天气现象风向风力最低气温NaN
1北京北京微风27西南风 3-4级13详情
2北京海淀南风 3-4级27西南风 3-4级13详情
3北京朝阳微风27西南风 3-4级11详情
4北京顺义南风 <3级27西南风 3-4级13详情
5北京怀柔微风28微风10详情
6北京通州微风27西南风 3-4级11详情
7北京昌平南风 <3级28北风 <3级11详情
8北京延庆西风 <3级24西风 <3级8详情
9北京丰台西南风 3-4级27西南风 3-4级12详情
10北京石景山南风 3-4级26微风12详情
11北京大兴微风27西南风 3-4级12详情
12北京房山微风27微风12详情
13北京密云南风 <3级27东南风 <3级10详情
14北京门头沟南风 3-4级26微风12详情
15北京平谷微风27南风 <3级11详情
16北京东城微风27西南风 3-4级11详情
17北京西城南风 3-4级27西南风 3-4级13详情

要注意这样的操作并没有改变文档的源数据,要改变源数据需要使用inplace = True

5.4.2.3.2 替换全部的多个值
  • 采用字典的形式,字典的key是要替换的值,value是替换后的值
  • 采用列表的形式,前面列表保存原值,后面列表保存新值。
# 将“西南风<3级”替换为“微风”,将"西南风3-4级”替换为“小风"
tqDf.replace({"西南风 <3级":"微风","西南风 3-4级":"小风"})
省/直辖市城市周二(4月19日)白天周二(4月19日)白天.1周二(4月19日)白天.2周二(4月19日)夜间周二(4月19日)夜间.1周二(4月19日)夜间.2Unnamed: 8
0省/直辖市城市天气现象风向风力最高气温天气现象风向风力最低气温NaN
1北京北京微风27小风13详情
2北京海淀南风 3-4级27小风13详情
3北京朝阳微风27小风11详情
4北京顺义南风 <3级27小风13详情
5北京怀柔微风28微风10详情
6北京通州微风27小风11详情
7北京昌平南风 <3级28北风 <3级11详情
8北京延庆西风 <3级24西风 <3级8详情
9北京丰台小风27小风12详情
10北京石景山南风 3-4级26微风12详情
11北京大兴微风27小风12详情
12北京房山微风27微风12详情
13北京密云南风 <3级27东南风 <3级10详情
14北京门头沟南风 3-4级26微风12详情
15北京平谷微风27南风 <3级11详情
16北京东城微风27小风11详情
17北京西城南风 3-4级27小风13详情
# 将“西南风<3级”替换为“微风”,将"西南风3-4级”替换为“小风"
tqDf.replace(["西南风 <3级","西南风 3-4级"],["微风","小风"])
省/直辖市城市周二(4月19日)白天周二(4月19日)白天.1周二(4月19日)白天.2周二(4月19日)夜间周二(4月19日)夜间.1周二(4月19日)夜间.2Unnamed: 8
0省/直辖市城市天气现象风向风力最高气温天气现象风向风力最低气温NaN
1北京北京微风27小风13详情
2北京海淀南风 3-4级27小风13详情
3北京朝阳微风27小风11详情
4北京顺义南风 <3级27小风13详情
5北京怀柔微风28微风10详情
6北京通州微风27小风11详情
7北京昌平南风 <3级28北风 <3级11详情
8北京延庆西风 <3级24西风 <3级8详情
9北京丰台小风27小风12详情
10北京石景山南风 3-4级26微风12详情
11北京大兴微风27小风12详情
12北京房山微风27微风12详情
13北京密云南风 <3级27东南风 <3级10详情
14北京门头沟南风 3-4级26微风12详情
15北京平谷微风27南风 <3级11详情
16北京东城微风27小风11详情
17北京西城南风 3-4级27小风13详情
5.4.2.3.3 替换某列里的内容,而不改变其它列
# 仅将'周二(4月19日)白天.1'列里面的“西南风<3级”替换为“微风”
tmpDf = tqDf.copy()
tmpDf['周二(4月19日)白天.1'].replace("西南风 <3级","微风",inplace=True)
tmpDf
省/直辖市城市周二(4月19日)白天周二(4月19日)白天.1周二(4月19日)白天.2周二(4月19日)夜间周二(4月19日)夜间.1周二(4月19日)夜间.2Unnamed: 8
0省/直辖市城市天气现象风向风力最高气温天气现象风向风力最低气温NaN
1北京北京微风27西南风 3-4级13详情
2北京海淀南风 3-4级27西南风 3-4级13详情
3北京朝阳微风27西南风 3-4级11详情
4北京顺义南风 <3级27西南风 3-4级13详情
5北京怀柔微风28西南风 <3级10详情
6北京通州微风27西南风 3-4级11详情
7北京昌平南风 <3级28北风 <3级11详情
8北京延庆西风 <3级24西风 <3级8详情
9北京丰台西南风 3-4级27西南风 3-4级12详情
10北京石景山南风 3-4级26西南风 <3级12详情
11北京大兴微风27西南风 3-4级12详情
12北京房山微风27西南风 <3级12详情
13北京密云南风 <3级27东南风 <3级10详情
14北京门头沟南风 3-4级26西南风 <3级12详情
15北京平谷微风27南风 <3级11详情
16北京东城微风27西南风 3-4级11详情
17北京西城南风 3-4级27西南风 3-4级13详情
5.4.2.3.4 替换某行内容
#仅替换index=3行(朝阳区)的“西南风<3级”替换为“微风”
tmpDf = tqDf.copy()
tmpDf.iloc[3].replace("西南风 <3级","微风",inplace=True)
tmpDf
省/直辖市城市周二(4月19日)白天周二(4月19日)白天.1周二(4月19日)白天.2周二(4月19日)夜间周二(4月19日)夜间.1周二(4月19日)夜间.2Unnamed: 8
0省/直辖市城市天气现象风向风力最高气温天气现象风向风力最低气温NaN
1北京北京西南风 <3级27西南风 3-4级13详情
2北京海淀南风 3-4级27西南风 3-4级13详情
3北京朝阳微风27西南风 3-4级11详情
4北京顺义南风 <3级27西南风 3-4级13详情
5北京怀柔西南风 <3级28西南风 <3级10详情
6北京通州西南风 <3级27西南风 3-4级11详情
7北京昌平南风 <3级28北风 <3级11详情
8北京延庆西风 <3级24西风 <3级8详情
9北京丰台西南风 3-4级27西南风 3-4级12详情
10北京石景山南风 3-4级26西南风 <3级12详情
11北京大兴西南风 <3级27西南风 3-4级12详情
12北京房山西南风 <3级27西南风 <3级12详情
13北京密云南风 <3级27东南风 <3级10详情
14北京门头沟南风 3-4级26西南风 <3级12详情
15北京平谷西南风 <3级27南风 <3级11详情
16北京东城西南风 <3级27西南风 3-4级11详情
17北京西城南风 3-4级27西南风 3-4级13详情
#仅替换index=[3:6]行(朝阳区、顺义区、怀柔区)的“西南风<3级”替换为“微风”
tmpDf = tqDf.copy()
tmpDf.iloc[3:6].replace("西南风 <3级","微风",inplace=True)
tmpDf
D:\ProgramFiles\Anaconda3\lib\site-packages\pandas\core\frame.py:5244: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  method=method,
省/直辖市城市周二(4月19日)白天周二(4月19日)白天.1周二(4月19日)白天.2周二(4月19日)夜间周二(4月19日)夜间.1周二(4月19日)夜间.2Unnamed: 8
0省/直辖市城市天气现象风向风力最高气温天气现象风向风力最低气温NaN
1北京北京西南风 <3级27西南风 3-4级13详情
2北京海淀南风 3-4级27西南风 3-4级13详情
3北京朝阳微风27西南风 3-4级11详情
4北京顺义南风 <3级27西南风 3-4级13详情
5北京怀柔微风28微风10详情
6北京通州西南风 <3级27西南风 3-4级11详情
7北京昌平南风 <3级28北风 <3级11详情
8北京延庆西风 <3级24西风 <3级8详情
9北京丰台西南风 3-4级27西南风 3-4级12详情
10北京石景山南风 3-4级26西南风 <3级12详情
11北京大兴西南风 <3级27西南风 3-4级12详情
12北京房山西南风 <3级27西南风 <3级12详情
13北京密云南风 <3级27东南风 <3级10详情
14北京门头沟南风 3-4级26西南风 <3级12详情
15北京平谷西南风 <3级27南风 <3级11详情
16北京东城西南风 <3级27西南风 3-4级11详情
17北京西城南风 3-4级27西南风 3-4级13详情
5.4.2.3.5 使用正则表达式替换

正则表达式很强大,能够让我们实现一次替换很多很多个不同的值

# 把气温数字27或28标注为“高温”
tmpDf = tqDf.copy()
tmpDf.replace("[2][78]","高温", regex = True, inplace = True)
tmpDf
省/直辖市城市周二(4月19日)白天周二(4月19日)白天.1周二(4月19日)白天.2周二(4月19日)夜间周二(4月19日)夜间.1周二(4月19日)夜间.2Unnamed: 8
0省/直辖市城市天气现象风向风力最高气温天气现象风向风力最低气温NaN
1北京北京西南风 <3级高温西南风 3-4级13详情
2北京海淀南风 3-4级高温西南风 3-4级13详情
3北京朝阳西南风 <3级高温西南风 3-4级11详情
4北京顺义南风 <3级高温西南风 3-4级13详情
5北京怀柔西南风 <3级高温西南风 <3级10详情
6北京通州西南风 <3级高温西南风 3-4级11详情
7北京昌平南风 <3级高温北风 <3级11详情
8北京延庆西风 <3级24西风 <3级8详情
9北京丰台西南风 3-4级高温西南风 3-4级12详情
10北京石景山南风 3-4级26西南风 <3级12详情
11北京大兴西南风 <3级高温西南风 3-4级12详情
12北京房山西南风 <3级高温西南风 <3级12详情
13北京密云南风 <3级高温东南风 <3级10详情
14北京门头沟南风 3-4级26西南风 <3级12详情
15北京平谷西南风 <3级高温南风 <3级11详情
16北京东城西南风 <3级高温西南风 3-4级11详情
17北京西城南风 3-4级高温西南风 3-4级13详情
5.4.2.3.6 使用条件替换
# 判断[“周二(4月19日)白天.1”] 列的字符串为 “西南风 <3级"时,将本行的 [“Unnamed: 8”]列,替换为”西南风,微风"
tmpDf = tqDf.copy()
tmpDf.loc[tmpDf["周二(4月19日)白天.1"]=="西南风 <3级","Unnamed: 8"]="西南风,微风"
tmpDf
省/直辖市城市周二(4月19日)白天周二(4月19日)白天.1周二(4月19日)白天.2周二(4月19日)夜间周二(4月19日)夜间.1周二(4月19日)夜间.2Unnamed: 8
0省/直辖市城市天气现象风向风力最高气温天气现象风向风力最低气温NaN
1北京北京西南风 <3级27西南风 3-4级13西南风,微风
2北京海淀南风 3-4级27西南风 3-4级13详情
3北京朝阳西南风 <3级27西南风 3-4级11西南风,微风
4北京顺义南风 <3级27西南风 3-4级13详情
5北京怀柔西南风 <3级28西南风 <3级10西南风,微风
6北京通州西南风 <3级27西南风 3-4级11西南风,微风
7北京昌平南风 <3级28北风 <3级11详情
8北京延庆西风 <3级24西风 <3级8详情
9北京丰台西南风 3-4级27西南风 3-4级12详情
10北京石景山南风 3-4级26西南风 <3级12详情
11北京大兴西南风 <3级27西南风 3-4级12西南风,微风
12北京房山西南风 <3级27西南风 <3级12西南风,微风
13北京密云南风 <3级27东南风 <3级10详情
14北京门头沟南风 3-4级26西南风 <3级12详情
15北京平谷西南风 <3级27南风 <3级11西南风,微风
16北京东城西南风 <3级27西南风 3-4级11西南风,微风
17北京西城南风 3-4级27西南风 3-4级13详情
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值