[Python] 数据预处理(缺失值、异常值、重复值) [相关方法参数说明、代码示例、相关概念](三)

简介: [Python] 数据预处理(缺失值、异常值、重复值) [相关方法参数说明、代码示例、相关概念](三)

1.2.3 使用平均值填补缺失值

调用 fillna() 方法,使用每列的平均值对数据表中对应列的缺失值进行填补。

  • mean():
  • 获取调用该方法的数据集的一行或一列的平均值。
  • axis:轴向,默认 axis=0 计算每列的算数平均数,axis=1 计算每行的算数平均数。

经过验证,调用 mean() 方法计算列的均值,空值(缺失值)不会计算在内。

# 包的导入
import pandas as pd
import numpy as np
# 读取数据
data = pd.read_excel('../../监测点C逐小时污染物浓度与气象实测数据.xlsx')
# 由于表格中的部分缺失值使用字符串类型的'—' 'NULL' 'NA' 表示
# 所有先对这些数据进行处理
def fun(x):
  if (x=='—' or x=='NULL' or x=='NA'): return np.nan
  else: return x
# applymap() 方法会遍历并处理表格中每个单元格的数据
# fun 为传入的函数参数,用于处理每个单元格
# fun 函数会接收一个参数,为表格中每个单元格的数据
data = data.applymap(fun)
# 使用每列的均值对每列中的缺失值进行填补
# def fun_mean(col):
#   如果当前列是第二列直接退出函数
#   第二列的数据为字符串类型
#   if (col.name == '地点'): return col
#   col.fillna(value=col.mean(), inplace=True)
#   return col
# re = data.apply(fun_mean)
# 循环处理第三列及往后的每列
# 使用每列的均值对每列中的缺失值进行填补
for col_name in data.columns[2:]:
  # 当前要处理的列
  col = data[col_name]
  # 使用当前列的均值填补缺失值
  col.fillna(value=col.mean(), inplace=True)
  # 更新原数据表
  data[col_name] = col
data

返回文章目录

1.2.4 使用众数填补缺失值

调用 fillna() 方法,使用每列的众数对数据表中对应列的缺失值进行填补。

  • mode():
  • 获取调用该方法的数据集的一行或一列的众数。如果个数最多的取值存在多个,则返回多个值。
  • axis:轴向,默认 axis=0 获取每列的众数,axis=1 获取每行的众数。

湿度这一列的取值情况如下:

# 包的导入
import pandas as pd
import numpy as np
# 读取数据
data = pd.read_excel('../../监测点C逐小时污染物浓度与气象实测数据.xlsx')
# 由于表格中的部分缺失值使用字符串类型的'—' 'NULL' 'NA' 表示
# 所有先对这些数据进行处理
def fun(x):
  if (x=='—' or x=='NULL' or x=='NA'): return np.nan
  else: return x
# applymap() 方法会遍历并处理表格中每个单元格的数据
# fun 为传入的函数参数,用于处理每个单元格
# fun 函数会接收一个参数,为表格中每个单元格的数据
data = data.applymap(fun)
# 使用每列的众数对每列中的缺失值进行填补
def fun_(col):
  # 获取第一个众数填补缺失值
  col.fillna(value=col.mode()[0], inplace=True)
  return col
re = data.apply(fun_)
re

返回文章目录

1.2.5 使用中位数填补缺失值

调用 fillna() 方法,使用每列的中位数对数据表中对应列的缺失值进行填补。

  • median():
  • 获取调用该方法的数据集的一行或一列的中位数。
  • axis:轴向,默认 axis=0 获取每列的中位数,axis=1 获取每行的中位数。

湿度这一列的中位数如下:

# 包的导入
import pandas as pd
import numpy as np
# 读取数据
data = pd.read_excel('../../监测点C逐小时污染物浓度与气象实测数据.xlsx')
# 由于表格中的部分缺失值使用字符串类型的'—' 'NULL' 'NA' 表示
# 所有先对这些数据进行处理
def fun(x):
  if (x=='—' or x=='NULL' or x=='NA'): return np.nan
  else: return x
# applymap() 方法会遍历并处理表格中每个单元格的数据
# fun 为传入的函数参数,用于处理每个单元格
# fun 函数会接收一个参数,为表格中每个单元格的数据
data = data.applymap(fun)
# 使用每列的中位数对每列中的缺失值进行填补
def fun_(col):
  # 如果当前列是第二列直接退出函数
  # 第二列的数据为字符串类型
  if (col.name == '地点'): return col
  col.fillna(value=col.median(), inplace=True)
  return col
re = data.apply(fun_)
re

返回文章目录

1.2.6 使用缺失值前一个与后一个非缺失值的均值填补

调用 interpolate() 方法,使用每列的缺失值前一个与后一个非缺失值的均值对数据表中对应列的缺失值进行填补。

如果第一行就存在缺失值,则本方法不适用,缺失值不会被填补,仍然为 NaN。

当前的测试数据如下:

# 包的导入
import pandas as pd
import numpy as np
# 读取数据
data = pd.read_excel('../../1.xlsx')
# 由于表格中的部分缺失值使用字符串类型的'—' 'NULL' 'NA' 表示
# 所有先对这些数据进行处理
def fun(x):
  if (x=='—' or x=='NULL' or x=='NA'): return np.nan
  else: return x
# applymap() 方法会遍历并处理表格中每个单元格的数据
# fun 为传入的函数参数,用于处理每个单元格
# fun 函数会接收一个参数,为表格中每个单元格的数据
data = data.applymap(fun)
# 使用每列的缺失值前一个与后一个非缺失值的均值
# 对每列中的缺失值进行填补
def fun_(col):
  # 第一列为时间类型直接退出函数
  if (col.name == '实测日期'): return col
  # 如果当前列是第二列直接退出函数
  # 第二列的数据为字符串类型
  if (col.name == '地点'): return col
  # col = col.interpolate()
  # 直接修改原数据
  col.interpolate(inplace=True)
  return col
re = data.apply(fun_)
re

返回文章目录

1.2.7 使用拉格朗日插值法对缺失值进行填补

以下内容来自:

[1]赵莉,孙娜,李丽萍,崔杰.拉格朗日插值法在数据清洗中的应用[J].辽宁工业大学学报(自然科学版),2022,42(02):102-105+117.DOI:10.15916/j.issn1674-3261.2022.02.007.

文献知网连接

返回文章目录

1.2.7.1 拉格朗日插值法

拉格朗日多项式插值法的基本思想是:给出一个恰好穿过二维平面上几个已知点的多项式,利用最小次数的多项式来构建一条光滑曲线,使曲线通

过所有已知点。


image.png

image.png

image.png

将 x=18 代入可以得到 L(18)=-11,因此缺失的值是-11。

返回文章目录

1.2.7.2 代码

当前将要进行缺失值填补的数据:

为了防止取缺失值前后的非缺失值时索引越界,对文献中的代码进行了修改

import numpy as np
import pandas as pd
# 引入拉格朗日插值法所需的方法
from scipy.interpolate import lagrange
# 文件读取
data = pd.read_excel('../../1.xlsx')
# 字符串表示的空值预处理
def fun(x):
  if (x=='—' or x=='NULL' or x=='NA'): return np.nan
  else: return x
data = data.applymap(fun)
# 生成拉格朗日插值
def interpolate_columns(data_col, missing_val_idx, k=5):
  """
  data_col: 需要进行缺失值填补的列
  missing_val_idx: 数据缺失的单元格在该列对应的索引
  k: 缺失值前后取值的个数, 默认为5个
  return: 返回拉格朗日插值
  """
  # 防止取缺失值前后的非缺失值时下标越界
  # 向缺失值前取值的个数,默认为 k
  f_k = k
  # 如果缺失值前还有的数值个数小于 k
  # 更改取值个数
  if(missing_val_idx < k): f_k = missing_val_idx
  # 向缺失值后取值的个数,默认为 k
  b_k = k
  # 如果缺失值后还有的数值个数小于 k
  # 更改取值个数
  if((data_col.size-missing_val_idx-1) < k): b_k = data_col.size-missing_val_idx-1
  # 获取二者的较小值
  if(f_k <= b_k): k = f_k
  else: k = b_k
  # 取出当前缺失值位置前后 k 个值
  y = data_col[ 
    list(range(missing_val_idx-k, missing_val_idx))  + list(range(missing_val_idx+1, missing_val_idx+1+k)) 
  ]
  # 去除空值
  y = y[ y.notnull() ]
  # 生成拉格朗日插值函数
  f = lagrange(y.index, list(y))
  # 计算并返回缺失值将要填补的数据值
  return f(missing_val_idx)
# 遍历数据表
# 每列
for i in data.columns[2:]:
  # 遍历每列中的每个单元格
  for j in range(data[i].size):
    # 如果单元格为空
    # 进行拉格朗日插值
    if data[i].isnull()[j]:
      data[i][j] = interpolate_columns(data[i], j)
data

此代码无法对数据表第一行与最后一行存在的缺失值进行填补,由于代码修改,当缺失值在第一行或最后一行时,取缺失值前后的非缺失值的个数为0,所以无法使用拉格朗日插值法进行数据的填补。

文献中的代码:

返回文章目录

1.2.8 使用预测模型对缺失值进行填补

预测模型较多,后面补上

返回文章目录

2. 异常值处理

返回文章目录

2.1 异常值的检测

  • 检查数据集中的异常值,常用的方法有:
  • 3σ 准则(拉依达准则)
  • 箱线图检测

返回文章目录

2.1.1 3σ 准则(拉依达准则)

相关概念

3σ(西格玛)准则(拉依达准则) 是指先假设一组检测数据只含有随机误差,对其进行计算处理得到标准偏差,按一定概率确定一个区间,认为凡超过这个区间的误差,就不属于随机误差而是粗大误差,含有该误差的数据应予以剔除。

这种判别处理原理及方法 仅局限于对正态或近似正态分布 的样本数据处理,它是 以测量次数充分大为前提 的,当测量次数少的情形用准则剔除粗大误差是不够可靠的。因此,在测量次数较少的情况下,最好不要选用该准则

来源于百度百科 链接

在正态分布中:

符号 说明
μ  数学期望(均值)
σ 2  方差
σ  标准差

image.png


“小概率事件”和假设检验的基本思想:“小概率事件” 通常指发生的概率小于5% 的事件,认为在一次试验中该事件是 几乎不可能发生 的。由此可见 X落在(μ-3σ,μ+3σ)以外 的概率小于千分之三,在实际问题中常认为相应的事件 不会发生 ,基本上可以把区间(μ-3σ,μ+3σ)看作是随机变量X实际可能的取值区间,这称之为正态分布的“3σ”原则

来源于百度百科 链接


image.png

image.png


在整理试验数据时,往往会遇到这样的情况,即在一组试验数据里,发现少数几个偏差特别大的可疑数据,这类数据称为 Outlier 或 Exceptional Data ,他们往往是由于过失误差引起。

来源于百度百科 链接

数据分布图绘制
  • seaborn.distplot():
  • 参数:
  • a:接收一维数组或列表为参数,为绘制图形的数据。
  • hist:是否显示直方图,默认值为 True,默认情况下显示直方图。
  • kde:是否显示核密度估计,默认值为 True,默认情况下显示核密度估计。
  • bins:接收 int 或 list 类型的数据为参数,控制直方图的划分,即直方图有几柱。
  • rug:是否绘制变量的分布情况,默认值为 False,默认情况下不显示。
  • fit:
  • hist_kws:接收字典类型的数据为参数,设置绘制的直方图的显示样式。
  • kde_kws:接收字典类型的数据为参数,设置绘制的核密度估计的显示样式。
  • rug_kws:接收字典类型的数据为参数,设置绘制的变量分布情况的显示样式。
  • color:设置绘制图形的颜色。
  • vertical:绘制的图形x轴与y轴是否进行对调,绘制的图形显示在x轴还是y轴,默认值为False,显示在x轴。
  • norm_hist:控制直方图的高度(y轴)显示的是密度还是计数。在不含有核密度估计的图形中,默认为 False,显示的为计数。在含有核密度估计的图形中,默认为 True,显示的为密度。
  • axlabel:接收字符串类型的数据为参数,用于设置x轴的标签。
  • label:接收字符串类型的数据为参数,用于设置直方图的图例。
  • ax:seaborn.distplot() 会返回一个坐标轴对象,可以用于设置图形的四个坐标轴。

参考:

【Python可视化 | Seaborn之seaborn.distplot()】鹿港小小镇

【sns.distplot()用法】小小喽啰

数据文件名:

监测点A逐小时污染物浓度与气象实测数据_去除整行缺失_补全数据_去除负数.xlsx

这里只进行简单的测试,更加详细的测试【待写】

绘制 SO2监测浓度 的数据分布图

import pandas as pd
# 画图所需的包
import matplotlib.pyplot as plt
# 绘制数据分布图所需的包
import seaborn as sns
# 提高 matplotlib 在 jupyter 中作图的分辨率
%config InlineBackend.figure_format = 'retina'
# 处理中文与负号的显示问题
plt.rcParams['font.sans-serif'] = ['FangSong'] # 指定默认字体
plt.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题
# 读取数据
data = pd.read_excel('./监测点A逐小时污染物浓度与气象实测数据_去除整行缺失_补全数据_去除负数.xlsx')
# 修改列名
data.columns = ['监测时间', '地点', 'SO2监测浓度', 'NO2监测浓度', 'PM10监测浓度',
       'PM2.5监测浓度', 'O3监测浓度', 'CO监测浓度', '温度', '湿度',
       '气压', '风速', '风向']
# 绘制数据分布图
# ax 接收返回的坐标轴对象
ax = sns.distplot(
  # 绘制图形的数据
  data['SO2监测浓度'],
  # 直方图柱 20个 
  bins=20, 
  # 显示变量的分布情况
  rug=True,
  # 直方图样式设置
  hist_kws={
    'label': 'SO2监测浓度',
    'color': 'red'
  },
  # 核密度估计曲线样式设置
  kde_kws={
    'label': 'SO2监测浓度核密度估计',
    'color': 'green'
  },
  # 设置x轴的标签
  axlabel= r'$SO_{2}$'
)
# 取消上轴和右轴的显示
ax.spines['top'].set_color('none')
ax.spines['right'].set_color('none')
# 显示图例
plt.legend()
plt.show()

返回文章目录

2.1.2 箱线图检测

以下内容来自:

[1]孙向东,刘拥军,陈雯雯,贾智宁,黄保续.箱线图法在动物卫生数据异常值检验中的运用[J].中国动物检疫,2010,27(07):66-68.

知网文献链接

相关概念

箱线图(Boxplot)也称箱须图(Box-whisker Plot),是美国著名统计学家 John W. Tukey 于 1977 年发明的。箱线图法利用数据中的五个统计量:最小值、下四分位数(Q1)、中位数(Q2)、上四分位数(Q3)与最大值 来描述数据。

  • 箱线图可用于:
  • (1)鉴别数据中的异常值,包括离群值和极端值;
  • (2) 判断数据的偏态和尾重;
  • (3)比较几组数据的形状。

以下内容(本文)仅讨论其在异常值鉴别中的应用。

箱线图根据实际数据绘制,既 不需要事先假定数据服从特定的概率分布 ,也 没有对数据作任何限制性要求 ,能够真实、直观地表现数据形状的本来面貌。

箱线图判断异常值的标准以四分位数和四分位距为基础,较多数据的变化对四分位数影响不大,所以箱线图判断异常值的标准具有较强的鲁棒性(Robust),检测结果比较客观。

箱线图法采用中位数代替平均数检测异常值是统计检测方法上的一大改进。箱线图法能够有效克服数据中存在异常值时,不能测出异常值的这种掩盖效应(masking effect)。

箱线图的结构:

箱线图由参照系(坐标轴)、标志物(箱体、上下四分位线、中位线、异常值截断点)、检测数据(箱体两端的延伸线、异常值)三种成分构成,具体

见图1。

其中 箱体的两端分别对应下四分位数 Q1 和上四分位数 Q3Q1和 Q3之间称作四分位距 (Inter Quartile Range,IQR)。 上四分位点右边 1.5倍 IQR 和下四分位点左边 1.5 倍 IQR位置对应的点是异常值截断点 ,异常值截断点之间是内限。上四分位点右边 3 倍 IQR 和下四分位点左边 3 倍IQR 位置对应的点是极端值截断点,极端值截断点之间是外限。

异常值截断点以外的数据称作异常值 ,其中在内限与外限之间的异常值为温和异常值或离群值(Outlier,mild outliers),在外限以外的为极端异常值或极端值(Extreme,extreme outliers)。

箱线图的结构与标准正态分布函数 N(0, 1) 之间的比较见图2。

其中 Q3 与 Q1 之间包含了 50%的数据点,异常值截断点之间包含了 99.3%的数据点,非异常值误判为异常值的概率不大于 0.7%。

箱线图的结构图

箱线图绘制

以下博客对于绘制箱线图的方法参数介绍的很详细,这里不在进行介绍。

  • matplotlib.pyplot.boxplot()
将方法的参数及其说明复制在这:
x:指定要绘制箱线图的数据,可以是一组数据也可以是多组数据;
notch:是否以凹口的形式展现箱线图,默认非凹口;
sym:指定异常点的形状,默认为蓝色的+号显示;
vert:是否需要将箱线图垂直摆放,默认垂直摆放;
whis:指定上下须与上下四分位的距离,默认为1.5倍的四分位差;
positions:指定箱线图的位置,默认为range(1, N+1),N为箱线图的数量;
widths:指定箱线图的宽度,默认为0.5;
patch_artist:是否填充箱体的颜色,默认为False;
meanline:是否用线的形式表示均值,默认用点来表示;
showmeans:是否显示均值,默认不显示;
showcaps:是否显示箱线图顶端和末端的两条线,默认显示;
showbox:是否显示箱线图的箱体,默认显示;
showfliers:是否显示异常值,默认显示;
boxprops:设置箱体的属性,如边框色,填充色等;
labels:为箱线图添加标签,类似于图例的作用;即箱线图对应x轴点的名字
flierprops:设置异常值的属性,如异常点的形状、大小、填充色等;
medianprops:设置中位数的属性,如线的类型、粗细等;
meanprops:设置均值的属性,如点的大小、颜色等;
capprops:设置箱线图顶端和末端线条的属性,如颜色、粗细等;
whiskerprops:设置须的属性,如颜色、粗细、线的类型等;
manage_ticks:是否自适应标签位置,默认为True;
autorange:是否自动调整范围,默认为False;
  • seaborn.boxplot()
将方法的参数及其说明复制在这:
x, y, hue:数据或向量数据中的变量名称
用于绘制长格式数据的输入。
data:DataFrame,数组,数组列表
用于绘图的数据集。
如果x和y都缺失,那么数据将被视为宽格式。
否则数据被视为长格式。
order, hue_order:字符串列表
控制分类变量(对应的条形图)的绘制顺序,
若缺失则从数据中推断分类变量的顺序。
orient:“v”或“h”
控制绘图的方向(垂直或水平)。
这通常是从输入变量的 dtype 推断出来的,
但是当“分类”变量为数值型或绘制宽格式数据时
可用于指定绘图的方向。
color:matplotlib颜色
所有元素的颜色,或渐变调色板的种子颜色。
palette:调色板名称,列表或字典
用于hue变量的不同级别的颜色。
可以从color_palette()得到一些解释,
或者将色调级别映射到matplotlib颜色的字典。
saturation:float
控制用于绘制颜色的原始饱和度的比例。
通常大幅填充在轻微不饱和的颜色下看起来更好,
如果您希望绘图颜色与输入颜色规格完美匹配
可将其设置为1。
width:float
不使用色调嵌套时完整元素的宽度,
或主要分组变量一个级别的所有元素的宽度。
dodge:bool
使用色调嵌套时,元素是否应沿分类轴移动。
fliersize:float
用于表示异常值观察的标记的大小。
linewidth:float
构图元素的灰线宽度。
whis:float
控制在超过高低四分位数时 IQR (四分位间距)的比例,
因此需要延长绘制的触须线段。超出此范围的点将被识别为异常值。
notch:boolean
是否使矩形框“凹陷”以指示中位数的置信区间。
还可以通过plt.boxplot的一些参数来控制
ax:matplotlib轴
绘图时使用的 Axes 轴对象,否则使用当前 Axes 轴对象
kwargs:键值映射
其他在绘图时传给plt.boxplot的参数
设置方法与 plt.boxplot 一样

数据文件名:

监测点A逐小时污染物浓度与气象实测数据_去除整行缺失_补全数据_去除负数.xlsx

绘制 SO2监测浓度 的箱线图

测试一些经常会使用的参数和参数的常用设置

matplotlib.pyplot.boxplot()

import pandas as pd
# 画图所需的包
import matplotlib.pyplot as plt
# 提高 matplotlib 在 jupyter 中作图的分辨率
%config InlineBackend.figure_format = 'retina'
# 处理中文与负号的显示问题
plt.rcParams['font.sans-serif'] = ['FangSong'] # 指定默认字体
plt.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题
# 读取数据
data = pd.read_excel('./监测点A逐小时污染物浓度与气象实测数据_去除整行缺失_补全数据_去除负数.xlsx')
# 修改列名
data.columns = ['监测时间', '地点', 'SO2监测浓度', 'NO2监测浓度', 'PM10监测浓度',
       'PM2.5监测浓度', 'O3监测浓度', 'CO监测浓度', '温度', '湿度',
       '气压', '风速', '风向']
# 绘制箱线图
plt.boxplot(
  # 绘图数据
  data['SO2监测浓度'],
  # 箱子是否内凹
  # notch=True,
  # 设置异常点的形状
  # sym='.',
  # 填充箱体颜色
  patch_artist=True,
  # 显示平均值,默认使用点显示
  showmeans=True,
  # 设置箱子的宽度
  widths=0.1,
  # 设置箱子的样式,需要 patch_artist=True
  boxprops={
    # 箱子的边框为灰色
    'color': 'gray',
    # 箱子的填充色为橙色
    'facecolor': 'orange',
    # 设置边框线的宽度
    'linewidth': '2'
  },
  # 设置异常值点的样式
  flierprops={
    # 设置点的形状
    'marker': '.',
    # 设置点的填充色
    'markerfacecolor': 'blue',
    # 设置点的边框色
    'markeredgecolor': 'blue',
    # 设置点的大小
    'markersize': '2'
  },
  # 添加箱线图在x轴对应位置的名字
  # x轴坐标点名
  labels=['SO2监测浓度'],
  # 设置须的样式
  whiskerprops={
    # 设置线的颜色
    'color': 'green'
  },
  # 设置箱线图最值线的样式
  capprops={
    # 设置线的颜色
    'color': 'red',
    # 设置线的宽度
    'linewidth': '3'
  }
)
plt.grid(linestyle=':')
# 显示图例
plt.legend()
plt.show()

绘制 所有列 的箱线图

测试一些经常会使用的参数和参数的常用设置

seaborn.boxplot()

import pandas as pd
# 画图所需的包
import matplotlib.pyplot as plt
# 绘制数据分布图所需的包
import seaborn as sns
# 提高 matplotlib 在 jupyter 中作图的分辨率
%config InlineBackend.figure_format = 'retina'
# 处理中文与负号的显示问题
plt.rcParams['font.sans-serif'] = ['FangSong'] # 指定默认字体
plt.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题
# 读取数据
data = pd.read_excel('./监测点A逐小时污染物浓度与气象实测数据_去除整行缺失_补全数据_去除负数.xlsx')
# 修改列名
data.columns = ['监测时间', '地点', 'SO2监测浓度', 'NO2监测浓度', 'PM10监测浓度',
       'PM2.5监测浓度', 'O3监测浓度', 'CO监测浓度', '温度', '湿度',
       '气压', '风速', '风向']
# 设置画布大小
plt.figure(figsize=(18, 5))
# 绘制箱线图
# 会返回一个坐标轴对象
ax = sns.boxplot(
  # x = data['NO2监测浓度'],
  # 绘图的数据
  # y = data['SO2监测浓度'],
  # 传入 DataFrame 类型的数据,会绘制每列的箱线图
  data=data,
  # 箱子的填充色
  # 有多个箱子,多个箱子的颜色都会一致
  # color='red',
  # 设置调色板,会根据调色板的颜色映射规则对箱子填充颜色
  palette='viridis',
  # 设置箱子的宽度
  width=0.7,
  # 异常值点的大小
  fliersize=2,
  # 箱线图中边框、线的宽度
  linewidth=1.2,
  # 箱子内凹
  notch=True,
  # 其他样式设置, 与 matplotlib.pyplot.boxplot() 一样
  # 显示均值
  showmeans=True,
  # 设置异常值点的样式
  flierprops={
    # 设置点的形状
    'marker': '.',
    # 设置点的填充色
    'markerfacecolor': 'blue',
    # 设置点的边框色
    'markeredgecolor': 'blue',
    # 设置点的大小
    'markersize': '2'
  }
)
# 取消上轴和右轴的显示
ax.spines['top'].set_color('none')
ax.spines['right'].set_color('none')
ax.spines['left'].set_color('none')
plt.grid(linestyle=':')
# 显示图例
plt.legend()
plt.show()

返回文章目录

2.2 异常值的处理

  • 需要进行异常值处理的情况,主要有如下几种:
  • 1.数值的取值范围有明确的要求,对于不在要求的取值范围内的数据可以进行异常值的处理。如,要求取值要为正数,对于取值为负数的数值需要进行处理。
  • 2.使用 3σ 准则(拉依达准则)检测异常值,对于落在(μ-3σ,μ+3σ)以外的数据需要进行异常值处理。
  • 3.使用箱线图检测异常值,对于落在异常值截断线以外的数据需要进行异常值处理。
  • 异常值处理的方式:
  • 1.直接将异常值删除。
  • 2.将异常值置为空,采用缺失值填补的方法对异常值进行替换。

返回文章目录

2.2.1 对不在指定取值范围内的异常值处理

数据文件名:

监测点A逐小时污染物浓度与气象实测数据_去除整行缺失_数据填补.xlsx

data['SO2监测浓度(μg/m³)'].value_counts

统计 SO2监测浓度(μg/m³) 的取值情况:

存在16个数据取值为负数,由于浓度大于等于0,所以对取值为负数的异常值进行处理。

未处理前的数据情况:

返回文章目录

删除异常值

由于 SO2监测浓度(μg/m³) 取值为负数的数据个数并不多,所以将 SO2监测浓度(μg/m³) 取值为负数的行直接删除。

# 包的引入
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
# 读取数据
data = pd.read_excel('../22/监测点A逐小时污染物浓度与气象实测数据_去除整行缺失_数据填补.xlsx')
# 删除 SO2监测浓度(μg/m³) 取值为负数的行
# 即取出 SO2监测浓度(μg/m³) 取值大于等于0的行
re = data[data['SO2监测浓度(μg/m³)']>=0]
re.count()

返回文章目录

异常值置为空值

未处理前的数据情况:

# 包的引入
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
# 读取数据
data = pd.read_excel('../22/监测点A逐小时污染物浓度与气象实测数据_去除整行缺失_数据填补.xlsx')
# 深复制一份数据
data1 = data.copy() 
# 将 SO2监测浓度(μg/m³) 列中取值为负数的数据置为空值
data1['SO2监测浓度(μg/m³)'][data1['SO2监测浓度(μg/m³)']<0] = pd.NA
data1.count()

返回文章目录

2.2.2 基于 3σ 准则(拉依达准则)的异常值处理

这里只进行异常值的筛选,不进行处理,若要处理可以采用与 2.2.1 中类似的方法进行处理,删除异常值或者置为空值后填补异常值。

# 包的引入
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
# 提高 matplotlib 在 jupyter 中作图的分辨率
%config InlineBackend.figure_format = 'retina'
# 处理中文与负号的显示问题
plt.rcParams['font.sans-serif'] = ['FangSong'] # 指定默认字体
plt.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题
# 读取数据
data = pd.read_excel('../22/监测点A逐小时污染物浓度与气象实测数据_去除整行缺失_数据填补.xlsx')
# 获取 SO2监测浓度(μg/m³) 列
so2 = data['SO2监测浓度(μg/m³)']
# 计算均值与标准差
mean_so2 = so2.mean()
std_so2 = so2.std()
print(mean_so2, std_so2)
# 计算 μ-3σ μ+3σ
left = mean_so2 - 3*std_so2
right = mean_so2 + 3*std_so2
# 绘制数据分布图
# ax 接收返回的坐标轴对象
ax = sns.distplot(
  # 绘制图形的数据
  data['SO2监测浓度(μg/m³)'],
  # 显示变量的分布情况
  rug=True,
  # 设置x轴的标签
  axlabel= r'$SO_{2}$'
)
# 绘制 μ-3σ μ+3σ
plt.axvline(left, linestyle='--', color='orange')
plt.axvline(right, linestyle='--', color='orange')
# 显示图例
plt.legend()
plt.show()
# 复制数据集
data1 = data.copy()
# 筛选出 SO2监测浓度(μg/m³) 列取值不在 (μ-3σ, μ+3σ) 内的行
data1 = data1[np.abs(data1['SO2监测浓度(μg/m³)']-mean_so2) > 3*std_so2]
data1

均值与标准差

基于 3σ 准则(拉依达准则) 筛选出的 SO2监测浓度(μg/m³) 取值异常的行:

返回文章目录

2.2.3 基于箱线图检测的异常值处理

这里只进行异常值的筛选,不进行处理,若要处理可以采用与 2.2.1 中类似的方法进行处理,删除异常值或者置为空值后填补异常值。

# 包的引入
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
# 提高 matplotlib 在 jupyter 中作图的分辨率
%config InlineBackend.figure_format = 'retina'
# 处理中文与负号的显示问题
plt.rcParams['font.sans-serif'] = ['FangSong'] # 指定默认字体
plt.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题
# 读取数据
data = pd.read_excel('../22/监测点A逐小时污染物浓度与气象实测数据_去除整行缺失_数据填补.xlsx')
# 获取 SO2监测浓度(μg/m³) 列
so2 = data['SO2监测浓度(μg/m³)']
# 绘制箱线图
plt.boxplot(
  # 绘图数据
  so2,
  # 填充箱体颜色
  patch_artist=True,
  # 显示平均值,默认使用点显示
  showmeans=True,
  # 设置箱子的宽度
  widths=0.1,
  # 设置箱子的样式,需要 patch_artist=True
  boxprops={
    # 箱子的边框为黑色
    'color': 'k',
    # 箱子的填充色为橙色
    'facecolor': 'orange',
  },
  # 设置异常值点的样式
  flierprops={
    # 设置点的形状
    'marker': '.',
    # 设置点的填充色
    'markerfacecolor': 'blue',
    # 设置点的边框色
    'markeredgecolor': 'blue',
    # 设置点的大小
    'markersize': '2'
  },
  # 添加箱线图在x轴对应位置的名字
  # x轴坐标点名
  labels=['SO2监测浓度'],
)
plt.grid(linestyle=':')
# 显示图例
plt.legend()
plt.show()
# 获取 SO2监测浓度(μg/m³) 的上下四分位数
bottom, top = so2.quantile([.25, .75])
print('下四分位数: ', bottom, '上四分位数', top)
# 计算 IQR
IQR = top - bottom
print('IQR: ', IQR)
# 计算异常值截断点
top_error = top + 1.5*IQR
bottom_error = bottom - 1.5*IQR
print('异常值截断点', bottom_error, top_error)
# 复制数据集
data1 = data.copy()
data1 = data1[(so2>top_error) | (so2<bottom_error)]
data1

基于箱线图检测筛选出的 SO2监测浓度(μg/m³) 取值异常的行:

返回文章目录

3. 重复值处理

  • 数据集中出现重复值有以下几种情况:
  • 1.不同行之间在各列上的取值均相同,即不同行的数据取值完全一致。
  • 2.不同行之间存在在某些列上的取值相同

对于重复值可以根据需要,选择对全部列进行去重,也可以选择对某些列进行去重。

可以使用 DataFrame.drop_duplicates() 方法来处理重复值。

  • DataFrame.drop_duplicates()
  • 参数:
  • subset:接收 string 或 序列 为参数,表示要进行去重的列,默认为None,表示全部的列(只有当一行中所有的列一样,才会对该行进行去重)
  • keep:接收 string 为参数,表示重复时保留第几个数据。first:保留第一个。last:保留最后一个。false:只要有重复都不保留。默认为first。
  • inplace:表示是否在原表上进行修改。默认为False。

默认情况下,对所有的列进行去重,不在原表上进行修改,有重复值时默认保留重复值的第一个。

代码示例:

l = [
  np.array([1,2,3]),
  np.array([1,1,2]),
  np.array([1,1,2]),
  np.array([1,1,1])
]
df = pd.DataFrame(l)
print(df)
print()
print(df.drop_duplicates())
print()
print(df)

l = [
  np.array([1,2,3]),
  np.array([1,1,2]),
  np.array([1,1,2]),
  np.array([1,1,1])
]
df = pd.DataFrame(l)
print(df)
print()
# 在原表上进行修改,无返回值
# 不在原表上进行修改,会返回修改后的新表
# 对第一第二列的数据进行去重,保留重复值的最后一个
print(df.drop_duplicates(subset=[0,1], inplace=True, keep='last'))
print()
print(df)



相关文章
|
22天前
|
开发框架 数据建模 中间件
Python中的装饰器:简化代码,增强功能
在Python的世界里,装饰器是那些静悄悄的幕后英雄。它们不张扬,却能默默地为函数或类增添强大的功能。本文将带你了解装饰器的魅力所在,从基础概念到实际应用,我们一步步揭开装饰器的神秘面纱。准备好了吗?让我们开始这段简洁而富有启发性的旅程吧!
29 6
|
16天前
|
安全
Python-打印99乘法表的两种方法
本文详细介绍了两种实现99乘法表的方法:使用`while`循环和`for`循环。每种方法都包括了步骤解析、代码演示及优缺点分析。文章旨在帮助编程初学者理解和掌握循环结构的应用,内容通俗易懂,适合编程新手阅读。博主表示欢迎读者反馈,共同进步。
|
15天前
|
数据可视化 Python
以下是一些常用的图表类型及其Python代码示例,使用Matplotlib和Seaborn库。
通过这些思维导图和分析说明表,您可以更直观地理解和选择适合的数据可视化图表类型,帮助更有效地展示和分析数据。
57 8
|
20天前
|
Python
探索Python中的装饰器:简化代码,增强功能
在Python的世界里,装饰器就像是给函数穿上了一件神奇的外套,让它们拥有了超能力。本文将通过浅显易懂的语言和生动的比喻,带你了解装饰器的基本概念、使用方法以及它们如何让你的代码变得更加简洁高效。让我们一起揭开装饰器的神秘面纱,看看它是如何在不改变函数核心逻辑的情况下,为函数增添新功能的吧!
|
20天前
|
程序员 测试技术 数据安全/隐私保护
深入理解Python装饰器:提升代码重用与可读性
本文旨在为中高级Python开发者提供一份关于装饰器的深度解析。通过探讨装饰器的基本原理、类型以及在实际项目中的应用案例,帮助读者更好地理解并运用这一强大的语言特性。不同于常规摘要,本文将以一个实际的软件开发场景引入,逐步揭示装饰器如何优化代码结构,提高开发效率和代码质量。
44 6
|
21天前
|
人工智能 数据可视化 数据挖掘
探索Python编程:从基础到高级
在这篇文章中,我们将一起深入探索Python编程的世界。无论你是初学者还是有经验的程序员,都可以从中获得新的知识和技能。我们将从Python的基础语法开始,然后逐步过渡到更复杂的主题,如面向对象编程、异常处理和模块使用。最后,我们将通过一些实际的代码示例,来展示如何应用这些知识解决实际问题。让我们一起开启Python编程的旅程吧!
|
20天前
|
存储 数据采集 人工智能
Python编程入门:从零基础到实战应用
本文是一篇面向初学者的Python编程教程,旨在帮助读者从零开始学习Python编程语言。文章首先介绍了Python的基本概念和特点,然后通过一个简单的例子展示了如何编写Python代码。接下来,文章详细介绍了Python的数据类型、变量、运算符、控制结构、函数等基本语法知识。最后,文章通过一个实战项目——制作一个简单的计算器程序,帮助读者巩固所学知识并提高编程技能。
|
8天前
|
Unix Linux 程序员
[oeasy]python053_学编程为什么从hello_world_开始
视频介绍了“Hello World”程序的由来及其在编程中的重要性。从贝尔实验室诞生的Unix系统和C语言说起,讲述了“Hello World”作为经典示例的起源和流传过程。文章还探讨了C语言对其他编程语言的影响,以及它在系统编程中的地位。最后总结了“Hello World”、print、小括号和双引号等编程概念的来源。
101 80
|
26天前
|
存储 索引 Python
Python编程数据结构的深入理解
深入理解 Python 中的数据结构是提高编程能力的重要途径。通过合理选择和使用数据结构,可以提高程序的效率和质量
134 59
|
7天前
|
分布式计算 大数据 数据处理
技术评测:MaxCompute MaxFrame——阿里云自研分布式计算框架的Python编程接口
随着大数据和人工智能技术的发展,数据处理的需求日益增长。阿里云推出的MaxCompute MaxFrame(简称“MaxFrame”)是一个专为Python开发者设计的分布式计算框架,它不仅支持Python编程接口,还能直接利用MaxCompute的云原生大数据计算资源和服务。本文将通过一系列最佳实践测评,探讨MaxFrame在分布式Pandas处理以及大语言模型数据处理场景中的表现,并分析其在实际工作中的应用潜力。
30 2