不是删除,而是拉回正常范围。
2.1 三种方法- 分位数去极值
- 中位数 绝对偏差去极值
- 正态分布去极值
排序后,处于中间位置的那个数。Median
奇数:中间的那个数
偶数:中间两个数的平均值
3.2 四分位数- 第一四分位数(Q1)排列后25%
- 第二四分位数(Q2)排列后 50% 中位数
- 第三四分位数(Q3)排列后75%
百分位数:数据所处位置为整体的某个%位数
- 0 quantile = 0 percentile
- 0.25quantile = 25 percentile
- 0.50quantile = 50 percentile
- 0.75quantile = 75 percentile
将分位数以外的极值, 用分位数点的值替换
Pandas Dataframe操作
from scipy.stats.mstats import winsorize
import numpy as np
import pandas as pd
# 获取所有股票代码
stocks = all_instruments('CS').order_book_id
# 获取因子
fund = get_factor(stocks, factor=['pe_ratio'], start_date='20180102', end_date='20180102')
# 删除日期index
fund = fund.reset_index(1, drop=True)
# 删除 nan数据
fund = fund.dropna()
# 分位数去极值
fund['peration_winsorize'] = winsorize(fund['pe_ratio'], limits=0.025)
# fund
# 绘制结果
fund['pe_ratio'][:500].plot()
fund['peration_winsorize'][:500].plot()
自实现分位数去极值
def quantile(factor, up, down):
"""
分位数去极值
"""
up_scale = np.percentile(factor, up)
down_scale = np.percentile(factor, down)
factor = np.where(factor > up_scale, up_scale, factor)
factor = np.where(factor < down_scale, down_scale, factor)
return factor
# 分位数去极值 2.5% ~ 97.5%
fund['quantile'] = quantile(fund['pe_ratio'], 97.5, 2.5)
# 绘制结果
fund['pe_ratio'][:500].plot()
fund['quantile'][:500].plot()
4. 中位数绝对值偏差去极值 (最常用)
MAD,是一种先计算所有因子与中位数之间的距离总和来检测离群的方法。
4.1计算法方法- 1、找到中位数
- 2、每个值与中位数的绝对偏差
- 3、计算绝对偏差的中位数 MAD
- 4、计算 MAD_e = 1.4826 * MAD 然后确定参数n 做出调整
if x > 中位数 + n * MAD_e else x = 中位数 + n * MAD_e
if x < 中位数 - n * MAD_e elsex = 中位数 - n * MAD_e
其它值不变
4.2 实现中位数绝对偏差法一般 n = 3
def mad(factor, n=3):
"""
3倍中位数偏差法
"""
# 1、找中位数
med = np.median(factor)
# 2.求绝对偏差
# 3、计算绝对偏差的中位数 MAD
mad = np.median(abs(factor - med))
# 求出上下限
up = med + (1.4826 * mad) * n # 4、计算 MAD_e = 1.4826 * MAD 然后确定参数n 做出调整
down = med - (1.4826 * mad) * n
# 去极值
factor = np.where(factor > up, up, factor)
factor = np.where(factor < down, down, factor)
return factor
# 执行去极值
fund['3mad'] = mad(fund['pe_ratio'])
# 显示结果
fund['pe_ratio'][:500].plot()
fund['3mad'][:500].plot()
5、正态分布去极值(效果一般)
1、sigma原则
- 2sigma ==>95.4%
- 3sigma ==>99.73%
- 4sigma ==>99.99%
# 3sigma方法去极值
def three_sigma(factor, sigma=3):
# 计算平均值和标准差
mean = factor.mean()
std = factor.std()
print(mean, std)
# 计算上下限
up = mean + (sigma * std)
down = mean - (sigma * std)
print(up, down)
# 替换极值
factor = np.where(factor > up, up, factor)
factor = np.where(factor < down, down, factor)
return factor
# 执行 3sigma 方法去极值
fund['three_sigma'] = three_sigma(fund['pe_ratio'], sigma=0.025)
# 显示结果
fund['pe_ratio'][:500].plot()
fund['three_sigma'][:500].plot()
6、总结
推荐使用 中位数绝对值偏差 去极值



