网易首页 > 网易号 > 正文 申请入驻

【Python】60个“特征工程”计算函数(Python代码)

0
分享至

近期一些朋友询问我关于如何做特征工程的问题,有没有什么适合初学者的有效操作。

特征工程的问题往往需要具体问题具体分析,当然也有一些暴力的策略,可以在竞赛初赛前期可以带来较大提升,而很多竞赛往往依赖这些信息就可以拿到非常好的效果,剩余的则需要结合业务逻辑以及很多其他的技巧,此处我们将平时用得最多的聚合操作罗列在下方。

最近刚好看到一篇文章汇总了非常多的聚合函数,就摘录在下方,供许多初入竞赛的朋友参考。

聚合特征汇总

pandas自带的聚合函数

其它重要聚合函数

其它重要聚合函数&分类分别如下。

def median(x):     return np.median(x) def variation_coefficient(x):     mean = np.mean(x)     if mean != 0:         return np.std(x) / mean     else:         return np.nan def variance(x):     return np.var(x) def skewness(x):     if not isinstance(x, pd.Series):         x = pd.Series(x)     return pd.Series.skew(x) 
def kurtosis(x):
    if not isinstance(x, pd.Series):
        x = pd.Series(x)
    return pd.Series.kurtosis(x)

def standard_deviation(x):
    return np.std(x)

def large_standard_deviation(x):
    if (np.max(x)-np.min(x)) == 0:
        return np.nan
    else:
        return np.std(x)/(np.max(x)-np.min(x))

def variation_coefficient(x):
    mean = np.mean(x)
    if mean != 0:
        return np.std(x) / mean
    else:
        return np.nan

def variance_std_ratio(x):
    y = np.var(x)
    if y != 0:
        return y/np.sqrt(y)
    else:
        return np.nan

def ratio_beyond_r_sigma(x, r):
    if x.size == 0:
        return np.nan
    else:
        return np.sum(np.abs(x - np.mean(x)) > r * np.asarray(np.std(x))) / x.size

def range_ratio(x):
    mean_median_difference = np.abs(np.mean(x) - np.median(x))
    max_min_difference = np.max(x) - np.min(x)
    if max_min_difference == 0:
        return np.nan
    else:
        return mean_median_difference / max_min_difference
    
def has_duplicate_max(x):
    return np.sum(x == np.max(x)) >= 2

def has_duplicate_min(x):
    return np.sum(x == np.min(x)) >= 2

def has_duplicate(x):
    return x.size != np.unique(x).size

def count_duplicate_max(x):
    return np.sum(x == np.max(x))

def count_duplicate_min(x):
    return np.sum(x == np.min(x))

def count_duplicate(x):
    return x.size - np.unique(x).size

def sum_values(x):
    if len(x) == 0:
        return 0
    return np.sum(x)

def log_return(list_stock_prices):
    return np.log(list_stock_prices).diff() 

def realized_volatility(series):
    return np.sqrt(np.sum(series**2))

def realized_abs_skew(series):
    return np.power(np.abs(np.sum(series**3)),1/3)

def realized_skew(series):
    return np.sign(np.sum(series**3))*np.power(np.abs(np.sum(series**3)),1/3)

def realized_vol_skew(series):
    return np.power(np.abs(np.sum(series**6)),1/6)

def realized_quarticity(series):
    return np.power(np.sum(series**4),1/4)

def count_unique(series):
    return len(np.unique(series))

def count(series):
    return series.size

 #drawdons functions are mine 
def maximum_drawdown(series):
    series = np.asarray(series)
    if len(series)<2:
        return 0
    k = series[np.argmax(np.maximum.accumulate(series) - series)]
    i = np.argmax(np.maximum.accumulate(series) - series)
    if len(series[:i])<1:
        return np.NaN
    else:
        j = np.max(series[:i])
    return j-k

def maximum_drawup(series):
    series = np.asarray(series)
    if len(series)<2:
        return 0
    

    series = - series
    k = series[np.argmax(np.maximum.accumulate(series) - series)]
    i = np.argmax(np.maximum.accumulate(series) - series)
    if len(series[:i])<1:
        return np.NaN
    else:
        j = np.max(series[:i])
    return j-k

def drawdown_duration(series):
    series = np.asarray(series)
    if len(series)<2:
        return 0

    k = np.argmax(np.maximum.accumulate(series) - series)
    i = np.argmax(np.maximum.accumulate(series) - series)
    if len(series[:i]) == 0:
        j=k
    else:
        j = np.argmax(series[:i])
    return k-j

def drawup_duration(series):
    series = np.asarray(series)
    if len(series)<2:
        return 0

    series=-series
    k = np.argmax(np.maximum.accumulate(series) - series)
    i = np.argmax(np.maximum.accumulate(series) - series)
    if len(series[:i]) == 0:
        j=k
    else:
        j = np.argmax(series[:i])
    return k-j

def max_over_min(series):
    if len(series)<2:
        return 0
    if np.min(series) == 0:
        return np.nan
    return np.max(series)/np.min(series)

def mean_n_absolute_max(x, number_of_maxima = 1):
    """ Calculates the arithmetic mean of the n absolute maximum values of the time series."""
    assert (
        number_of_maxima > 0
    ), f" number_of_maxima={number_of_maxima} which is not greater than 1"

    n_absolute_maximum_values = np.sort(np.absolute(x))[-number_of_maxima:]

    return np.mean(n_absolute_maximum_values) if len(x) > number_of_maxima else np.NaN


def count_above(x, t):
    if len(x)==0:
        return np.nan
    else:
        return np.sum(x >= t) / len(x)

def count_below(x, t):
    if len(x)==0:
        return np.nan
    else:
        return np.sum(x <= t) / len(x)

 #number of valleys = number_peaks(-x, n) 
def number_peaks(x, n):
    """     Calculates the number of peaks of at least support n in the time series x. A peak of support n is defined as a     subsequence of x where a value occurs, which is bigger than its n neighbours to the left and to the right.     """
    x_reduced = x[n:-n]

    res = None
    for i in range(1, n + 1):
        result_first = x_reduced > _roll(x, i)[n:-n]

        if res is None:
            res = result_first
        else:
            res &= result_first

        res &= x_reduced > _roll(x, -i)[n:-n]
    return np.sum(res)

def mean_abs_change(x):
    return np.mean(np.abs(np.diff(x)))

def mean_change(x):
    x = np.asarray(x)
    return (x[-1] - x[0]) / (len(x) - 1) if len(x) > 1 else np.NaN

def mean_second_derivative_central(x):
    x = np.asarray(x)
    return (x[-1] - x[-2] - x[1] + x[0]) / (2 * (len(x) - 2)) if len(x) > 2 else np.NaN


def root_mean_square(x):
    return np.sqrt(np.mean(np.square(x))) if len(x) > 0 else np.NaN

def absolute_sum_of_changes(x):
    return np.sum(np.abs(np.diff(x)))

def longest_strike_below_mean(x):
    if not isinstance(x, (np.ndarray, pd.Series)):
        x = np.asarray(x)
    return np.max(_get_length_sequences_where(x < np.mean(x))) if x.size > 0 else 0

def longest_strike_above_mean(x):
    if not isinstance(x, (np.ndarray, pd.Series)):
        x = np.asarray(x)
    return np.max(_get_length_sequences_where(x > np.mean(x))) if x.size > 0 else 0

def count_above_mean(x):
    m = np.mean(x)
    return np.where(x > m)[0].size

def count_below_mean(x):
    m = np.mean(x)
    return np.where(x < m)[0].size

def last_location_of_maximum(x):
    x = np.asarray(x)
    return 1.0 - np.argmax(x[::-1]) / len(x) if len(x) > 0 else np.NaN

def first_location_of_maximum(x):
    if not isinstance(x, (np.ndarray, pd.Series)):
        x = np.asarray(x)
    return np.argmax(x) / len(x) if len(x) > 0 else np.NaN

def last_location_of_minimum(x):
    x = np.asarray(x)
    return 1.0 - np.argmin(x[::-1]) / len(x) if len(x) > 0 else np.NaN

def first_location_of_minimum(x):
    if not isinstance(x, (np.ndarray, pd.Series)):
        x = np.asarray(x)
    return np.argmin(x) / len(x) if len(x) > 0 else np.NaN

 # Test non-consecutive non-reoccuring values ? 
def percentage_of_reoccurring_values_to_all_values(x):
    if len(x) == 0:
        return np.nan
    unique, counts = np.unique(x, return_counts=True)
    if counts.shape[0] == 0:
        return 0
    return np.sum(counts > 1) / float(counts.shape[0])

def percentage_of_reoccurring_datapoints_to_all_datapoints(x):
    if len(x) == 0:
        return np.nan
    if not isinstance(x, pd.Series):
        x = pd.Series(x)
    value_counts = x.value_counts()
    reoccuring_values = value_counts[value_counts > 1].sum()
    if np.isnan(reoccuring_values):
        return 0

    return reoccuring_values / x.size


def sum_of_reoccurring_values(x):
    unique, counts = np.unique(x, return_counts=True)
    counts[counts < 2] = 0
    counts[counts > 1] = 1
    return np.sum(counts * unique)

def sum_of_reoccurring_data_points(x):
    unique, counts = np.unique(x, return_counts=True)
    counts[counts < 2] = 0
    return np.sum(counts * unique)

def ratio_value_number_to_time_series_length(x):
    if not isinstance(x, (np.ndarray, pd.Series)):
        x = np.asarray(x)
    if x.size == 0:
        return np.nan

    return np.unique(x).size / x.size

def abs_energy(x):
    if not isinstance(x, (np.ndarray, pd.Series)):
        x = np.asarray(x)
    return np.dot(x, x)

def quantile(x, q):
    if len(x) == 0:
        return np.NaN
    return np.quantile(x, q)

 # crossing the mean ? other levels ?  
def number_crossing_m(x, m):
    if not isinstance(x, (np.ndarray, pd.Series)):
        x = np.asarray(x)
     # From https://stackoverflow.com/questions/3843017/efficiently-detect-sign-changes-in-python 
    positive = x > m
    return np.where(np.diff(positive))[0].size

def absolute_maximum(x):
    return np.max(np.absolute(x)) if len(x) > 0 else np.NaN

def value_count(x, value):
    if not isinstance(x, (np.ndarray, pd.Series)):
        x = np.asarray(x)
    if np.isnan(value):
        return np.isnan(x).sum()
    else:
        return x[x == value].size

def range_count(x, min, max):
    return np.sum((x >= min) & (x < max))

def mean_diff(x):
    return np.nanmean(np.diff(x.values))

base_stats = ['mean','sum','size','count','std','first','last','min','max',median,skewness,kurtosis]
higher_order_stats = [abs_energy,root_mean_square,sum_values,realized_volatility,realized_abs_skew,realized_skew,realized_vol_skew,realized_quarticity]
additional_quantiles = [quantile_01,quantile_025,quantile_075,quantile_09]
other_min_max = [absolute_maximum,max_over_min]
min_max_positions = [last_location_of_maximum,first_location_of_maximum,last_location_of_minimum,first_location_of_minimum]
peaks = [number_peaks_2, mean_n_absolute_max_2, number_peaks_5, mean_n_absolute_max_5, number_peaks_10, mean_n_absolute_max_10]
counts = [count_unique,count,count_above_0,count_below_0,value_count_0,count_near_0]
reoccuring_values = [count_above_mean,count_below_mean,percentage_of_reoccurring_values_to_all_values,percentage_of_reoccurring_datapoints_to_all_datapoints,sum_of_reoccurring_values,sum_of_reoccurring_data_points,ratio_value_number_to_time_series_length]
count_duplicate = [count_duplicate,count_duplicate_min,count_duplicate_max]
variations = [mean_diff,mean_abs_change,mean_change,mean_second_derivative_central,absolute_sum_of_changes,number_crossing_0]
ranges = [variance_std_ratio,ratio_beyond_01_sigma,ratio_beyond_02_sigma,ratio_beyond_03_sigma,large_standard_deviation,range_ratio]

参考文献:

https://www.kaggle.com/code/lucasmorin/amex-feature-engineering-2-aggreg-functions

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
四位好莱坞女星泳装热舞视频爆火,网友:身材太绝了

四位好莱坞女星泳装热舞视频爆火,网友:身材太绝了

娱圈观察员
2026-08-23 00:17:15
随着曼联爆冷0-2,埃弗顿2-0,利兹联1-0,英超最新积分榜出炉

随着曼联爆冷0-2,埃弗顿2-0,利兹联1-0,英超最新积分榜出炉

侧身凌空斩
2026-08-23 00:03:54
中国经济接下来:会发生什么?

中国经济接下来:会发生什么?

生命可以承受之轻
2026-08-22 15:41:30
60岁大爷勇闯AI做动画被全网催更 独家专访:作品灵魂由人把控

60岁大爷勇闯AI做动画被全网催更 独家专访:作品灵魂由人把控

封面新闻
2026-08-22 13:14:21
王祉怡:自己真正拼尽全力之后,就没有任何遗憾了

王祉怡:自己真正拼尽全力之后,就没有任何遗憾了

懂球帝
2026-08-23 00:27:06
刚刚,“苏超”积分榜更新!

刚刚,“苏超”积分榜更新!

扬子晚报
2026-08-22 22:03:05
宏远热身赛84-84广州!新主帅亲自指挥,陈家政表现出色,杨腾飞有惊喜

宏远热身赛84-84广州!新主帅亲自指挥,陈家政表现出色,杨腾飞有惊喜

多特体育说
2026-08-22 22:17:15
升学宴5死再升级!亲历者终于说出实情,墙塌另有原因,本可避免

升学宴5死再升级!亲历者终于说出实情,墙塌另有原因,本可避免

就一点
2026-08-21 15:35:53
官方回应“白菜收购蘸取甲醛溶液问题”:情况属实,相关人员车辆被采取强制措施

官方回应“白菜收购蘸取甲醛溶液问题”:情况属实,相关人员车辆被采取强制措施

界面新闻
2026-08-22 15:56:59
甲醛白菜,一毒14年

甲醛白菜,一毒14年

呦呦鹿鸣
2026-08-22 21:38:36
去了上海安福路才发现:满街都在穿“中产三件套”,舒适又高级

去了上海安福路才发现:满街都在穿“中产三件套”,舒适又高级

白宸侃片
2026-08-23 01:18:58
这种身材在普通人家都嫁不出去!人大附中女孩引争议,走路都费劲

这种身材在普通人家都嫁不出去!人大附中女孩引争议,走路都费劲

世界圈
2026-08-20 09:29:58
不再保持中立,东盟国家密集“选边站”,台海叙事正在被彻底改写

不再保持中立,东盟国家密集“选边站”,台海叙事正在被彻底改写

麓谷隐士
2026-08-22 08:08:44
卡地亚晚宴“见光死”,舒淇嫩了,张婧仪歪嘴,萧敬腾咋皮包骨了

卡地亚晚宴“见光死”,舒淇嫩了,张婧仪歪嘴,萧敬腾咋皮包骨了

洲洲影视娱评
2026-08-22 13:53:17
妻子被侵犯后体内查出三人DNA,她哭着说是情夫的。可调完监控,警察说她在说谎

妻子被侵犯后体内查出三人DNA,她哭着说是情夫的。可调完监控,警察说她在说谎

温情故事匣
2026-08-22 15:29:02
2:1!贝林闪击+姆巴佩哑火,新援90分钟绝杀,穆帅二进宫开门红

2:1!贝林闪击+姆巴佩哑火,新援90分钟绝杀,穆帅二进宫开门红

阿超他的体育圈
2026-08-23 06:23:16
就在大家都以为中国会坚决回应时,北京却选择了战略克制。

就在大家都以为中国会坚决回应时,北京却选择了战略克制。

回京历史梦
2026-08-22 18:23:43
唐田:不是输了球就没办法谈尊严;比赛最后发生了不可控的事

唐田:不是输了球就没办法谈尊严;比赛最后发生了不可控的事

懂球帝
2026-08-22 22:53:55
王菲现身那英演唱会现场,坐在观众席开心摇晃荧光棒跟唱;宋丹丹、龚俊、张晚意、张雅琪、李沁、杨坤、张碧晨、屠洪刚等明星纷纷现身

王菲现身那英演唱会现场,坐在观众席开心摇晃荧光棒跟唱;宋丹丹、龚俊、张晚意、张雅琪、李沁、杨坤、张碧晨、屠洪刚等明星纷纷现身

大风新闻
2026-08-22 20:58:14
局势失控?乌军炸毁朝鲜援俄军火专列,事发地距黑龙江仅一江之隔

局势失控?乌军炸毁朝鲜援俄军火专列,事发地距黑龙江仅一江之隔

陌上桃花开的
2026-08-22 04:16:57
2026-08-23 06:47:00
Ai学习的老章 incentive-icons
Ai学习的老章
Ai学习的老章
3511文章数 11195关注度
往期回顾 全部

科技要闻

苹果裁员200人:Vision Pro砍游戏团队

头条要闻

全季起诉“金季”索赔10万 老板娘:日租才50到60元

头条要闻

全季起诉“金季”索赔10万 老板娘:日租才50到60元

体育要闻

字母+汤神,有没有搞头?

娱乐要闻

《空枪》预测票房缩水,手握王炸都没赢

财经要闻

蔡昉解读经济:扩大消费需求的政策思考

汽车要闻

钛9全球首秀/四季度上市 方程S系列内饰车展亮相

态度原创

本地
手机
时尚
公开课
军事航空

本地新闻

《牛来》的一声“妈妈”,到底多少人被精神污染了

手机要闻

小米18 Pro透明探索版回归:致敬一代经典小米8

真爱返场|| 5年如一日的心头好,这个价格真香

公开课

李玫瑾:为什么性格比能力更重要?

军事要闻

披露林肯号航母内幕的美国军报多人被炒

无障碍浏览 进入关怀版