2017-04-13 51 views
6

如何根據條件將列分成兩個不同的列,但保持一個密鑰?例如在正值和負值上分割一列

 col1 col2 time  value 
0  A  sdf 16:00:00  100 
1  B  sdh 17:00:00  -40 
2  A  sf 18:00:45  300 
3  D  sfd 20:04:33  -89 

我想這樣

 time  main_val sub_val 
0 16:00:00  100   NaN 
1 17:00:00  NaN   -40 
2 18:00:45  300   NaN 
3 20:04:33  NaN   -89 

回答

6

一個新的數據框,您可以使用mask

mask = df['value'] < 0 
df['main_val'] = df['value'].mask(mask) 
df['sub_val'] = df['value'].mask(~mask) 
df = df.drop(['col1','col2', 'value'], axis=1) 
print (df) 
     time main_val sub_val 
0 16:00:00  100.0  NaN 
1 17:00:00  NaN -40.0 
2 18:00:45  300.0  NaN 
3 20:04:33  NaN -89.0 
+0

@MaxU - 謝謝你。 – jezrael

4

我用pd.get_dummiesmaskmul

n = {True: 'main_val', False: 'sub_val'} 
m = pd.get_dummies(df.value > 0).rename(columns=n) 
df.drop('value', 1).join(m.mask(m == 0).mul(df.value, 0)) 

    col1 col2  time sub_val main_val 
0 A sdf 16:00:00  NaN  100.0 
1 B sdh 17:00:00 -40.0  NaN 
2 A sf 18:00:45  NaN  300.0 
3 D sfd 20:04:33 -89.0  NaN 

如果你看看m.mask(m == 0),它會變得更清楚它是如何工作的。

sub_val main_val 
0  NaN  1.0 
1  1.0  NaN 
2  NaN  1.0 
3  1.0  NaN 

pd.get_dummies給了我們一個零和一個。然後我把所有的零分成np.nan。當我與mul相乘時,df.value列將在這兩列中得到廣播,並且我們得到了我們的結果。我使用join將其附加回數據幀。


我們可以提高速度與numpy

v = df.value.values[:, None] 
m = v > 0 
n = np.where(np.hstack([m, ~m]), v, np.nan) 
c = ['main_val', 'sub_val'] 
df.drop('value', 1).join(pd.DataFrame(n, df.index, c)) 

    sub_val main_val 
0  NaN  1.0 
1  1.0  NaN 
2  NaN  1.0 
3  1.0  NaN 
1

這甚至可以完成通過透視表

df['Val1'] = np.where(df.value >=0,'main_val','sub_val') 

df = pd.pivot_table(df,index='time', values='value', 
       columns=['Val1'], aggfunc=np.sum).reset_index() 

df = pd.DataFrame(df.values) 
df.columns = ['time','main_val','sub_val']