Featuretools 1.1x按customer_id聚合timestamp的min/max实现方法咨询
在FeatureTools 1.1x中对Datetime字段按分组计算Min/Max的解决方案
问题原因
FeatureTools内置的min/max聚合原语仅支持数值类型,无法直接作用于Datetime字段,但可以通过自定义聚合原语来实现需求。
解决方案:自定义Datetime聚合原语
通过继承FeatureTools的AggregationPrimitive类,实现针对Datetime类型的min和max聚合逻辑,然后在DFS任务中使用这些自定义原语。
完整代码示例
import featuretools as ft import pandas as pd import numpy as np from featuretools.primitives import AggregationPrimitive from featuretools.variable_types import Datetime # 自定义Datetime最小值聚合原语 class DatetimeMin(AggregationPrimitive): name = "datetime_min" input_types = [Datetime] return_type = Datetime def get_function(self): return pd.Series.min # 自定义Datetime最大值聚合原语 class DatetimeMax(AggregationPrimitive): name = "datetime_max" input_types = [Datetime] return_type = Datetime def get_function(self): return pd.Series.max # 生成测试数据 n = 100 events_df = pd.DataFrame({ "id" : range(n), "customer_id": np.random.choice(["a", "b", "c"], n), "timestamp": pd.date_range("Jan 1, 2019", freq="1h", periods=n), "amount": np.random.rand(n) * 100 }) # 创建EntitySet,修正index参数为数据中的主键列"id" es = ft.EntitySet(id='my_set') es = es.add_dataframe( dataframe=events_df, dataframe_name='events', time_index='timestamp', index='id' ) # 运行DFS生成特征 feature_matrix, feature_defs = ft.dfs( entityset=es, target_dataframe_name='events', agg_primitives=['datetime_min', 'datetime_max', 'max'], trans_primitives=[], primitive_options={ # 对所有聚合原语设置按customer_id分组 "*": { "include_groupby_columns": {"events": ["customer_id"]} } } ) # 查看结果示例 print(feature_matrix[['datetime_min_timestamp_by_customer_id', 'datetime_max_timestamp_by_customer_id', 'max_amount_by_customer_id']].head())
代码说明
- 自定义原语:
DatetimeMin和DatetimeMax指定输入/输出类型为Datetime,内部调用Pandas原生的Series.min/Series.max方法,天然支持Datetime类型的聚合。
- EntitySet修正:原代码中
add_dataframe的index参数错误,需设置为数据中的唯一标识列id,否则会导致EntitySet初始化失败。 - DFS配置:
- 将自定义原语
datetime_min、datetime_max与内置的max(用于amount字段)一起加入agg_primitives。 - 使用
"*"匹配所有聚合原语,统一设置按customer_id分组,避免单独配置每个原语。
- 将自定义原语
备选方案:转成数值型时间戳
如果不想自定义原语,可以先将Datetime转成Unix时间戳(数值类型),用内置min/max聚合后再转回Datetime:
# 在生成测试数据后添加时间戳列 events_df['timestamp_unix'] = events_df['timestamp'].view('int64') // 10**9 # 后续DFS使用内置min/max聚合timestamp_unix,之后再转回Datetime # 聚合完成后: feature_matrix['min_timestamp'] = pd.to_datetime(feature_matrix['min_timestamp_unix_by_customer_id'], unit='s') feature_matrix['max_timestamp'] = pd.to_datetime(feature_matrix['max_timestamp_unix_by_customer_id'], unit='s')
这种方法更快捷,但自定义原语的方式更符合FeatureTools的特征工程流程,代码可维护性更强。
内容的提问来源于stack exchange,提问作者Xue
相关产品推荐
相关产品推荐

