Как создать новые переменные по нескольким идентификаторам в featuretools? - PullRequest
0 голосов
/ 13 февраля 2020

У меня есть набор данных, в котором по одной строке для каждого участника и для каждой транзакции, и есть разные магазины, в которых покупка могла быть получена из 'brand_id'. Я хочу использовать featuretools, чтобы выводить по одной строке на каждого участника с совокупным «доходом» по каждому идентификатору бренда.

Что я хочу:

import featuretools as ft
import pandas as pd

df = pd.DataFrame({'member_id': [1,1,1,1,2,2,3,4,4,4,4,5,5,5],
                   'transaction_id': [1,2,3,4,5,6,7,8,9,10,11,12,13,14],
                   'brand_id': ['A','A','B','B','B','B','A','B','A','B','B','A','B','A'],
                   'revenue': [32,124,54,12,512,51,12,4,12,412,512,14,89,12]
                  })

df2 = df.groupby(
            ['member_id',
             'brand_id']
        ).agg({
            'transaction_id': 'count',
            'revenue' :['sum', 'mean']}
        ).reset_index()

df2.columns = ['member_id', 'brand_id', 'transactions', 'revenue_sum', 'revenue_mean']

df2 = df2.pivot(index='member_id', 
                columns='brand_id', 
                values=['transactions',
                      'revenue_sum',
                      'revenue_mean']
               ).fillna(0
               ).reset_index()

groups = ['A', 'B']
df2.columns = ['memberid'] + \
              [x + '_transactions_count' for x in groups] + \
              [x + '_revenue_sum' for x in groups] + \
              [x + '_revenue_mean' for x in groups]

Вот как выглядит вывод:

enter image description here

Вот моя попытка использовать инструментальные средства, но независимо от того, что я пробовал, я не могу заставить его создавать новые переменные, разбитые по каждому уникальному значению «brand_id».

es = ft.EntitySet(id = 'my_set')
es.entity_from_dataframe(entity_id='members',
                        index='member_id',
                        dataframe = pd.DataFrame({'member_id':[1,2,3,4,5]})
                        )

es.entity_from_dataframe(entity_id='trans',
                        index='transaction_id',
                        variable_types = {'brand_id': ft.variable_types.Id},
                        dataframe=df.copy()
                        )
# create the relationship
r_member_accrual = ft.Relationship(es['members']['member_id'],
                                   es['trans']['member_id'])
# add the relationship to the entity set
es = es.add_relationship(r_member_accrual)

fm, fl = ft.dfs(target_entity='members',
               entityset=es,
               agg_primitives=['sum','mean','count'],
               groupby_trans_primitives=["cum_sum"],
               primitive_options={
                   'cum_sum': {
                       'ignore_groupby_variables': {'trans':['member_id']}
                   }
               }
               )

Вот результат, который я получаю, но это не то, чего я добиваюсь. enter image description here

1 Ответ

1 голос
/ 14 февраля 2020

Вы можете использовать interesting_values с where_primitives для агрегирования дохода на одного участника и бренд. Я пойду через пример. Сначала мы создаем набор сущностей, используя транзакции в качестве базовой.

es = ft.EntitySet()

es.entity_from_dataframe(
    entity_id='transactions',
    index='transaction_id',
    dataframe=df,
)

Затем мы нормализуем сущности для участников и брендов. Это автоматически создаст отношения.

es.normalize_entity(
    base_entity_id='transactions',
    new_entity_id='brands',
    index='brand_id',
)

es.normalize_entity(
    base_entity_id='transactions',
    new_entity_id='members',
    index='member_id',
)

Теперь мы добавим интересные значения к brand_id в транзакциях. Это позволяет нам создавать функции, обусловленные ценностями бренда.

es['transactions']['brand_id'].interesting_values = ['A', 'B']

Наконец, мы запускаем DFS, используя where_primitives, чтобы указать, какие примитивы агрегации могут создавать функции, основанные на интересных значениях.

fm, fl = ft.dfs(
    target_entity='members',
    entityset=es,
    agg_primitives=['sum', 'mean', 'count'],
    where_primitives=['sum', 'mean', 'count'],
)

fm.filter(regex='WHERE').round(1).T
member_id                                          1      2     3      4     5
COUNT(transactions WHERE brand_id = A)           2.0    0.0   1.0    1.0   2.0
COUNT(transactions WHERE brand_id = B)           2.0    2.0   0.0    3.0   1.0
SUM(transactions.revenue WHERE brand_id = A)   156.0    0.0  12.0   12.0  26.0
SUM(transactions.revenue WHERE brand_id = B)    66.0  563.0   0.0  928.0  89.0
MEAN(transactions.revenue WHERE brand_id = A)   78.0    NaN  12.0   12.0  13.0
MEAN(transactions.revenue WHERE brand_id = B)   33.0  281.5   NaN  309.3  89.0

Дайте мне знать, если это поможет.

...