基于多个条件的新列,忽略缺失值

时间:2018-08-06 00:51:00

标签: python pandas numpy

我有一些缺少某些值的数据框:

       A     B
0  63.0   9.0
1   NaN  35.0
2  51.0  95.0
3  25.0  11.0
4  91.0   NaN
5   2.0  47.0
6  37.0  10.0
7   NaN  88.0
8  75.0  87.0
9  92.0  21.0

我想根据以上两列的条件创建一个新列:

df['C'] = numpy.where((df['A']>55) | (df['B']>55), "Yes", "No")

这可行,但未考虑缺失值:

      A     B    C
0  63.0   9.0  Yes
1   NaN  35.0   No
2  51.0  95.0  Yes
3  25.0  11.0   No
4  91.0   NaN  Yes
5   2.0  47.0   No
6  37.0  10.0   No
7   NaN  88.0  Yes
8  75.0  87.0  Yes
9  92.0  21.0  Yes

要纠正缺失值,我必须运行以下代码:

df['C'] = numpy.where((df['A'].isnull()) | (df['B'].isnull()), numpy.nan, df['C'])

然后我将获得适当的新列:

      A     B    C
0  63.0   9.0  Yes
1   NaN  35.0  NaN
2  51.0  95.0  Yes
3  25.0  11.0   No
4  91.0   NaN  NaN
5   2.0  47.0   No
6  37.0  10.0   No
7   NaN  88.0  NaN
8  75.0  87.0  Yes
9  92.0  21.0  Yes

有没有更好的方法,以便我仅可以纠正单行代码中的缺失值?

4 个答案:

答案 0 :(得分:4)

使用 np.select 。条件 的顺序在这里很重要,因为np.select选择了第一个有效选项,因此您必须先进行空检查。

c1 = df.isnull().any(1)
c2 = df.gt(55).any(1)

df['C'] = np.select([c1, c2], [np.nan, 'Yes'], 'No')

      A     B    C
0  63.0   9.0  Yes
1   NaN  35.0  nan
2  51.0  95.0  Yes
3  25.0  11.0   No
4  91.0   NaN  nan
5   2.0  47.0   No
6  37.0  10.0   No
7   NaN  88.0  nan
8  75.0  87.0  Yes
9  92.0  21.0  Yes

答案 1 :(得分:3)

根据要执行多少列操作,这会变得有些复杂。

这是mapmask的替代选择:

(df[['A', 'B']]
   .gt(55)
   .any(1)
   .map(lambda x: 'Yes' if x else 'No')  # .map({True : 'Yes', False : 'No'}.__getitem__)
   .mask(df[['A', 'B']].isna().any(1))
) 

0    Yes
1    NaN
2    Yes
3     No
4    NaN
5     No
6     No
7    NaN
8    Yes
9    Yes
dtype: object

这仍然是一条语句,为了便于阅读,它分为多行。

答案 2 :(得分:3)

束缚两个anymap

(df>55).any(1).mask((df.isnull()).any(1),np.nan).map({1:'Yes',0:'No'})
Out[405]: 
0    Yes
1    NaN
2    Yes
3     No
4    NaN
5     No
6     No
7    NaN
8    Yes
9    Yes
dtype: object

或使用两个np.where

a=(df>55).any(1)
b=df.isnull().any(1)
np.where(b,np.nan,np.where(a,'Yes','No'))
Out[407]: 
array(['Yes', 'nan', 'Yes', 'No', 'nan', 'No', 'No', 'nan', 'Yes', 'Yes'],
      dtype='<U32')

答案 3 :(得分:2)

IMO,如果我们想忽略NaN行,我们就删除它们。分配将与索引对齐,从而导致缺少索引的NaN。

In [317]: df["C"] = (df[["A","B"]].dropna() > 55).any(axis=1).replace(
                    {False: "No", True: "Yes"})

In [318]: df
Out[318]: 
      A     B    C
0  63.0   9.0  Yes
1   NaN  35.0  NaN
2  51.0  95.0  Yes
3  25.0  11.0   No
4  91.0   NaN  NaN
5   2.0  47.0   No
6  37.0  10.0   No
7   NaN  88.0  NaN
8  75.0  87.0  Yes
9  92.0  21.0  Yes