我正在尝试摆脱数据框中的NaN值。 我不想用平均值填充NaN或进行填充,而是根据列内值的分布来填充缺失值。 换句话说,如果一列包含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
答案 0 :(得分:1)
ser = pd.Series([
1, 1, np.nan, 0, 0, 1, np.nan, 1, 1, np.nan, 0, 0, np.nan])
将value_counts
与normalize=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