featuretools 历史标签计数
featuretools historical label counts
背景
对于 CRM 项目,我有机会的快照。我已经能够使用 featuretools
构建许多功能,但我真正想要的是拥有历史获胜次数和比率。换句话说,我想知道:
For a given opportunity, how many deals have been won up until the opportunity was last modified?
示例数据
import pandas as pd
import featuretools as ft
df = pd.DataFrame(
{'OpportunityId': [111, 111, 222, 222, 222, 333, 333, 333],
'UpdateId': [1,3,2,5,7,4,6,8],
'Label': ['Open', 'Win', 'Open', 'Open', 'Win', 'Open', 'Open', 'Open'],
'CreatedOn': pd.to_datetime(['9/27/18','9/27/18','9/28/18','9/28/18','9/28/18','10/2/18','10/2/18','10/2/18']),
'ModifiedOn': pd.to_datetime(['9/27/18','10/1/18','9/28/18','10/3/18','10/7/18','10/2/18','10/6/18','10/10/18']),
'EstRevenue': [2000, 2000, 80000, 84000, 78000, 100000, 95000, 110000]})
df
| OpportunityId | UpdateId | Label | CreatedOn | ModifiedOn | EstRevenue |
|---------------|----------|-------|------------|------------|------------|
| 111 | 1 | Open | 2018-09-27 | 2018-09-27 | 2000 |
| 111 | 3 | Win | 2018-09-27 | 2018-10-01 | 2000 |
| 222 | 2 | Open | 2018-09-28 | 2018-09-28 | 80000 |
| 222 | 5 | Open | 2018-09-28 | 2018-10-03 | 84000 |
| 222 | 7 | Win | 2018-09-28 | 2018-10-07 | 78000 |
| 333 | 4 | Open | 2018-10-02 | 2018-10-02 | 100000 |
| 333 | 6 | Open | 2018-10-02 | 2018-10-06 | 95000 |
| 333 | 8 | Open | 2018-10-02 | 2018-10-10 | 110000 |
期望的输出
| OPPORTUNITIES | Label | CreatedOn | Max( ModifiedOn ) | AVG( EstRevenue ) | Wins |
|---------------|-------|-----------|-------------------|------------------:|------|
| 111 | Win | 9/27/18 | 10/1/18 | 2000 | 0 |
| 222 | Win | 9/28/18 | 10/7/18 | 80667 | 1 |
| 333 | Open | 10/2/18 | 10/10/18 | 101667 | 2 |
到目前为止的尝试
让我费尽心思的是...
- 依赖于多个机会的功能...我需要一个单独的实体吗?
- 我如何聚合
Label
来提供以下两者:
- 当前值
Label
,
Label
列为0时的计数
我的挑战是 Label
专栏...虽然通常我会制作 CurrentLabel
专栏,但我很确定 ft
可以处理这个...
es = (ft.EntitySet(id='CRM')
.entity_from_dataframe(
entity_id='updates',
dataframe=df,
index='UpdateId',
time_index='ModifiedOn')
.normalize_entity(
base_entity_id='updates',
new_entity_id='opportunities',
index='OpportunityId',
make_time_index='CreatedOn',
copy_variables=['Label'],
additional_variables=['CreatedOn']
)
)
es['updates']['Label'].interesting_values = ['Win']
Entityset: CRM
Entities:
updates [Rows: 8, Columns: 5]
opportunities [Rows: 3, Columns: 3]
Relationships:
updates.OpportunityId -> opportunities.OpportunityId
feature_matrix, feature_defs = ft.dfs(
entityset=es,
target_entity="opportunities",
agg_primitives=[
"mean","count","num_unique","time_since_first"],
trans_primitives=[
'time_since_previous'],
where_primitives=[
"sum","count"],
max_depth=2,
verbose=1
)
有几种不同的方法可以解决这个问题:
- 创建一个新的数据框列并使用
last
聚合原语
对于这种方法,在创建实体集之前,首先在数据框中创建一个新的 Wins
列,用于跟踪一段时间内的累计获胜总数。您可能需要按 ModifiedOn
列对数据框进行排序,以确保累计和值正确。此外,我在这里使用 .shift()
将列值移动一个位置,以仅计算 在 更新之前发生的胜利:
df = df.sort_values('ModifiedOn')
df['Wins'] = df['Label'].shift().eq('Win').cumsum()
当您 运行 深度特征合成时,将 last
基元添加到您的 agg_primitives
列表中:
feature_matrix, feature_defs = ft.dfs(
entityset=es,
target_entity="opportunities",
agg_primitives=["mean", "count", "num_unique", "time_since_first", "last"],
trans_primitives=["time_since_previous"],
where_primitives=["sum", "count"],
max_depth=2,
verbose=1
)
现在,当您检查特征矩阵时,您将看到一个标记为 LAST(updates.Label)
的列,该列显示机会上次更新时 Label
的值。您还将有一个标记为 LAST(updates.Wins)
的列,显示上次更新机会时的总获胜次数。
- 使用带有自定义基元的种子特征
这种方法在概念上与第一种方法相似,但使用种子特征和自定义原语来获得所需的输出。
在 运行 深度特征合成之前,创建一个新的布尔种子特征,定义 Label
是否等于 Win
:
label_is_win = ft.Feature(es["updates"]["Label"]) == "Win"
接下来,定义一个自定义转换基元,它将使用此种子功能来 return 获胜的累积总和:
class ShiftedCumSumBoolean(ft.primitives.TransformPrimitive):
name = "shifted_cum_sum_boolean"
input_types = [ft.variable_types.Boolean]
return_type = ft.variable_types.Numeric
uses_full_entity = True
def get_function(self):
def shifted_cum_sum(values):
return values.shift(fill_value=(False)).cumsum()
return shifted_cum_sum
当你运行深度特征合成时,将新的ShiftedCumSumBoolean
基元添加到trans_primitives
的列表中。此外,将 last
原语添加到 agg_primitives
的列表中,以在机会更新时提供最后一个标签值。最后,将 label_is_win
种子特征添加到 ft.dfs
调用中的种子特征列表:
feature_matrix, feature_defs = ft.dfs(
entityset=es,
target_entity="opportunities",
agg_primitives=["mean","count","num_unique","time_since_first", "last"],
trans_primitives=["time_since_previous", ShiftedCumSumBoolean],
where_primitives=["sum", "count"],
seed_features=[label_is_win],
max_depth=2,
verbose=1,
)
使用此解决方案,您的特征矩阵将有一个标记为 LAST(updates.Label)
的列,显示上次更新商机时 Label
的值。您还将有一个标记为 LAST(updates.SHIFTED_CUM_SUM_BOOLEAN(Label = Win))
的列,显示上次更新机会时的总获胜次数。
背景
对于 CRM 项目,我有机会的快照。我已经能够使用 featuretools
构建许多功能,但我真正想要的是拥有历史获胜次数和比率。换句话说,我想知道:
For a given opportunity, how many deals have been won up until the opportunity was last modified?
示例数据
import pandas as pd
import featuretools as ft
df = pd.DataFrame(
{'OpportunityId': [111, 111, 222, 222, 222, 333, 333, 333],
'UpdateId': [1,3,2,5,7,4,6,8],
'Label': ['Open', 'Win', 'Open', 'Open', 'Win', 'Open', 'Open', 'Open'],
'CreatedOn': pd.to_datetime(['9/27/18','9/27/18','9/28/18','9/28/18','9/28/18','10/2/18','10/2/18','10/2/18']),
'ModifiedOn': pd.to_datetime(['9/27/18','10/1/18','9/28/18','10/3/18','10/7/18','10/2/18','10/6/18','10/10/18']),
'EstRevenue': [2000, 2000, 80000, 84000, 78000, 100000, 95000, 110000]})
df
| OpportunityId | UpdateId | Label | CreatedOn | ModifiedOn | EstRevenue |
|---------------|----------|-------|------------|------------|------------|
| 111 | 1 | Open | 2018-09-27 | 2018-09-27 | 2000 |
| 111 | 3 | Win | 2018-09-27 | 2018-10-01 | 2000 |
| 222 | 2 | Open | 2018-09-28 | 2018-09-28 | 80000 |
| 222 | 5 | Open | 2018-09-28 | 2018-10-03 | 84000 |
| 222 | 7 | Win | 2018-09-28 | 2018-10-07 | 78000 |
| 333 | 4 | Open | 2018-10-02 | 2018-10-02 | 100000 |
| 333 | 6 | Open | 2018-10-02 | 2018-10-06 | 95000 |
| 333 | 8 | Open | 2018-10-02 | 2018-10-10 | 110000 |
期望的输出
| OPPORTUNITIES | Label | CreatedOn | Max( ModifiedOn ) | AVG( EstRevenue ) | Wins |
|---------------|-------|-----------|-------------------|------------------:|------|
| 111 | Win | 9/27/18 | 10/1/18 | 2000 | 0 |
| 222 | Win | 9/28/18 | 10/7/18 | 80667 | 1 |
| 333 | Open | 10/2/18 | 10/10/18 | 101667 | 2 |
到目前为止的尝试
让我费尽心思的是...
- 依赖于多个机会的功能...我需要一个单独的实体吗?
- 我如何聚合
Label
来提供以下两者:- 当前值
Label
, Label
列为0时的计数
- 当前值
我的挑战是 Label
专栏...虽然通常我会制作 CurrentLabel
专栏,但我很确定 ft
可以处理这个...
es = (ft.EntitySet(id='CRM')
.entity_from_dataframe(
entity_id='updates',
dataframe=df,
index='UpdateId',
time_index='ModifiedOn')
.normalize_entity(
base_entity_id='updates',
new_entity_id='opportunities',
index='OpportunityId',
make_time_index='CreatedOn',
copy_variables=['Label'],
additional_variables=['CreatedOn']
)
)
es['updates']['Label'].interesting_values = ['Win']
Entityset: CRM
Entities:
updates [Rows: 8, Columns: 5]
opportunities [Rows: 3, Columns: 3]
Relationships:
updates.OpportunityId -> opportunities.OpportunityId
feature_matrix, feature_defs = ft.dfs(
entityset=es,
target_entity="opportunities",
agg_primitives=[
"mean","count","num_unique","time_since_first"],
trans_primitives=[
'time_since_previous'],
where_primitives=[
"sum","count"],
max_depth=2,
verbose=1
)
有几种不同的方法可以解决这个问题:
- 创建一个新的数据框列并使用
last
聚合原语
对于这种方法,在创建实体集之前,首先在数据框中创建一个新的 Wins
列,用于跟踪一段时间内的累计获胜总数。您可能需要按 ModifiedOn
列对数据框进行排序,以确保累计和值正确。此外,我在这里使用 .shift()
将列值移动一个位置,以仅计算 在 更新之前发生的胜利:
df = df.sort_values('ModifiedOn')
df['Wins'] = df['Label'].shift().eq('Win').cumsum()
当您 运行 深度特征合成时,将 last
基元添加到您的 agg_primitives
列表中:
feature_matrix, feature_defs = ft.dfs(
entityset=es,
target_entity="opportunities",
agg_primitives=["mean", "count", "num_unique", "time_since_first", "last"],
trans_primitives=["time_since_previous"],
where_primitives=["sum", "count"],
max_depth=2,
verbose=1
)
现在,当您检查特征矩阵时,您将看到一个标记为 LAST(updates.Label)
的列,该列显示机会上次更新时 Label
的值。您还将有一个标记为 LAST(updates.Wins)
的列,显示上次更新机会时的总获胜次数。
- 使用带有自定义基元的种子特征 这种方法在概念上与第一种方法相似,但使用种子特征和自定义原语来获得所需的输出。
在 运行 深度特征合成之前,创建一个新的布尔种子特征,定义 Label
是否等于 Win
:
label_is_win = ft.Feature(es["updates"]["Label"]) == "Win"
接下来,定义一个自定义转换基元,它将使用此种子功能来 return 获胜的累积总和:
class ShiftedCumSumBoolean(ft.primitives.TransformPrimitive):
name = "shifted_cum_sum_boolean"
input_types = [ft.variable_types.Boolean]
return_type = ft.variable_types.Numeric
uses_full_entity = True
def get_function(self):
def shifted_cum_sum(values):
return values.shift(fill_value=(False)).cumsum()
return shifted_cum_sum
当你运行深度特征合成时,将新的ShiftedCumSumBoolean
基元添加到trans_primitives
的列表中。此外,将 last
原语添加到 agg_primitives
的列表中,以在机会更新时提供最后一个标签值。最后,将 label_is_win
种子特征添加到 ft.dfs
调用中的种子特征列表:
feature_matrix, feature_defs = ft.dfs(
entityset=es,
target_entity="opportunities",
agg_primitives=["mean","count","num_unique","time_since_first", "last"],
trans_primitives=["time_since_previous", ShiftedCumSumBoolean],
where_primitives=["sum", "count"],
seed_features=[label_is_win],
max_depth=2,
verbose=1,
)
使用此解决方案,您的特征矩阵将有一个标记为 LAST(updates.Label)
的列,显示上次更新商机时 Label
的值。您还将有一个标记为 LAST(updates.SHIFTED_CUM_SUM_BOOLEAN(Label = Win))
的列,显示上次更新机会时的总获胜次数。