数据预处理(上)之离群值处理、标准化

  • Post author:
  • Post category:其他


https://www.ricequant.com/community/topic/4271/

一般的数据预处理中常提及到三类处理:去极值、标准化、中性化。这几个词想必大家都不陌生,也许存在疑问或有自己的一番见解,本文将先对前两个进行解释和总结,欢迎讨论和指正~


一、离群值处理

因为过大或过小的数据可能会影响到分析结果,尤其是在做回归的时候,我们需要对那些离群值进行处理。实际上离群值和极值是有区别的,因为极值不代表异常,但实际处理中这两个所用方法差不多,所以这里也不强行区分了。
处理方法是调整因子值中的离群值至上下限(Winsorzation处理),其中上下限由离群值判断的标准给出,从而减小离群值的影响力。离群值的判断标准有三种,分别为 MAD、 3σ、百分位法。
下图是2017-10-23日的全市场BP原始数据。



1. MAD法:

MAD又称为绝对值差中位数法(Median Absolute Deviation)。MAD 是一种先需计算所有因子与平均值之间的距离总和来检测离群值的方法。

处理的逻辑:第一步,找出所有因子的中位数 Xmedian;第二步,得到每个因子与中位数的绝对偏差值 Xi−Xmedian;第三步,得到绝对偏差值的中位数 MAD;最后,确定参数 n,从而确定合理的范围为 [Xmedian−nMAD,Xmedian+nMAD],并针对超出合理范围的因子值做如下的调整:

对全市场BP原始数据进行MAD处理后的结果:



2. 3σ法

又称为标准差法。标准差本身可以体现因子的离散程度,是基于因子的平均值 Xmean而定的。在离群值处理过程中,可通过用 Xmean±nσ来衡量因子与平均值的距离。
标准差法处理的逻辑与MAD法类似,首先计算出因子的平均值与标准差,其次确认参数 n(这里选定 n = 3),从而确认因子值的合理范围为 [Xmean−nσ,Xmean+nσ],并对因子值作如下的调整:



对全市场BP原始数据进行3σ法处理后的结果:


3. 百分位法:

计算的逻辑是将因子值进行升序的排序,对排位百分位高于97.5%或排位百分位低于2.5%的因子值,进行类似于 MAD 、 3σ 的方法进行调整。
对全市场BP原始数据进行百分位法处理后的结果:

通过这几个图表比对,我们可以发现百分位法的结果和MAD很相似。



二、标准化

标准化(standardization)在统计学中有一系列含义,一般使用z-score的方法。处理后的数据从有量纲转化为无量纲,从而使得数据更加集中,或者使得不同的指标能够进行比较和回归。
由此可见,标准化应该用于多个不同量级指标之间需要互相比较的时候。讲到这里,我们应该区分一下标准化和中性化。中性化的目的在于消除因子中的偏差和不需要的影响,详细的内容将会在下一个帖子总结~

对因子进行标准化处理的方法主要有以下两种:


1、对原始因子值进行标准化;

方法一可以保留更多的因子分布信息,但是需要去掉极端值,否则会影响到回归结果。回归的方法一般使用z-score,将因子值的均值调整为0,标准差调整为1。 标准化处理基于原始数据的均值和标准差,处理的逻辑是因子值减去均值后,再除以标准差。
对已经过3σ法去极值后的结果进行标准化:



2、用因子的排序值进行标准化。

方法二只关注原始序列的相对排序关系,所以对原始变量的分布不做要求,属于非参数统计方法,可以适用于更多类型的数据。首先将原始数据的排序值作为参数,再将之带入方法一的标准化计算中。
由于转为排序值之后的分布图像意义不大,就不在此贴出。

在RQPro中的因子研究部分提供了三种离群值处理和方法一的标准化处理(当然我也不知道它们和我的代码是否完全一致…),大家可以试一试哦~
下一个帖子将讨论中性化~


数据预处理之去极值、标准化.ipynb克隆研究 +109
In [1]:

#import seaborn
import numpy as np
import pandas as pd
import math
from statsmodels import regression
import statsmodels.api as sm
stocks = all_instruments(type="CS", date='2017-10-23').order_book_id.tolist()
data = get_fundamentals(query(fundamentals.eod_derivative_indicator.pb_ratio,fundamentals.eod_derivative_indicator.market_cap
).filter(fundamentals.income_statement.stockcode.in_(stocks)), '2017-10-23', '1d').major_xs('2017-10-23').dropna()
data['BP'] = 1/data['pb_ratio']

一、离群值处理

In [2]:

def filter_extreme_MAD(series,n): #MAD:中位数去极值
  median = series.quantile(0.5)
  new_median = ((series - median).abs()).quantile(0.50)
  max_range = median + n*new_median
  min_range = median - n*new_median
  return np.clip(series,min_range,max_range)
def filter_extreme_3sigma(series,n=3): #3 sigma
  mean = series.mean()
  std = series.std()
  max_range = mean + n*std
  min_range = mean - n*std
  return np.clip(series,min_range,max_range)
def filter_extreme_percentile(series,min = 0.025,max = 0.975): #百分位法
  series = series.sort_values()
  q = series.quantile([min,max])
  return np.clip(series,q.iloc[0],q.iloc[1])

可以看出MAD和百分位法的结果十分相近。

In [3]:

fig = plt.figure(figsize = (20, 8))
ax = data['BP'].plot.kde(label = 'Original_BP')
ax = filter_extreme_percentile(data['BP']).plot.kde(label = 'Percentile')
ax = filter_extreme_3sigma(data['BP']).plot.kde(label = '3sigma')
ax = filter_extreme_MAD(data['BP'],5).plot.kde(label = 'MAD')
ax.legend()

Out[3]:
<matplotlib.legend.Legend at 0x7fec777a5dd8>

二、标准化处理

In [4]:

def standardize_series(series): #原始值法
  std = series.std()
  mean = series.mean()
  return (series-mean)/std
fig = plt.figure(figsize = (20, 8))
new = filter_extreme_3sigma(data['BP'])
ax = standardize_series(new).plot.kde(label = 'standard_1')
ax.legend()

Out[4]:
<matplotlib.legend.Legend at 0x7fec777867b8>

In [5]:

standard_2 = standardize_series(new.rank())
standard_2

Out[5]:
000005.XSHE   -0.197560
600602.XSHG    0.376072
600651.XSHG    0.538256
600652.XSHG    0.042995
600654.XSHG    0.470770
600653.XSHG    0.527371
600601.XSHG    0.957323
000004.XSHE   -1.655042
000002.XSHE    0.773369
000001.XSHE    1.709467
000009.XSHE   -0.143136
600603.XSHG    1.467823
000012.XSHE    0.846298
600604.XSHG    0.373895
000016.XSHE   -0.419611
600605.XSHG   -0.096331
600606.XSHG    1.429726
000011.XSHE   -0.291170
000017.XSHE   -1.730148
000020.XSHE   -1.648511
000008.XSHE   -0.152932