2017-09-23 76 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獲得相同的值。 –