数据科学竞赛:递增特征构建的简单实现

数据科学竞赛:递增特征构建的简单实现,第1张

数据科学竞赛:递增特征构建的简单实现

在智能风控或者其他的数据科学竞赛当中,我们经常可以从用户的基础信息表中发现类似这样的特征:

字段英文名字段含义last_3m_avg_aum近3个月均aumlast_6m_avg_aum近6个月均aumlast_12m_avg_aum近12个月均aumlast_3m_avg_times近3个月取款平均值last_3m_avg_times近6个月取款平均值last_3m_avg_times近12个月取款平均值

这些原始的特征在建模中有着自己的“贡献力”,很显然基于这些字段我们可以生成很多的特征。有一种特征就是关于这些变量的递增变量,什么意思呢?

就是3个月均aum之间的关系:如果是递增的就将新生成的特征记录为1,反之记录为0

数据准备

在进行实验之前我们进行数据的准备,我们设置的实验数据如下:

import pandas as pd
data = [
        [1,2,3,],
        [2,3,2],
        [3,24,2],
        [4,np.nan,2],
        [5,np.nan,1]
    ]
columns = ['last_3m_avg_aum','last_6m_avg_aum','last_12m_avg_aum']
data_df = pd.Dataframe(data,columns=columns)
data_df
列递增

假设我们现在的需求是判断某一列数据是否是递增的,这个怎么实现呢?我们可以遍历某一列数据进行下一个值与当前值的比较。

显然这个办法比较蠢,还好pandas中实现了一个方法我们可以直接的调用,比如以下几个例子(代码使用jupyter notebook):

data_df['last_3m_avg_aum'].is_monotonic
data_df['last_3m_avg_aum'].is_monotonic_increasing
data_df['last_12m_avg_aum'].is_monotonic
data_df['last_12m_avg_aum'].is_monotonic_decreasing

# 依次输出:
True
True
False
True

可以看出:

is_monotonic: 用来判断严格单调的(不论是单调递增还是单调递减)

is_monotonic_increasing: 用来判断是否递增(不是严格的也行)

is_monotonic_decreasing: 用来判断是否递减(不是严格的也行)

那么关于这几个方法的实现细节,大家可以转官方文档进行查看。

这是关于列递增的方式,使用Pandas自带的方法就可以完成。

行递增

上述方式判断是列递增,那么怎么实现行数据的递增判断呢?接下来我们提供几种思路和方法供大家考虑,也欢迎小伙伴提出新的方法:

(1)第1种方法就是简单的使用for循环取数进行判断,由于过于简单就不在演示。

(2)第2种方法是对目标dataframe进行转置,再使用自带的方法进行判断,接下来我将写一个函数,用来判断每一行数据是否都是递增的,并新增一列来存储判断的结果:

import gc
import pandas as pd
def progressive_increasing(df,columns,newcolname):
    df_T = df[columns].T
    df[newcolname] = df_T.apply(lambda x:x.is_monotonic)
    df[newcolname] = df[newcolname].astype(int)
    del df_T
    gc.collect()
    return df
columns = ['last_3m_avg_aum','last_6m_avg_aum','last_12m_avg_aum']
new_df = progressive_increasing(data_df,columns,'is_increasing')

打印new_df的输出为:

is_increasing列存储了我们需要的特征,上述函数还是比较好用的,传入三个参数就可以实现我们的需求。

是不是觉得自己特别的秀呢?但是在实际使用的时候会出现一个问题,当我们的数据量很大的时候,比如说我当时处理100W个样本的时候,此时这个函数就跑不动了。那么出现的问题在哪呢?大家自己找答案。

找答案的时候我们会发现一个新的问题:大矩阵/大稀疏矩阵的转置问题。

感觉又有话题讨论了,不过这次我们不讨论。

另外上述方法中有一个小技巧,就是使用了gc.collect(),可以帮助我们在大量数据的情况下节省点内存。

为了解决这个函数跑不动的问题,我就又写了一个方法。这个方法最终是我构建特征的方案。

(3)方法3说简单也是非常简单的,talk is cheap, show you the code:

import pandas as pd
def progressive_increasing_use(df,columns,newcolname):
    df[newcolname] = (df[columns[1]] > df[columns[0]]) & (df[columns[2]] > df[columns[0]])
    df[newcolname] = df[newcolname].astype(int)
    return df
columns = ['last_3m_avg_aum','last_6m_avg_aum','last_12m_avg_aum']
new_df = progressive_increasing_use(data_df,columns,'is_increasing')
new_df

输出如下:

结果与上述第2种方法一模一样,那么该方法与第二个方法相比有运行速度上有什么区别呢?我们使用 %%time来看一下:

100次运行消耗的时间1.97s,如果我们把内存回收的代码出去,我们来看一下时间:

这个时间要省很多了,大概190ms。由于dataframe比较小,所以这个回收一下内存的时间就显得比较大。再看一下第3种方法的时间:

显然第3种方法消耗的时间是最短的。当我们处理的dataframe很大的时候,不同方法之间的时间差距会拉开的更多,大家可以创建一个超大的dataframe进行试验一下。

总结

本次文章我们以构建特征工程中遇到的一个问题出发,讲解了如何计算一个increasing趋势特征,并引出一个值得思考的问题:大矩阵的转置(存储)。如果有空我们下期推文将研究一下大矩阵的相关问题。另外我们还可以构建其他的特征,如:每一行大于这行平均值的个数特征等等。

以上就是本次文章的全部内容,亲爱的朋友下次再见。

一天介绍一本书

Python数据分析与大数据处理从入门到精通:本书主要讲解数据分析与大数据处理所需的技术、基础设施、核心概念、实施流程。从编程语言准备、数据采集与清洗、数据分析与可视化,到大型数据的分布式存储与分布式计算,贯穿了整个大数据项目开发流程。


点击这里,阅读更多数据文章!

欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/zaji/5671173.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存