原始因子处理之手写去极值函数
程序员文章站
2022-07-13 15:18:29
...
一、去极值
- 百分位去极值:直接以上下百分位为边界,将边界外数据归为边界上数据,目前行业内一般不使用。
- 标准化去极值:又称为标准差法。标准差本身可以体现因子的离散程度,是基于因子的平均值 Xmean而定的。在离群值处理过程中,可通过用 Xmean±nσ来衡量因子与平均值的距离。 标准差法处理的逻辑与MAD法类似,首先计算出因子的平均值与标准差,其次确认参数 n(这里选定 n = 3,3个标准差以内概率为99.73%),从而确认因子值的合理范围为 [Xmean−nσ,Xmean nσ]
- MAD中位数去极值:由于常见的3σ去极值法是基于样本服从正态分布这个假设的,但往往我们发现大部分因子值的分布都并不服从正态分布,厚尾分布的情况较为普遍。因此我们采用更加稳健的MAD(Median Absolute Deviation 绝对中位数法)首先计算因子值的中位数????????????????????????????,并定义绝对中位值为:采取与3σ法等价的方法,我们将大于???????????????????????????? + 3 ∗ ????????????的值或小于???????????????????????????? − 3 ∗ ????????????的值定义为异常值。在对异常值做处理时,需要根据因子的具体情况来决定是直接剔除异常值,还是将异常值设为上下限的数值,常用的方法是后者。 操作步骤:
- Step1.找出所有因子的中位数median
- Step2.计算所有因子与1中的median的差值绝对值的中位数MAD
- Step3.确定边界[median−nMAD,median+nMAD]
4、相关代码(MAD中位数去极值)
def winsorize_med(data, scale=1, inclusive=True, inf2nan=True, axis=1):
'''
参数
------------
data: pd.Series/pd.DataFrame, 待缩尾的序列
scale: 倍数,默认为 1.0。会将位于 [med - scale * distance, med + scale * distance] 边界之外的值替换为边界值/np.nan
inclusive bool 是否将位于边界之外的值替换为边界值,默认为 True。 如果为 True,则将边界之外的值替换为边界值,否则则替换为 np.nan
inf2nan: 是否将 np.inf 和 -np.inf 替换成 np.nan,默认为 True。如果为 True,在缩尾之前会先将 np.inf 和 -np.inf 替换成 np.nan,缩尾的时候不会考虑 np.nan,否则 inf 被认为是在上界之上,-inf 被认为在下界之下
axis: 在 data 为 pd.DataFrame 时使用,沿哪个方向做标准化,默认为 1。0 为对每列做缩尾,1 为对每行做缩尾
返回
------------
中位数去极值之后的因子数据
'''
if isinstance(data,pd.DataFrame):
value = data.copy()
if axis==1:
long = value.shape[0]
for i in range(long):
s = value.iloc[i,:]
if inf2nan==True:
s[np.isinf(s)]=np.nan
med = np.median(s.dropna())
distance = np.median(np.abs(s-med).dropna())
up = med+scale*distance
down = med-scale*distance
if inclusive==True:
s[s>up]=up
s[s<down]=down
else:
s[s>up]=np.nan
s[s<down]=np.nan
else:
med = np.median(s.dropna())
distance = np.median(np.abs(s-med).dropna())
up = med+scale*distance
down = med-scale*distance
if inclusive==True:
s[s>up]=up
s[s<down]=down
else:
s[s>up]=np.nan
s[s<down]=np.nan
return value
elif axis==0:
width = value.shape[1]
for j in range(width):
s = value.iloc[:,j]
if inf2nan==True:
s[np.isinf(s)]=np.nan
med = np.median(s.dropna())
distance = np.median(np.abs(s-med).dropna())
up = med+scale*distance
down = med-scale*distance
if inclusive==True:
s[s>up]=up
s[s<down]=down
else:
s[s>up]=np.nan
s[s<down]=np.nan
else:
med = np.median(s.dropna())
distance = np.median(np.abs(s-med).dropna())
up = med+scale*distance
down = med-scale*distance
if inclusive==True:
s[s>up]=up
s[s<down]=down
else:
s[s>up]=np.nan
s[s<down]=np.nan
return value
else:
return('axis值有误')
elif isinstance(data,pd.Series):
value = data.copy()
if inf2nan==True:
value[np.isinf(value)]=np.nan
med = np.median(value.dropna())
distance = np.median(np.abs(value-med).dropna())
up = med+scale*distance
down = med-scale*distance
if inclusive==True:
value[value>up]=up
value[value<down]=down
else:
value[value>up]=np.nan
value[value<down]=np.nan
return value
else:
med = np.median(value.dropna())
distance = np.median(np.abs(value-med).dropna())
up = med+scale*distance
down = med-scale*distance
if inclusive==True:
value[value>up]=up
value[value<down]=down
else:
value[value>up]=np.nan
value[value<down]=np.nan
return value
else:
print('不是pd.Series和pd.DataFrame类型')
return
上一篇: Hadoop案例,附代码
下一篇: 策略模式