【问题标题】:How to replace every NaN in a column with different random values using pandas?如何使用熊猫用不同的随机值替换列中的每个 NaN?
【发布时间】:2018-03-14 13:26:54
【问题描述】:

我最近一直在玩熊猫,现在我尝试用不同的正态分布随机值替换数据框中的 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 可能具有不同的值。

但我想问有没有其他简单的方法可以做到这一点?

感谢您的帮助和建议。

【问题讨论】:

  • 发布的解决方案是否适合您?
  • 两种解决方案都运行良好。

标签: python pandas random normal-distribution


【解决方案1】:

这是处理底层数组数据的一种方法 -

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

本质上,我们使用 size param with np.random.normal 一次性生成所有随机数和 NaN 的计数,并再次使用 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 是的,m.sum() 基本上可以为您提供可以作为大小参数提供给np.random.normal() 的 NaN 计数,从而为我们提供一次所需的 rand 数,因此实现矢量化解决方案。
【解决方案2】:

在 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) 

【讨论】:

    【解决方案3】:

    我认为你需要:

    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
    

    【讨论】:

      猜你喜欢
      • 2022-12-03
      • 1970-01-01
      • 2018-03-16
      • 2018-08-24
      • 2019-04-24
      • 1970-01-01
      • 2016-05-18
      • 1970-01-01
      • 2021-03-22
      相关资源
      最近更新 更多