2013-03-13 44 views
5

我有一個數據幀:設置數據幀的非空值有條件

 0   1   2 3   4 y 
35 NaN  NaN  NaN NaN 0.342153 0 
40 NaN 0.326323  NaN NaN  NaN 0 
43 NaN  NaN 0.290126 NaN  NaN 0 
49 NaN 0.326323  NaN NaN  NaN 0 
50 NaN 0.391147  NaN NaN  NaN 1 

和代碼生成它:

import pandas as pd 
import numpy as np 

nan = np.nan 

df = pd.DataFrame(
{0L: {35: nan, 40: nan, 43: nan, 49: nan, 50: nan}, 
1L: {35: nan, 
    40: 0.32632316859446198, 
    43: nan, 
    49: 0.32632316859446198, 
    50: 0.39114724480578139}, 
2L: {35: nan, 40: nan, 43: 0.29012581014105987, 49: nan, 50: nan}, 
3L: {35: nan, 40: nan, 43: nan, 49: nan, 50: nan}, 
4L: {35: 0.34215328467153283, 40: nan, 43: nan, 49: nan, 50: nan}, 
'y': {35: 0, 40: 0, 43: 0, 49: 0, 50: 1}}) 

我需要分配一個值,使用下面的僞代碼的每一列:

column = 1 if column > threshold else 0 where column != NaN 

我一直在使用索引看中做到這一點,像這樣嘗試:

df.ix[df[1].notnull(),1] = 1; df 

    0 1   2 3   4 y 
35 NaN NaN  NaN NaN 0.342153 0 
40 NaN 1  NaN NaN  NaN 0 
43 NaN NaN 0.290126 NaN  NaN 0 
49 NaN 1  NaN NaN  NaN 0 
50 NaN 1  NaN NaN  NaN 1 

但是A)我不知道如何應用條件邏輯和B)我必須迭代地將邏輯應用到每列,而不是整個數據幀。

問:

如何申請條件邏輯的數據幀的非空值,保留其他字段的無效?

回答

5
# you need this because your y column is an int64 (otherwise this the next step 
# will throw an exception), on the to fix list in 0.11-dev though 
In [71]: df = orig_df.astype('float64') 

# use boolean indexing! 
# NaN are automatically excluded 
In [72]: df[df>0.3] = 1 ; df[df<=0.3] = 0 

In [73]: df 
Out[73]: 
    0 1   2 3 4 y 
35 NaN NaN  NaN NaN 1 0 
40 NaN 1  NaN NaN NaN 0 
43 NaN NaN   0 NaN NaN 0 
49 NaN 1  NaN NaN NaN 0 
50 NaN 1  NaN NaN NaN 1 
3

你可以使用applymap,因爲它看起來像你真的想要的元素單元的操作:

>>> df.applymap(lambda x: x if pd.isnull(x) else (1 if x > 0.3 else 0)) 
    0 1 2 3 4 y 
35 NaN NaN NaN NaN 1 0 
40 NaN 1 NaN NaN NaN 0 
43 NaN NaN 0 NaN NaN 0 
49 NaN 1 NaN NaN NaN 0 
50 NaN 1 NaN NaN NaN 1 

雖然在這種特殊情況下,我們能欺騙(兩次):

>>> (df > 0.3) * 1 + df * 0 
    0 1 2 3 4 y 
35 NaN NaN NaN NaN 1 0 
40 NaN 1 NaN NaN NaN 0 
43 NaN NaN 0 NaN NaN 0 
49 NaN 1 NaN NaN NaN 0 
50 NaN 1 NaN NaN NaN 1 
1

你在找什麼是iterrows()方法。 pandas documentation

我不是100%確定你想用僞代碼完成什麼,但是下面的代碼會修改新的系列(可以分配給數據框)。

updated = df['data'] 
for index, row in df.iterrows(): 
    if ((not pd.isnull(df[index])) and df[index] > threshold) : 
     updated[index] = 1.0 
    else: 
     updated[index] = 0.0 
df['data'] = updated 

它很可能給你一個警告SettingWithCopyWarning關於迭代器分配一樣,所以請謹慎使用。