2017-03-28 37 views
2

我需要在組內的數據框的列中轉發填充值。我應該注意到,一個羣體的第一個價值永遠不會被建築遺失。目前我有以下解決方案。在熊貓數據框列中向前填充缺失值的高效解決方案?

df = pd.DataFrame({'a': [1,1,2,2,2], 'b': [1, np.nan, 2, np.nan, np.nan]}) 

# desired output 
a b 
1 1 
1 1 
2 2 
2 2 
2 2 

以下是我迄今嘗試的三種解決方案。

# really slow solutions 
df['b'] = df.groupby('a')['b'].transform(lambda x: x.fillna(method='ffill')) 
df['b'] = df.groupby('a')['b'].fillna(method='ffill') 

# much faster solution, but more memory intensive and ugly all around 
tmp = df.drop_duplicates('a', keep='first') 
df.drop('b', inplace=True, axis=1) 
df = df.merge(tmp, on='a') 

所有這三個產生期望我的輸出,但前兩個需要很長一段時間我的數據集,而第三個方案是更多的內存密集型的,感覺非常笨拙。有沒有其他方法可以轉發填充列?

+1

按組分類的真實數據,作爲示例數據是什麼?如果是這樣的話,你應該可以僅僅定義一個'ffill',因爲你的組中的第一個值總是存在的,即'df ['b'] = df ['b'] .ffill()'。 – root

+0

哇。我完全錯過了。分類後,它閃電般快。謝謝@root! – 3novak

回答

1

您需要按df.sort_values(['a', 'b']).ffill()這兩列進行排序以確保健壯性。如果np.nan留在組中的第一個位置,則ffill將使用前一組中的值填充該值。由於np.nan將放置在任何類別的末尾,因此按ab進行排序可確保您在任何組的前面都不會有np.nan。然後您可以使用初始索引.loc.reindex取回原始訂單。

這顯然比其他建議慢一點......但是,我認爲這將是正確其中其他人不是。

演示

考慮數據框df

df = pd.DataFrame({'a': [1,1,2,2,2], 'b': [1, np.nan, np.nan, 2, np.nan]}) 

print(df) 

    a b 
0 1 1.0 
1 1 NaN 
2 2 NaN 
3 2 2.0 
4 2 NaN 

嘗試

df.sort_values('a').ffill() 

    a b 
0 1 1.0 
1 1 1.0 
2 2 1.0 # <--- this is incorrect 
3 2 2.0 
4 2 2.0 

而是做

df.sort_values(['a', 'b']).ffill().loc[df.index] 

    a b 
0 1 1.0 
1 1 1.0 
2 2 2.0 
3 2 2.0 
4 2 2.0 

特別注意
這仍是不正確,如果整個集團缺失值

1

這個怎麼

df.groupby('a').b.transform('ffill') 
2

使用ffill()直接將提供最好的結果。這裏是比較

%timeit df.b.ffill(inplace = True) 
best of 3: 311 µs per loop 

%timeit df['b'] = df.groupby('a')['b'].transform(lambda x: x.fillna(method='ffill')) 
best of 3: 2.34 ms per loop 

%timeit df['b'] = df.groupby('a')['b'].fillna(method='ffill') 
best of 3: 4.41 ms per loop 
相關問題