2016-07-28 4 views
2

나는 에 조건부로 팬더 DataFrame에 비 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']) 

을 말해을, 나는 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 

가 더 나은 방법 (t)가 있습니까 : 행 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을 사용할 수 있습니다.

먼저 기본값 프레임이 필요합니다. 귀하가 될 수 설정에서 :

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 

부작용 출력 다른 정렬 순서이다

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을 적용하고, 인덱스를 다시 다중 색인 세트. 순서를 유지하기 위해 원본 색인을 사용할 수 있습니다 (단조롭고 독특한 경우 다른 임시 열을 대신 사용하십시오).

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

Nice! 내 솔루션에서 열을 반복 할 필요가 없습니다. – hobgreenson