2016-07-28 14 views
2

私は、非NaN列の 値に条件付きパンダDataFrameNaN値を充填に関する質問があります。説明するために:NaN以外の列の値に条件付きパンダDATAFRAMEで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 

は今、私は最初の3つの列に依存して、いくつかのデフォルト値を、持っていると仮定します。つまり

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']) 

、私は中NaNの値についてdefault_cにペーストしたいのですがより良い方法トンがあります

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 

:行2、及びこれを行うには、行4にdefault_aペースト、私は以下のやや洗練解決策を考え出しました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

関連する問題