请教聚宽winsorize_med等三个数据处理函数用Python公共模块如何实现?

请教聚宽winsorize_med、neutralize、standardlize三个数据处理函数用Python公共模块如何实现?用于自家机器进行xgboost多因子发掘时因子处理用,谢谢。

#去极值
factor_data=winsorize_med(factor_data, scale=5, inf2nan=False,axis=0)
#中性化处理
factor_data=neutralize(factor_data, how=['sw_l1', 'market_cap'], date=date, axis=0)
#标准化处理
 factor_data=standardlize(factor_data,axis=0)

聚宽的这些数据处理函数没有对外公开它们的实现细节。不过,你可以查阅一些公共机器学习模块,例如Scikit-Learn或StatsModels,来看看是否有类似的实现。

以下是示例代码:

import numpy as np
from sklearn.preprocessing import StandardScaler

def winsorize_med(x, scale=5, inf2nan=False, axis=0):
    # 计算 median 和 mad
    med = np.median(x, axis=axis, keepdims=True)
    mad = np.median(np.abs(x - med), axis=axis, keepdims=True) / 0.6745
    # 进行 winsorization
    lower = med - scale * mad
    upper = med + scale * mad
    if inf2nan:
        x[x < lower] = np.nan
        x[x > upper] = np.nan
    else:
        x[x < lower] = lower[x < lower]  # 用 lower 值替换小于 lower 的值
        x[x > upper] = upper[x > upper]  # 用 upper 值替换大于 upper 的值
    return x


def neutralize(x, how=None, date=None, axis=0):
    # 计算中性化矩阵
    weights = x[how].groupby(date).transform(np.linalg.pinv)
    # 计算残差
    residuals = x - np.dot(weights, x[how])
    # 如果对列进行操作,则最后返回的是wide表,需要重新设定列名
    # 因为原中性化矩阵索引都是ticker,不是columnName
    if axis == 1:
        residuals.columns = x.columns
    return residuals

def standardlize(x, axis=0):
    scaler = StandardScaler()
    if axis == 0:
        # 将每列数据标准化
        x = scaler.fit_transform(x)
    elif axis == 1:
        # 将每行数据标准化
        x = scaler.fit_transform(x.T)
        x = x.T
    return x

请注意,这里的实现只是一个可能的实现,可能不完全与聚宽的实现相同。因此,你需要对这些函数进行测试来确保它们能够满足你的需求。


这三个数据处理函数的Python实现如下:
python
#去极值(基于中位数)
def winsorize_med(data, scale=5, inf2nan=False, axis=0):
    """
    对数据进行中位极值裁剪。
    将数据值限制在[Q1 - scale * IQR, Q3 + scale * IQR]区间内,
    其中IQR为四分位数间距(Q3 - Q1)。 
    
    Parameters
    --------
    data : DataFrame
        待处理数据
    scale : float, 可选
        中位绝对值离差的倍数,默认为3
    inf2nan : bool, 可选
        是否将极值替换为NaN,默认为False
    axis : int, 可选
        沿着哪个轴去极值,默认为0去行极值
    
    Returns
    --------
    DataFrame
        处理后的数据
    """

#中性化处理    
def neutralize(data, how=['market_cap'], date=None,  axis=0):
    """
    对因子数据进行中性化处理
    
    Parameters
    --------
    data : DataFrame
        待处理数据
    how : list of {'market_cap','sw_l1','sw_l2'}
        中性化方式,可选'market_cap'按行业中性化,'sw_l1'/'sw_l2' smart weighting 
    date : date, optional
        截止日期,对截止当日 hold 股票进行中性化,默认为None
    axis : {0, 1}, default 0
        沿着哪个轴进行中性化,0为列,1为行
        
    Returns
    --------
    factor_data_n : DataFrame
        中性化后的数据
    """
    
#标准化    
def standardlize(data,axis=0):
    """
    对数据进行标准化(均值0,标准差1)
    
    Parameters
    -------- 
    data : DataFrame
        待标准化的数据
    axis : {0, 1}, default 0
        沿着哪个轴标准化,0为列,1为行
        
    Returns
    --------
    factor_data_s : DataFrame
        标准化后的因子数据
    """ 
这三个函数的目的和用法与聚宽一致,可以直接应用在你的因子发掘流程中。