问题描述
我正在尝试在 Featuretools 中创建一个自定义 TransformPrimitive 来计算滚动统计数据,如滚动总和或平均值。
This article explains well 如何使用 Pandas 完成此类任务。它展示了如何在使用 'window' 参数来表示用于计算统计量的观察数量时如何让事情运行起来。
但是,我打算提供一个字符串输入来计算以天为单位的偏移量。下面的行在概念上正确计算了我需要的东西。
transactions.groupby('ID').rolling(window='10D',on='TransactionDate')[['Quantity','AmountPaid']].sum()
TransformPrimitive 如下所示:
class RollingSum(TransformPrimitive):
"""Calculates the rolling sum.
Description:
Given a list of values,return the rolling sum.
"""
name = "rolling_sum"
input_types = [NaturalLanguage,NaturalLanguage]
return_type = Numeric
uses_full_entity = True
description_template = "the rolling sum of {}"
def __init__(self,window=None,on=None):
self.window = window
self.on = on
def get_function(self):
def rolling_sum(values):
"""method is passed a pandas series"""
return values.rolling(window=self.window,on=self.on).sum()
return rolling_sum
我试图从实体集中传递 TransactionDate 变量:
features_defs = ft.dfs(
entityset=es,max_depth=2,target_entity='CUSTOMER',agg_primitives=['sum'],groupby_trans_primitives=[
RollingSum(window='10D',on=es['TRANSACTION']['TransactionDate'])
],cutoff_time = label_times,cutoff_time_in_index=False,include_cutoff_time=False,features_only=True
)
但没有成功。我收到未使用的原始警告:
在 DFS 期间未使用某些指定的原语: groupby_trans_primitives: ['rolling_sum'] 这可能是由于使用的 max_depth 值太小,没有设置有趣的值,或者可能表明在数据中找不到与原语兼容的变量类型。 warnings.warn(warning_msg,UnusedPrimitiveWarning)
非常感谢您的建议!
解决方法
您尝试为 on 参数提供日期时间变量 es['TRANSACTION']['TransactionDate']
是正确的,但 Pandas 不知道如何处理 Featuretools 变量,因此这可能是一个好机会创建一个新的原语,RollingSumOnDatetime
。
您可以对此处的 RollingSum
原语进行一些更改,以便它可以使用您的日期时间列。
-
input_types
应该是[Numeric,DatetimeTimeIndex]
因为 用于滚动平均值的日期时间列必须是 存在于用于制作pd.DataFrame.rolling
称呼。 Numeric 变量是因为滚动只能是 在数字列上计算。DatetimeTimeIndex
变量 确保该系列将是一个单调的日期时间(因为 featuretools 将对时间索引进行排序),这是另一个要求 计算滚动总和。 - rolling_sum 函数应该将
Numeric
和DatetimeTimeIndex
列组合到一个 DataFrame 中,并且应该根据所需窗口计算滚动。
我想象 Primitive 看起来像这样:
class RollingSumOnDatetime(TransformPrimitive):
"""Calculates the rolling sum on a Datetime time index column.
Description:
Given a list of values and a Datetime time index,return the rolling sum.
"""
name = "rolling_sum_on_datetime"
input_types = [Numeric,DatetimeTimeIndex]
return_type = Numeric
uses_full_entity = True
description_template = "the rolling sum of {} on {}"
def __init__(self,window=None):
self.window = window
def get_function(self):
def rolling_sum(to_roll,on_column):
"""method is passed a pandas series"""
#create a DataFrame that has the both columns in it
df = pd.DataFrame({to_roll.name:to_roll,on_column.name:on_column})
rolled_df = df.rolling(window=self.window,on=on_column.name).sum()
return rolled_df[to_roll.name]
return rolling_sum