对于数据框中的每个列和单元格,使用该列中的随机值填写NaN / Null

时间:2018-12-04 21:07:50

标签: python pandas

我试图通过从该列中随机抽样来填充数据帧中每一列和该列中每个单元格的NaN / null值(例如,采样非NaN值)。我现在正在做以下

   for col in df:
        count = 0
        while True:
            sample = df[col].sample(n=1)
            count += 1
            if pd.notna(sample.item()):
                df[col].replace(sample, np.nan, inplace=True)
                break
            if count >= 100:
                break

这是不正确的,因为:

  1. 该黑客可以尝试进行100次采样,以期最终在100次尝试中找到非NaN。

  2. 它将用样本样品填充单元格,而我想分别为每个单元格随机采样一个值,例如没有任何偏斜

  3. 无论如何由于某种原因它都不起作用,导致df像以前一样具有NaN。

注意:数据框同时包含数字和字符串

1 个答案:

答案 0 :(得分:3)

您可以使用np.random.choice从一组值中生成一个样本:

sample = np.random.choice(pop, size=len(df)-len(pop), replace=True)

例如,

import numpy as np
import pandas as pd

arr = np.random.randint(10, size=(10,3)).astype(float)
mask = np.random.randint(2, size=arr.shape, dtype=bool)
arr[mask] = np.nan
df = pd.DataFrame(arr)
print(df)
#      0    1    2
# 0  8.0  NaN  0.0
# 1  1.0  3.0  2.0
# 2  NaN  NaN  NaN
# 3  6.0  NaN  7.0
# 4  NaN  8.0  5.0
# 5  1.0  4.0  6.0
# 6  NaN  NaN  NaN
# 7  NaN  NaN  NaN
# 8  8.0  NaN  NaN
# 9  5.0  NaN  2.0

for col in df:
    mask = pd.isnull(df[col])
    pop = df[col].dropna()
    if len(pop):
        sample = np.random.choice(pop, size=len(df)-len(pop), replace=True)
        df.loc[mask, col] = sample


print(df)

产生诸如

的结果
     0    1    2
0  8.0  4.0  0.0
1  1.0  3.0  2.0
2  1.0  8.0  2.0
3  6.0  3.0  7.0
4  8.0  8.0  5.0
5  1.0  4.0  6.0
6  1.0  8.0  2.0
7  8.0  4.0  6.0
8  8.0  4.0  7.0
9  5.0  3.0  2.0

df[col]返回一个系列。不能保证修改此系列 修改df本身。因此

df[col].replace(sample, np.nan, inplace=True)

修改df[col]返回的系列,但不能修改df

通常,要确保您修改了DataFrame,请使用df.loc[...] = ...df.iloc[...] = ...或生成一个新的DataFrame并将其重新分配给df(例如df = new_df),或生成一个新的值列并将其重新分配给一个列(例如df[col] = values