前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >数据科学竞赛:递增特征构建的简单实现

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

作者头像
朱小五
发布2021-12-15 18:07:19
8740
发布2021-12-15 18:07:19
举报
文章被收录于专栏:凹凸玩数据凹凸玩数据

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

字段英文名

字段含义

last_3m_avg_aum

近3个月均aum

last_6m_avg_aum

近6个月均aum

last_12m_avg_aum

近12个月均aum

last_3m_avg_times

近3个月取款平均值

last_3m_avg_times

近6个月取款平均值

last_3m_avg_times

近12个月取款平均值

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

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

数据准备

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

代码语言:javascript
复制
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):

代码语言:javascript
复制
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进行转置,再使用自带的方法进行判断,接下来我将写一个函数,用来判断每一行数据是否都是递增的,并新增一列来存储判断的结果:

代码语言:javascript
复制
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:

代码语言:javascript
复制
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趋势特征,并引出一个值得思考的问题:大矩阵的转置(存储)。如果有空我们下期推文将研究一下大矩阵的相关问题。另外我们还可以构建其他的特征,如:每一行大于这行平均值的个数特征等等。

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

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-12-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 凹凸数据 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 数据准备
  • 列递增
  • 行递增
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档