2017-09-23 114 views
1

我有一个DataFrame,df,包含几列。 df中的一些值是NaN。我想用一个有效值替换每个NaN,通过从给定列中的其他值随机抽样来选择。熊猫:使用列值的随机采样替换NaN

例如,如果:

df[work] = [4, 7, NaN, 4]

我想和时间4 2/3和71/3的时候更换df[work][2]

这里是我的尝试:

def resample_fillna(df): 
    for col in df.columns: 
     # get series consisting of non-NaN values 
     valid_series = df[col].dropna() 
     nan_indices = np.argwhere(np.isnan(df[col])) 
     for nan_index in nan_indices: 
      df[col][nan_index] = valid_series.sample(n=1) 

我想有一个更好的,更Python的方式。有什么想法吗?

谢谢!

+0

您是否用相同的随机值或每个不同的随机值替换所有缺失值? –

回答

2

让我们创建一些假数据,然后用同一列中的随机其他值填充缺失值。

np.random.seed(123) 
data = np.random.randint(0, 10, (10,5)) 
df = pd.DataFrame(data, columns=list('abcde')) 
df = df.where(df > 2) 
df 

    a b c d e 
0 NaN NaN 6.0 NaN 3.0 
1 9.0 6.0 NaN NaN NaN 
2 9.0 NaN NaN 9.0 3.0 
3 4.0 NaN NaN 4.0 NaN 
4 7.0 3.0 NaN 4.0 7.0 
5 NaN 4.0 8.0 NaN 7.0 
6 9.0 3.0 4.0 6.0 NaN 
7 5.0 6.0 NaN NaN 8.0 
8 3.0 5.0 NaN NaN 6.0 
9 NaN 4.0 4.0 6.0 3.0 

现在我们可以通过与apply每列和样品与来自非缺失值置换循环。

df.apply(lambda x: np.where(x.isnull(), x.dropna().sample(len(x), replace=True), x)) 

    a b c d e 
0 5.0 3.0 6.0 6.0 3.0 
1 9.0 6.0 4.0 9.0 7.0 
2 9.0 5.0 8.0 9.0 3.0 
3 4.0 3.0 8.0 4.0 6.0 
4 7.0 3.0 4.0 4.0 7.0 
5 9.0 4.0 8.0 6.0 7.0 
6 9.0 3.0 4.0 6.0 3.0 
7 5.0 6.0 4.0 4.0 8.0 
8 3.0 5.0 4.0 4.0 6.0 
9 9.0 4.0 4.0 6.0 3.0 
+0

为什么在'sample'内使用'len(x)'而不是仅仅执行'n = 1'? – bclayman

+2

@bclayman如果您抽样n = 1。这将从您的集合中拉出一个值,并将所有NaN中的一个值放置一次,而不是对每个nan的一次采样。例如,在Ted给定的设置中,如果您执行n = 1而不是n = len(x),则第一列将为所有三个NaN获得相同的值。 –