【问题标题】:Python: How to properly deal with NaN's in a pandas DataFrame for feature selection in scikit-learnPython:如何正确处理 Pandas DataFrame 中的 NaN 以在 scikit-learn 中进行特征选择
【发布时间】:2015-05-20 12:48:16
【问题描述】:

这与我在here 发布的一个问题有关,但这个问题更具体、更简单。

我有一个 pandas DataFrame,它的索引是唯一的用户标识符,列对应于唯一的事件,值 1(已参加)、0(未参加)或 NaN(未受邀/不相关)。对于 NaN,矩阵非常稀疏:有数百个事件,大多数用户最多只被邀请到几十个。

我创建了一些额外的列来衡量“成功”,我将其定义为相对于邀请的出席率:

my_data['invited'] = my_data.count(axis=1)
my_data['attended'] = my_data.sum(axis=1)-my_data['invited']
my_data['success'] = my_data['attended']/my_data['invited']

我现在的目标是对事件/列进行特征选择,从最基本的基于方差的方法开始:删除那些低方差的。然后我会查看事件的线性回归,并只保留那些具有大系数和小 p 值的事件。

但我的问题是我有这么多 NaN,我不确定处理它们的正确方法是什么,因为大多数 scikit-learn 方法会因为它们而给我错误。一个想法是将“没有参加”替换为 -1,将“未受邀”替换为 0,但我担心这会改变活动的意义。

谁能建议在不改变每个特征/事件的统计显着性的情况下处理所有这些 NaN 的正确方法?

编辑:我想补充一点,如果有一个合理的指标可以让我继续进行特征选择,我很乐意从上面更改我的“成功”指标.我只是想确定哪些事件在捕捉用户兴趣方面是有效的。它非常开放,这主要是练习特征选择的练习。

谢谢!

【问题讨论】:

  • 恐怕没有通用的答案,删除它们可能会使您的模型表现不佳,因为它没有足够的样本数据,而将它们全部设置为 0 或 -1 可能实际上会损害其他特征。我会将性能与将它们设置为 0、-1 以及平均值进行比较。我发现将其设置为均值不会使我的模型产生偏差,我使用了随机森林,但对于某些模型,它可能会使特征权重产生偏差

标签: python pandas scikit-learn feature-selection


【解决方案1】:

如果我理解正确,您希望在不显着改变其中的统计属性的情况下从 NaN 中清除您的数据 - 这样您就可以运行一些分析后记。

实际上我最近遇到了类似的事情,您可能感兴趣的一种简单方法是使用 sklearn 的“Imputer”。正如 EdChum 前面提到的,一种想法是用轴上的平均值代替。例如,其他选项包括用中位数替换。

类似:

from sklearn.preprocessing import Imputer
imp = Imputer(missing_values='NaN', strategy='mean', axis=1)
cleaned_data = imp.fit_transform(original_data)

在这种情况下,这会将 NaN 替换为每个轴的平均值(例如,让我们按事件估算,因此轴 = 1)。然后,您可以对清理后的数据进行四舍五入,以确保您得到 0 和 1。

我会按事件为数据绘制一些直方图,以健全地检查这种预处理是否会显着改变您的分布 - 因为我们可能会通过将如此多的值交换为均值/众数/中位数来引入过多的偏差每个轴。

参考链接:http://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.Imputer.html

更进一步(假设以上还不够),您可以交替执行以下操作:

  • 在删除所有 nan 数字后,获取数据中的每个事件列并计算参加 ('p') 与不参加 ('1 - p') 的概率。 [IE。 p = 出席/(出席 + 未出席)]
  • 然后使用从伯努利分布生成的随机数替换每个事件列中的 NaN 数,我们与您估计的“p”相匹配,大致类似于:

    import numpy as np

    n = 1 # number of trials

    p = 0.25 # estimated probability of each trial (i.e. replace with what you get for attended / total)

    s = np.random.binomial(n, p, 1000)

    # s now contains random a bunch of 1's and 0's you can replace your NaN values on each column with

再次重申,这本身并不完美,您最终是否仍会稍微偏向您的数据(例如,更准确的方法是考虑每个用户在事件之间的数据依赖性) - 但通过从一个大致匹配的分布,这至少应该比用平均值等任意替换更稳健。

希望这会有所帮助!

【讨论】:

    猜你喜欢
    • 2021-02-11
    • 2014-11-05
    • 2018-02-24
    • 2019-10-22
    • 2018-06-01
    • 2021-03-26
    • 1970-01-01
    • 2014-05-22
    相关资源
    最近更新 更多