<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>易博云天 &#187; 数据处理</title>
	<atom:link href="http://www.eavea.com/blog/index.php/tag/shujuchuli/feed" rel="self" type="application/rss+xml" />
	<link>http://www.eavea.com/blog</link>
	<description>专注技术：学习、交流、分享、免费，每天进步一点点！</description>
	<lastBuildDate>Mon, 13 Mar 2023 07:04:16 +0000</lastBuildDate>
	<language>zh-CN</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.6.1</generator>
		<item>
		<title>【Python实战】单变量异常值检测</title>
		<link>http://www.eavea.com/blog/index.php/pythonshizhandanbianliangyichangzhijiance.html</link>
		<comments>http://www.eavea.com/blog/index.php/pythonshizhandanbianliangyichangzhijiance.html#comments</comments>
		<pubDate>Tue, 14 Apr 2020 07:36:20 +0000</pubDate>
		<dc:creator>eavea</dc:creator>
				<category><![CDATA[后端技术]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[数据处理]]></category>

		<guid isPermaLink="false">http://www.eavea.com/blog/?p=55</guid>
		<description><![CDATA[【Python实战】单变量异常值检测 异常值检测是数据预处理阶段重要的环节，这篇文章介绍下对于单变量异常值检测 [&#8230;]]]></description>
				<content:encoded><![CDATA[<div>【Python实战】单变量异常值检测</div>
<blockquote><p>异常值检测是数据预处理阶段重要的环节，这篇文章介绍下对于单变量异常值检测的常用方法，通过Python代码实现。</p></blockquote>
<h2 id="toc-heading-1">一、什么是异常值</h2>
<p>异常值是在数据集中与其他观察值有很大差距的数据点，它的存在，会对随后的计算结果产生不适当的影响，因此检测异常值并加以适当的处理是十分必要的。</p>
<h2 id="toc-heading-2">二、异常值的处理</h2>
<p>异常值并不都是坏的，了解这一点非常重要。只是简单地从数据中删除异常值，而不考虑它们如何影响结果的话，可能会导致灾难。</p>
<blockquote><p>“异常值不一定是坏事。这些只是与其他模式不一致的观察。但事实上异常值非常有趣。例如，如果在生物实验中，某只老鼠没有死亡而其他老鼠都死了，去了解为什么将会非常有趣。这可能会带来新的科学发现。因此，检测异常值非常重要。” —— Pierre Lafaye de Micheaux，统计师</p></blockquote>
<p>对于异常值，一般有如下几种处理：</p>
<ul>
<li>删除含有异常值的记录（是否删除根据实际情况考虑）</li>
<li>将异常值视为缺失值，利用缺失值的处理方法进行处理</li>
<li>平均值修正（前后两个观测值的平均值）</li>
<li>不处理（直接在具有异常值的数据集上进行挖掘）</li>
</ul>
<h2 id="toc-heading-3">三、异常值的类型</h2>
<p>异常值有两种类型：单变量和多变量（Univariate and Multivariate）。单变量异常值是仅由一个变量中的极值组成的数据点，而多变量异常值是至少两个变量的组合异常分数。假设您有三个不同的变量 &#8211; X，Y，Z。如果您在三维空间中绘制这些变量的图形，它们应该形成一种云。位于此云之外的所有数据点都将是多变量异常值。</p>
<p>举个例子：做客户分析，发现客户的年平均收入是80万美元。但是，有两个客户的年收入是4美元和420万美元。这两个客户的年收入明显不同于其他人，那这两个观察结果将被视为异常值，并且是单变量异常值，当我们看到单变量的分布时，可以找到这些异常值。</p>
<p>再举个例子：身高和体重之间的关系。我们对“身高”和“体重”有单变量和双变量分布，如下图所示。</p>
<div><img alt="height_weight_outliers.png" src="https://www.wenyuanblog.com/medias/blogimages/height_weight_outliers.png" data-original="/medias/blogimages/height_weight_outliers.png" /></div>
<p>看箱线图（box plot后面会介绍）没有任何异常值，再看散点图（scatter plot），有两个值在一个特定的身高和体重的平均值以下。可见多变量异常值是n维空间中的异常值，必须通过多维度的分布才能体现出来。</p>
<p>&nbsp;</p>
<p>如果对异常值不太了解，可以阅读这篇<a title="数据探索指南" href="https://www.analyticsvidhya.com/blog/2016/01/guide-data-exploration/?utm_source=outlierdetectionpyod&amp;utm_medium=blog" target="_0" rel="external nofollow noopener noreferrer">《数据探索指南》</a>，上述部分解释也是从中摘录的。<br />
下面，我主要记录下单变量异常值检测的Python实现。</p>
<h2 id="toc-heading-4">四、常用异常检测方法</h2>
<p>原则上模拟数据集需要样本量足够大，这里仅是演示算法，所以就手动写了有限的样本。<br />
异常值的测量标准有很多，比较常见的是描述性统计法、三西格玛法（3σ法）、箱线图等：</p>
<h3 id="toc-heading-5">1. 描述性统计</h3>
<p>基于常识或经验，假定我们认为大于10的数值是不符合常理的。</p>
<p>下面用Python代码实现用描述性统计求异常值：</p>
<pre><code># -*- coding: utf-8 -*-

data = [2.78, 1.79, 4.73, 3.81, 2.78, 1.80, 4.81, 2.79, 1.78, 3.32, 10.8, 100.0]
threshold = 10

# 定义描述性统计识别异常值函数
def descriptive_statistics(data):
    return list(filter(lambda x: x &gt; threshold, data))

outliers = descriptive_statistics(data)
print('异常值共有：{0}个，分别是：{1}'.format(len(outliers), outliers))

# 输出：异常值共有：2个，分别是：[10.8, 100.0]
</code></pre>
<h3 id="toc-heading-6">2. 三西格玛（3σ）</h3>
<p>当数据服从正态分布时，99%的数值应该位于距离均值3个标准差之内的距离，P(|x−μ|&gt;3σ)≤0.003，当数值超出这个距离，可以认为它是异常值。<br />
正态分布状况下，数值分布表：</p>
<table>
<thead>
<tr>
<th>数值分布</th>
<th>在数据中的占比</th>
</tr>
</thead>
<tbody>
<tr>
<td>(μ-σ,μ+σ)</td>
<td>0.6827</td>
</tr>
<tr>
<td>(μ-2σ,μ+2σ)</td>
<td>0.9545</td>
</tr>
<tr>
<td>(μ-3σ,μ+3σ)</td>
<td>0.9973</td>
</tr>
</tbody>
</table>
<p>注：在正态分布中σ代表标准差，μ代表均值，x=μ为图形的对称轴</p>
<p>下面用Python代码实现用三西格玛求异常值：</p>
<pre><code># -*- coding: utf-8 -*-

import pandas as pd
import numpy as np

data = [2.78, 1.79, 4.73, 3.81, 2.78, 1.80, 4.81, 2.79, 1.78, 3.32, 10.8, 100.0]

# 定义3σ法则识别异常值函数
def three_sigma(data_series):
    rule = (data_series.mean() - 3 * data_series.std() &gt; data_series) | (data_series.mean() + 3 * data_series.std() &lt; data_series)
    index = np.arange(data_series.shape[0])[rule]
    outliers = data_series.iloc[index]
    return outliers.tolist()

data_series = pd.Series(data)
outliers = three_sigma(data_series)
print('异常值共有：{0}个，分别是：{1}'.format(len(outliers), outliers))

# 输出：异常值共有：1个，分别是：[100.0]
</code></pre>
<h3 id="toc-heading-7">3. 箱线图（box plot）</h3>
<p>和3σ原则相比，箱线图依据实际数据绘制，真实、直观地表现出了数据分布的本来面貌，且没有对数据作任何限制性要求（3σ原则要求数据服从正态分布或近似服从正态分布）。<br />
其判断异常值的标准以四分位数和四分位距为基础。四分位数给出了数据分布的中心、散布和形状的某种指示，具有一定的鲁棒性，即25%的数据可以变得任意远而不会很大地扰动四分位数，所以异常值通常不能对这个标准施加影响。鉴于此，箱线图识别异常值的结果比较客观，因此在识别异常值方面具有一定的优越性。<br />
箱线图提供了识别异常值的一个标准，即：<br />
上界 = Q3 + 1.5IQR<br />
下界 = Q1 &#8211; 1.5IQR<br />
小于下界或大于上界的值即为异常值。<br />
其中，<br />
Q3称为上四分位数（75%），表示全部观察值中只有四分之一的数据取值比它大；<br />
Q1称为下四分位数（25%），表示全部观察值中只有四分之一的数据取值比它小；<br />
IQR称为四分位数差，这里就是 Q3-Q1；<br />
1.5其实是个参数λ，这个参数通常取1.5（类似于正态分布中的μ±λ）</p>
<p>文字描述可能比较绕，下面用图片来解释下。<br />
<img alt="box_plot.png" src="https://www.wenyuanblog.com/medias/blogimages/box_plot.png" data-original="/medias/blogimages/box_plot.png" /></p>
<blockquote><p>第一四分位数 (Q1)，又称“较小四分位数”，等于该样本中所有数值由小到大排列后第25%的数字。<br />
第二四分位数 (Q2)，又称“中位数”，等于该样本中所有数值由小到大排列后第50%的数字。<br />
第三四分位数 (Q3)，又称“较大四分位数”，等于该样本中所有数值由小到大排列后第75%的数字。<br />
Q3与Q1的差距又称四分位距（InterQuartile Range,IQR）。</p></blockquote>
<p>四分位数的计算参见<a href="https://baike.baidu.com/item/四分位数" target="_0" rel="external nofollow noopener noreferrer">四分位数</a>和<a href="https://blog.csdn.net/ningyanggege/article/details/82625947" target="_0" rel="external nofollow noopener noreferrer">四分位数的计算</a></p>
<p>下面用Python代码实现用箱线图求异常值：</p>
<pre><code># -*- coding: utf-8 -*-

import pandas as pd

data = [2.78, 1.79, 4.73, 3.81, 2.78, 1.80, 4.81, 2.79, 1.78, 3.32, 10.8, 100.0]

# 定义箱线图识别异常值函数
def box_plot(data_series):
    q_abnormal_low = data_series.quantile(0.25) - 1.5 * (data_series.quantile(0.75) - data_series.quantile(0.25))
    q_abnormal_up = data_series.quantile(0.75) + 1.5 * (data_series.quantile(0.75) - data_series.quantile(0.25))
    index = (data_series &lt; q_abnormal_low) | (data_series &gt; q_abnormal_up)
    outliers = data_series.loc[index]
    return outliers.tolist()

sorted_data = sorted(data)
data_series = pd.Series(sorted_data)
outliers = box_plot(data_series)
print('异常值共有：{0}个，分别是：{1}'.format(len(outliers), outliers))

# 输出：异常值共有：2个，分别是：[10.8, 100.0]
</code></pre>
<h2 id="toc-heading-8">五、总结</h2>
<p>以上是最基础的几种单变量异常值检测方法，没有最好的，只有对当前数据场景最合适的。<br />
后期如果涉及机器学习的数据预处理，我会继续学习和研究多变量异常值的检测，相信会有更有意思的一些算法等着我去学习。<br />
参考<br />
异常检测的N种方法，阿里工程师都盘出来了：<a href="https://mp.weixin.qq.com/s/w7SbAHxZsmHqFtTG8ZAXNg" target="_0" rel="external nofollow noopener noreferrer">https://mp.weixin.qq.com/s/w7SbAHxZsmHqFtTG8ZAXNg</a><br />
数据探索指南：<a href="https://www.analyticsvidhya.com/blog/2016/01/guide-data-exploration/?utm_source=outlierdetectionpyod&amp;utm_medium=blog" target="_0" rel="external nofollow noopener noreferrer">https://www.analyticsvidhya.com/blog/2016/01/guide-data-exploration/?utm_source=outlierdetectionpyod&amp;utm_medium=blog</a><br />
Tukey method：<a href="https://en.wikipedia.org/wiki/Tukey%27s_range_test" target="_0" rel="external nofollow noopener noreferrer">https://en.wikipedia.org/wiki/Tukey%27s_range_test</a><br />
图基（Tukey）检验：一种值得倍加推崇的检验方法：<a href="http://blog.sina.com.cn/s/blog_60be90250100eojy.html" target="_0" rel="external nofollow noopener noreferrer">http://blog.sina.com.cn/s/blog_60be90250100eojy.html</a><br />
如何从大量数据中找出异常值：<a href="https://blog.csdn.net/wangyangzhizhou/article/details/83854951" target="_0" rel="external nofollow noopener noreferrer">https://blog.csdn.net/wangyangzhizhou/article/details/83854951</a><br />
概率论与数理统计 第四版 浙江大学出版社：<a href="https://book.douban.com/subject/3165271/" target="_0" rel="external nofollow noopener noreferrer">https://book.douban.com/subject/3165271/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.eavea.com/blog/index.php/pythonshizhandanbianliangyichangzhijiance.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
