numpy 如何让逻辑与运算符(&)处理NaN值取决于对方的值?

9q78igpj  于 4个月前  发布在  其他
关注(0)|答案(1)|浏览(93)

在pandas或numpy中,我需要如下内容:True & NaN == True,False & False == Fase,NaN & NaN == NaN
最有效的方法是什么?到目前为止,我必须这样做:

(a.fillna(True) & b.fillna(True)).where(~(a.isna() & b.isna()), None)

字符串
举例说明:

from itertools import product
a = pd.DataFrame((product([True, False, None], [True, False, None])))
display(a)
display((a[0].fillna(True) & a[1].fillna(True)).where(~(a[0].isna() & a[1].isna()), None))


输出是:

0   1
0   True    True
1   True    False
2   True    None
3   False   True
4   False   False
5   False   None
6   None    True
7   None    False
8   None    None

0     True
1    False
2     True
3    False
4    False
5    False
6     True
7    False
8     None
dtype: object


我有两种情况:A.大多数行有NaN和B。只有少数行有NaN我想知道什么是最好的方法,这样做,在这两种情况下分别

性能

b = a.sample(int(1e5), weights=[1,1,1,1,1,1,1,1,0.01], ignore_index=True, replace=True)
c = a.sample(int(1e5), weights=[1,1,1,1,1,1,1,1,80], ignore_index=True, replace=True)
display(b.isna().all(axis="columns").sum())
# 117 full NaN row
display(c.isna().all(axis="columns").sum())
# 90879 full NaN rows

import timeit
timeit.timeit(lambda: b.all(1).mask(b.isna().all(1)), number=100)
# 2.4s
timeit.timeit(lambda: c.all(1).mask(c.isna().all(1)), number=100)
# 1.6s
timeit.timeit(lambda: b.stack().groupby(level=0).all().reindex(b.index), number=100)
#3.3s
timeit.timeit(lambda: c.stack().groupby(level=0).all().reindex(c.index), number=100)
#0.9s


所以是的,正如预期的那样,堆栈方法,首先在计算之前删除所有的nan,因此对于大多数NaN情况来说,它更快。

9o685dep

9o685dep1#

使用mask

df.all(1).mask(df.isna().all(1))

0     True
1    False
2     True
3    False
4    False
5    False
6     True
7    False
8      NaN
dtype: object

字符串
另一种方法是使用stack

df.stack().groupby(level=0).all().reindex(df.index)

0     True
1    False
2     True
3    False
4    False
5    False
6     True
7    False
8      NaN
dtype: object

相关问题