关于featuretools,排名结果是错误的

Regarding featuretools, the rank results are wrong

使用Featuretools,我想将某个特征的值转换为排名。

这将是确切的问题。如果有人可以帮助我,请回答。

首先,下面的代码使用了pandas的rank函数并显示结果。我相信这个结果是正确的。

import pandas as pd
df = pd.DataFrame({'col1': [50, 80, 100, 80,90,100,150],
                   'col2': [0.3, 0.05, 0.1, 0.1,0.4,0.7,0.9]})
print(df.rank(method="dense",ascending=True))

但是,当我创建一个自定义基元和 运行 下面的代码时,结果是不同的。为什么会这样?如果错误,请修复我的代码。非常感谢您的帮助。

from featuretools.primitives import TransformPrimitive
from featuretools.variable_types import Numeric
import pandas as pd

class Rank(TransformPrimitive):
    name = 'rank'
    input_types = [Numeric]
    return_type = Numeric

    def get_function(self):
        def rank(column):
            return column.rank(method="dense",ascending=True)     
        return rank

df = pd.DataFrame({'col1': [50, 80, 100, 80,90,100,150],
                   'col2': [0.3, 0.05, 0.1, 0.1,0.4,0.7,0.9]})

import featuretools as ft
es = ft.EntitySet(id="test_es",     
                  entities=None,
                  relationships=None)

es.entity_from_dataframe(entity_id="data",
                         dataframe=df,
                         index="index",
                         variable_types=None,
                         make_index=True,
                         time_index=None,
                         secondary_time_index=None,
                         already_sorted=False)

feature_matrix, feature_defs = ft.dfs(entities=None,
                                      relationships=None,
                                      entityset=es,  
                                      target_entity="data", 
                                      cutoff_time=None,
                                      instance_ids=None,
                                      agg_primitives=None, 
                                      trans_primitives=[Rank], 
                                      groupby_trans_primitives=None, 
                                      allowed_paths=None,
                                      max_depth=2,
                                      ignore_entities=None, 
                                      ignore_variables=None, 
                                      primitive_options=None, 
                                      seed_features=None, 
                                      drop_contains=None,
                                      drop_exact=None,
                                      where_primitives=None,
                                      max_features=-1,
                                      cutoff_time_in_index=False,
                                      save_progress=None,
                                      features_only=False,
                                      training_window=None,
                                      approximate=None,
                                      chunk_size=None,
                                      n_jobs=-1,
                                      dask_kwargs=None,
                                      verbose=False,
                                      return_variable_types=None,
                                      progress_callback=None,     
                                      include_cutoff_time=False)
feature_matrix 

这是结果。

enter image description here

然而,当我尝试下面的代码时,我能够得到正确的数据。 为什么答案不同?

import pandas as pd
df = pd.DataFrame({'col1': [50, 80, 100, 80,90,100,150],
                   'col2': [0.3, 0.05, 0.1, 0.1,0.4,0.7,0.9]})
print(df.rank(method="dense",ascending=True))


pd.set_option('display.max_columns', 2000)

  
import featuretools as ft
es = ft.EntitySet()
es.entity_from_dataframe(entity_id='data',
                         dataframe=df,
                         index='index')

fm, fd = ft.dfs(entityset=es,
            target_entity='data',
            trans_primitives=[Rank])
fm

新答案: 根据您更新的代码,出现问题是因为您正在设置 njobs=-1。当您执行此操作时,Featuretools 会在幕后将特征矩阵的计算分配给多个工作人员。在这样做的过程中,Featuretools 正在分解数据框以计算工作人员之间的变换特征值并将片段发送给每个工作人员。

这会导致您定义的 Rank 原语出现问题,因为该原语需要所有数据都存在才能获得正确答案。对于这种情况,您需要在定义原语时设置 uses_full_entity=True 以强制特征工具在调用原语函数计算特征值时包含所有数据。

如果您按如下方式更新 Rank 原语定义,您将得到正确答案:

class Rank(TransformPrimitive):
    name = 'rank'
    input_types = [Numeric]
    return_type = Numeric
    uses_full_entity = True

    def get_function(self):
        def rank(column):
            return column.rank(method="dense",ascending=True)     
        return rank

旧答案: 在您定义的自定义原始函数中,您传递给 rank 的参数与您直接在 DataFrame 上调用 rank 时使用的参数不同。

直接在 DataFrame 上调用时,您使用以下参数:

.rank(method="min", ascending=False, numeric_only=True)

在您使用不同值的自定义原始函数中:

.rank(method="dense", ascending=True) 

如果更新原始函数以使用相同的参数,从 Featuretools 获得的结果应该与直接在 DataFrame 上调用 rank 时获得的结果相匹配。