2016-07-28 49 views
2

我有關於上 在熊貓DataFrame填充NaN值有條件地非NaN列的值的問題。爲了說明:灌裝NaN值在一個數據幀熊貓有條件地對非NaN的列的值

import numpy as np 
import pandas as pd 
print pd.__version__ 

0.18.1 

df = pd.DataFrame({'a': [1, 0, 0, 0, 1], 
        'b': [0, 1, 0, 0, 0], 
        'c': [0, 0, 1, 1, 0], 
        'x': [0.5, 0.2, 0, 0.2, 0], 
        'y': [0, 0, 0, 1, 0], 
        'z': [0.1, 0.1, 0.9, 0, 0.4]}) 

df.ix[[2,4], ['x','y','z']] = np.nan 

print df 

    a b c x y z 
0 1 0 0 0.5 0.0 0.1 
1 0 1 0 0.2 0.0 0.1 
2 0 0 1 NaN NaN NaN 
3 0 0 1 0.2 1.0 0.0 
4 1 0 0 NaN NaN NaN 

現在假設我有一些默認值,依賴於前三列:

default_c = pd.Series([0.5, 0.5, 0.5], index=['x', 'y', 'z']) 
default_a = pd.Series([0.2, 0.2, 0.2], index=['x', 'y', 'z']) 

換句話說,我想default_c粘貼在NaN值第2行,並在4排爲此default_a貼,我想出了下面的有些不雅的解決方案:

nan_x = np.isnan(df['x']) 
is_c = df['c']==1 
nan_c = nan_x & is_c 

print nan_c 

0 False 
1 False 
2  True 
3 False 
4 False 
dtype: bool 

df.ix[nan_c, default_c.index] = default_c.values 

print df 

    a b c x y z 
0 1 0 0 0.5 0.0 0.1 
1 0 1 0 0.2 0.0 0.1 
2 0 0 1 0.5 0.5 0.5 
3 0 0 1 0.2 1.0 0.0 
4 1 0 0 NaN NaN NaN 

有沒有更好的辦法ŧ o使用fillna()函數執行此操作嗎?

例如,下面是不行的,我猜是因爲我填補了DataFrame切片:

df.loc[df['a']==1].fillna(default_a, inplace=True) 

print df 

    a b c x y z 
0 1 0 0 0.5 0.0 0.1 
1 0 1 0 0.2 0.0 0.1 
2 0 0 1 0.5 0.5 0.5 
3 0 0 1 0.2 1.0 0.0 
4 1 0 0 NaN NaN NaN 

但這長線做:

df.loc[df['a']==1] = df.loc[df['a']==1].fillna(default_a) 

print df 

    a b c x y z 
0 1 0 0 0.5 0.0 0.1 
1 0 1 0 0.2 0.0 0.1 
2 0 0 1 0.5 0.5 0.5 
3 0 0 1 0.2 1.0 0.0 
4 1 0 0 0.2 0.2 0.2 

不管怎麼說,只是尋求如何使代碼儘可能簡單的建議。

回答

1

您可以將a, b, c列設置爲多索引並使用熊貓combine_first

首先,您需要一個默認框架。在你的設置,可以這樣:

df0 = pd.concat([default_a, default_c], axis=1).T 
df0.index = pd.Index([(1, 0, 0), (0, 0, 1)], names=list("abc")) 
df0 
Out[148]: 
     x y z 
a b c    
1 0 0 0.2 0.2 0.2 
0 0 1 0.5 0.5 0.5 

然後設置一個多指數DF1,應用combine_first,並重置索引:

df1 = df.set_index(['a', 'b', 'c']) 
>>> df1 
Out[151]: 
     x y z 
a b c    
1 0 0 0.5 0.0 0.1 
0 1 0 0.2 0.0 0.1 
    0 1 NaN NaN NaN 
    1 0.2 1.0 0.0 
1 0 0 NaN NaN NaN 

df1.combine_first(df0) 
Out[152]: 
     x y z 
a b c    
0 0 1 0.5 0.5 0.5 
    1 0.2 1.0 0.0 
    1 0 0.2 0.0 0.1 
1 0 0 0.5 0.0 0.1 
    0 0.2 0.2 0.2 

df1.combine_first(df0).reset_index() 
Out[154]: 
    a b c x y z 
0 0 0 1 0.5 0.5 0.5 
1 0 0 1 0.2 1.0 0.0 
2 0 1 0 0.2 0.0 0.1 
3 1 0 0 0.5 0.0 0.1 
4 1 0 0 0.2 0.2 0.2 

副作用是輸出的不同排序順序。爲了保持順序,我們可以使用原始索引(如果它是單調的和唯一的,否則使用額外的臨時列代替):

df2 = df.reset_index().set_index(['a', 'b', 'c']) 
>>> df2 
Out[156]: 
     index x y z 
a b c      
1 0 0  0 0.5 0.0 0.1 
0 1 0  1 0.2 0.0 0.1 
    0 1  2 NaN NaN NaN 
    1  3 0.2 1.0 0.0 
1 0 0  4 NaN NaN NaN 

df2.combine_first(df0).reset_index().set_index('index').sort_index() 
Out[160]: 
     a b c x y z 
index       
0  1 0 0 0.5 0.0 0.1 
1  0 1 0 0.2 0.0 0.1 
2  0 0 1 0.5 0.5 0.5 
3  0 0 1 0.2 1.0 0.0 
4  1 0 0 0.2 0.2 0.2 
+0

不錯!無需循環遍歷解決方案中的列。 – hobgreenson

相關問題