使用scikit-learn在另一个特征的名义值组中填补特征均值。

5
我想对一个特征进行均值插补,但只计算在另一列中具有相同类别/标称值的其他示例的均值,我想知道是否可以使用scikit-learn的Imputer类来实现这一点? 这样做会使它更容易添加到管道中。
例如:使用kaggle上的泰坦尼克号数据集:source,我该如何对每个pclass的平均票价进行插补。其背后的想法是不同等级的人之间的票价差异很大。
更新:经过与一些人的讨论,我应该使用的短语是“在类内插补平均值”。
我已经研究了下面Vivek的评论,并将在有时间时构建通用的管道函数来实现我的目标 :) 我有一个很好的想法,完成后会发布答案。

1
你可以按“舱位等级”拆分数据,为它们补充“票价”,然后再次堆叠它们以生成完整的数据。 - Vivek Kumar
谢谢@VivekKumar!我会考虑将其作为我的流程的一部分来完成。 - TheJokersThief
1
您可以查看此示例以获取实现自己的类的提示,该类可在管道中使用。 - Vivek Kumar
请参见 https://datascience.stackexchange.com/q/71856/55122 - Ben Reiniger
1个回答

1
以下是一种相当简单的方法来处理我的问题,仅旨在处理事情的手段。更强大的实现可能涉及使用scikit learn中的Imputer类,这意味着它也可以执行mode、median等操作,并且更擅长处理稀疏/密集矩阵。
这是基于Vivek Kumar对原始问题的评论,建议将数据分成堆栈并以这种方式进行插补,然后重新组合它们。
import numpy as np
from sklearn.base import BaseEstimator, TransformerMixin

class WithinClassMeanImputer(BaseEstimator, TransformerMixin):
    def __init__(self, replace_col_index, class_col_index = None, missing_values=np.nan):
        self.missing_values = missing_values
        self.replace_col_index = replace_col_index
        self.y = None
        self.class_col_index = class_col_index

    def fit(self, X, y = None):
        self.y = y
        return self

    def transform(self, X):
        y = self.y
        classes = np.unique(y)
        stacks = []

        if len(X) > 1 and len(self.y) = len(X):
            if( self.class_col_index == None ):
                # If we're using the dependent variable
                for aclass in classes:
                    with_missing = X[(y == aclass) & 
                                        (X[:, self.replace_col_index] == self.missing_values)]
                    without_missing = X[(y == aclass) & 
                                            (X[:, self.replace_col_index] != self.missing_values)]

                    column = without_missing[:, self.replace_col_index]
                    # Calculate mean from examples without missing values
                    mean = np.mean(column[without_missing[:, self.replace_col_index] != self.missing_values])

                    # Broadcast mean to all missing values
                    with_missing[:, self.replace_col_index] = mean

                    stacks.append(np.concatenate((with_missing, without_missing)))
            else:
                # If we're using nominal values within a binarised feature (i.e. the classes
                # are unique values within a nominal column - e.g. sex)
                for aclass in classes:
                    with_missing = X[(X[:, self.class_col_index] == aclass) & 
                                        (X[:, self.replace_col_index] == self.missing_values)]
                    without_missing = X[(X[:, self.class_col_index] == aclass) & 
                                            (X[:, self.replace_col_index] != self.missing_values)]

                    column = without_missing[:, self.replace_col_index]
                    # Calculate mean from examples without missing values
                    mean = np.mean(column[without_missing[:, self.replace_col_index] != self.missing_values])

                    # Broadcast mean to all missing values
                    with_missing[:, self.replace_col_index] = mean
                    stacks.append(np.concatenate((with_missing, without_missing)))

            if len(stacks) > 1 :
                # Reassemble our stacks of values
                X = np.concatenate(stacks)

        return X

2
你应该在“fit”时间学习相关的统计知识,这样测试数据就不会使用自己的分布来填充。 - Ben Reiniger

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接