如何使用pandas将列中的每个NaN值替换为不同的随机值?

9

最近我一直在使用pandas,现在我尝试将数据框中的NaN值替换为不同的正态分布随机值。

假设我有一个没有标题的CSV文件:

      0
0    343
1    483
2    101
3    NaN
4    NaN
5    NaN

我期望的结果应该类似于这样

       0
0     343
1     483
2     101
3     randomnumber1
4     randomnumber2
5     randomnumber3

但是我得到了以下内容:
       0
0     343
1     483
2     101
3     randomnumber1
4     randomnumber1
5     randomnumber1    # all NaN filled with same number

目前为止我的代码

import numpy as np
import pandas as pd

df = pd.read_csv("testfile.csv", header=None)
mu, sigma = df.mean(), df.std()
norm_dist = np.random.normal(mu, sigma, 1)
for i in norm_dist:
    print df.fillna(i)

我想要从数据框中获取NaN行的数量,并将np.random.normal(mu, sigma, 1)中的数字1替换为NaN行的总数,这样每个NaN可能会有不同的值。

但我想问是否有其他简单的方法来完成此操作?

谢谢您的帮助和建议。


你尝试过这些解决方案中的任何一个吗? - Divakar
这两个解决方案都很好用。 - Fang
3个回答

9

这是一种使用底层数组数据的方法 -


def fillNaN_with_unifrand(df):
    a = df.values
    m = np.isnan(a) # mask of NaNs
    mu, sigma = df.mean(), df.std()
    a[m] = np.random.normal(mu, sigma, size=m.sum())
    return df

本质上,我们使用NaN的计数和np.random.normal中的size参数一次性生成所有随机数,并再次使用NaN的掩码一次性分配它们。

样例运行 -

In [435]: df
Out[435]: 
       0
0  343.0
1  483.0
2  101.0
3    NaN
4    NaN
5    NaN

In [436]: fillNaN_with_unifrand(df)
Out[436]: 
            0
0  343.000000
1  483.000000
2  101.000000
3  138.586483
4  223.454469
5  204.464514

我理解您是在向我展示,如果我想使用我的计算NaN行的方法,应该怎么做,对吗?一开始我没有想到这种方法。谢谢您的指导。 - Fang
@Fang 是的,m.sum()基本上可以得到NaN的计数,这些NaN可以作为大小参数提供给np.random.normal(),从而一次性获得所需的随机数数量,从而实现向量化解决方案。 - Divakar

4
在pandas DataFrame列中,将随机值代替缺失值非常简单。
mean = df['column'].mean()
std = df['column'].std()

def fill_missing_from_Gaussian(column_val):
    if np.isnan(column_val) == True: 
        column_val = np.random.normal(mean, std, 1)
    else:
         column_val = column_val
return column_val

现在,只需将上述方法应用于存在缺失值的列即可。
df['column'] = df['column'].apply(fill_missing_from_Gaussian) 

1

我认为你需要:

mu, sigma = df.mean(), df.std()
#get mask of NaNs
a = df[0].isnull()
#get random values by sum ot Trues, processes like 1
norm_dist = np.random.normal(mu, sigma, a.sum())
print (norm_dist)
[ 184.90581318  364.89367364  181.46335348]
#assign values by mask
df.loc[a, 0] = norm_dist
print (df)

            0
0  343.000000
1  483.000000
2  101.000000
3  184.905813
4  364.893674
5  181.463353

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