0

我试图摆脱数据框中的 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
4

1 回答 1

1
ser = pd.Series([
    1, 1, np.nan, 0, 0, 1, np.nan, 1, 1, np.nan, 0, 0, np.nan])

使用value_countswithnormalize=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
于 2018-12-18T12:50:59.370 回答