2016-12-06 52 views
2

我正在尋找一種關於熊貓中非常大的數據框問題的解決方案。使用分組進行NAs的高效填充

比方說,我有一個非常大的數據框,其中有NAs。我想通過具有相同ID的行的平均值來填充這些NA。我知道一些ID與我無關(請參閱示例代碼中的數組「ids」)。

我想出了下面的代碼:

# relevant Ids 
ids = [2,3] 
# create example dataframe 
test = pd.DataFrame([[1,1,4],[1,np.nan,np.nan],[1,3,5],[2,np.nan,3],[2,5,5],[2,7,np.nan],[3,4,np.nan],[3,np.nan,3],[3,8,9]],columns=['id','v1','v2']) 
# fill NAs with the mean of the group defined by ID 
test[test.id.isin(ids)] = pd.concat([test[test.id.isin(ids)].id,test[test.id.isin(ids)].groupby('id').transform(lambda x: x.fillna(x.mean()))],axis=1) 

我在周圍有一個循環的環境中使用此。 在每個循環中,大約1000行將被添加到數據框,並且我必須爲這些行填充NAs。

這意味着,我可以擺脫這一點的每一點表現都會很棒。我試圖避免創建數據幀的副本,因爲這似乎更慢。

也許有人有一個想法?我認爲,例如過濾使用isin()三次應該避免,但我不能找到一個解決方案,而不復制數據框。

我不是python或pandas的專家,所以有可能是我錯過了一些東西。

+0

通常有多少列? – Divakar

+0

其實我會很滿意2列的解決方案:ID和價值例如 – hhllcks

+0

如果有多個行與NaN,我們會填入所有這些行相同的平均值? – Divakar

回答

1

這裏有一個NumPy的解決方案,通過列迭代 -

a = test.values 
ID = a[:,0].astype(int) 
for i in range(1,test.shape[1]): 
    nan_mask = np.isnan(a[:,i]) 
    ids_i = np.intersect1d(ID[~nan_mask], ids) # Account for at least 1 NaN grp 
    valid_mask = np.in1d(ID, ids_i) 
    m1 = ~nan_mask & valid_mask 
    m2 = nan_mask & valid_mask 
    s1 = np.bincount(ID[m1],a[m1,i])/np.bincount(ID[m1]) 
    test.iloc[m2,i] = s1[ID[m2],None] 
+0

該解決方案效果很好。但是:您是否知道如何解釋每個值爲南的ID?這導致我的錯誤。我想忽略這些行。 我認爲只要它不出現在m1中,就足以從數組m2中刪除ID。 – hhllcks

+0

剛剛編輯你的評論。現在它適用於我。 – hhllcks

+0

這是一個很好的解決方案還是有更好的方法? – hhllcks

1

好像你正在做很多工作。你不能只是第一次更換所有缺失值,然後篩選

test[['v1', 'v2']] = test.groupby('id').transform(lambda x: x.fillna(x.mean())) 
test[test.id.isin(ids)] 

還有一種方法無變換

test.set_index('id') \ 
    .fillna(test.groupby('id').mean()) \ 
    .loc[ids] \ 
    .reset_index()