函数无法解释 nan 值

Posted

技术标签:

【中文标题】函数无法解释 nan 值【英文标题】:Fuction can not interpret nan value 【发布时间】:2019-05-18 21:06:45 【问题描述】:

我正在尝试摆脱数据框中的 NaN 值。 我不想用平均值填充 NaN 或进行 ffill,而是想根据列内值的分布来填充缺失值。 换句话说,如果一列有 120 行,20 行是 NaN,80 包含 1.0,20 包含 0,0,我想用 1 填充 80% 的 NaN 值。请注意,该列包含浮点数。

我为此做了一个函数:

def fill_cr_hist(x):
    if x is pd.np.nan:
        r = random.random()
        if r > 0.80:
            return 0.0
        else:
            return 1.0
    else:
        return x

但是,当我调用该函数时,它不会更改 NaN 值。

df['Credit_History'] = df['Credit_History'].apply(fill_cr_hist)

我用 pd.np.nan 填充 NaN 值,但它没有改变任何东西。

df['Credit_History'].fillna(value=pd.np.nan, inplace=True)
df['Credit_History'] = df['Credit_History'].apply(fill_cr_hist)

我编写的另一个函数几乎相同并且工作正常。在这种情况下,该列包含字符串。

def fill_self_emp(x):
    if x is pd.np.nan:
        r = random.random()
        if r > 0.892442:
            return 'Yes'
        else:
            return 'No'
    else:
        return x

【问题讨论】:

您希望通过从列的分布中绘制而不是使用某个点估计值(如均值、中位数或众数)来填充缺失值的目标是什么?这通常是一个类似于"probability matching." 的认知谬误的错误,但是,这会导致比仅使用条件均值更高的均方误差,或者与 L1 损失和中位数类似。如果您正在寻找一种“错误最少”的数据插补方法,则不应镜像分布,而只需选择特定的点估计。 否则,您应该正确地创建一个缺失数据模型,并在给定非缺失数据和有关数据缺失机制的一些领域知识的情况下实际建模缺失数据的后验分布。然后,您可以通过一些基于 MCMC 的对缺失数据样本的平均来“平均化”缺失数据对任何其他计算的影响。这听起来很花哨,但实际上计算起来通常非常简单且便宜。但问题是,您要么处于一个简单的点估计就足够的情况(大部分时间),要么处于需要完整 MCMC 的情况。 (另一种说法是,从非缺失值所隐含的分布中进行绘制并不是绘制缺失值的可接受方式,除非在点估计为比非缺失分布更准确的估算值。) 【参考方案1】:
ser = pd.Series([
    1, 1, np.nan, 0, 0, 1, np.nan, 1, 1, np.nan, 0, 0, np.nan])

使用value_countsnormalize=True 来获取与您的值相对应的概率列表。然后根据给定的概率分布随机生成值,用fillna填充NaN。

p = ser.value_counts(normalize=True).sort_index().tolist()   
u = np.sort(ser.dropna().unique())
ser = ser.fillna(pd.Series(np.random.choice(u, len(ser), p=p)))

此解决方案适用于任何个数字/分类值,而不仅仅是 0 和 1。如果数据是字符串类型,则使用pd.factorize并转换为数字。


详情

首先,计算概率分布:

ser.value_counts(normalize=True).sort_index()

0.0    0.444444
1.0    0.555556
dtype: float64

获取唯一值的列表,以相同的方式排序:

np.sort(ser.dropna().unique())
array([0., 1.])

最后,生成具有指定概率分布的随机值。

pd.Series(np.random.choice(u, len(ser), p=p))

0     0.0
1     0.0
2     1.0
3     0.0
4     0.0
5     0.0
6     1.0
7     1.0
8     0.0
9     0.0
10    1.0
11    0.0
12    1.0
dtype: float64

【讨论】:

以上是关于函数无法解释 nan 值的主要内容,如果未能解决你的问题,请参考以下文章

无法从数据集中删除 NaN 值

Double 值无法转换为 Int64,因为它要么是无限的要么是 NaN

无法在pandas中通过lambda填充多列中的NaN值

Swift 3:致命错误:Double 值无法转换为 Int,因为它是无限的或 NaN

收到致命错误:双精度值无法转换为 Int,因为它是无限的或 NaN

检查 NaN 数据值 (C/C++/Python 实现)