在工作on an answer to another question时,我偶然发现了一个意想不到的行为:
考虑以下数据帧:
df = pd.DataFrame({
'A':list('AAcdef'),
'B':[4,5,4,5,5,4],
'E':[5,3,6,9,2,4],
'F':list('BaaBbA')
})
print(df)
A B E F
0 A 4 5 B #<— row contains 'A' and 5
1 A 5 3 a #<— row contains 'A' and 5
2 c 4 6 a
3 d 5 9 B
4 e 5 2 b
5 f 4 4 A
如果我们试图找到包含['A', 5]
的所有列,我们可以使用jezrael's answer:
cond = [['A'],[5]]
print( np.logical_and.reduce([df.isin(x).any(1) for x in cond]) )
它(正确地)产生:[ True True False False False False]
如果我们使用:
cond = [['A'],[5]]
print( df.apply(lambda x: np.isin([cond],[x]).all(),axis=1) )
这将产生:
0 False
1 False
2 False
3 False
4 False
5 False
dtype: bool
仔细检查第二次尝试发现:
np.isin(['A',5],df.loc[0])
“错误地”产生array([ True, False])
,可能是由于numpy
推断出数据类型<U1
,因此5!='5'
np.isin(['A',5],['A',4,5,'B'])
“正确地”产生array([ True, True])
,这意味着我们可以(并且应该)在上述.apply()
方法中使用df.loc[0].values.tolist()
问题,简化:
为什么我在一种情况下需要指定x.values.tolist()
,而在另一种情况下可以直接使用x
?你知道吗
print( np.logical_and.reduce([df.isin(x).any(1) for x in cond]) )
print( df.apply(lambda x: np.isin([cond],x.values.tolist()).all(),axis=1 ) )
编辑:
更糟糕的是,如果我们搜索[4,5]
:
cond = [[4],[5]]
## this returns False for row 0
print( df.apply(lambda x: np.isin([cond],x.values.tolist() ).all() ,axis=1) )
## this returns True for row 0
print( df.apply(lambda x: np.isin([cond],x.values ).all() ,axis=1) )
我认为在DataFrame中是用整数来混合数值的,所以如果loop by rows用混合类型来获得
Series
,那么numpy强制到strings
。你知道吗可能的解决方案是转换为数组,然后转换为
cond
中的string
值:不幸的是,对于一般的解决方案(如果可能的话,只有数字列)需要同时转换-
cond
和Series
:或所有数据:
如果在纯python中使用set,那么它工作起来很好:
因为
pd.Series
,^{pd.Series
。你知道吗pd.Series
转换为array-like,您的x.values.tolist()
应该可以工作。你知道吗相关问题 更多 >
编程相关推荐