pandas 当列包含“List”而不是“Tuple”时,比较运算符“==”无法按预期工作

pandas comparision operator `==` not working as expected when column contain `List` instead `Tuple`

import pandas as pd
import numpy as np

df = pd.DataFrame({'Li':[[1,2],[5,6],[8,9]],'Tu':[(1,2),(5,6),(8,9)]}
df
       Li      Tu
0  [1, 2]  (1, 2)
1  [5, 6]  (5, 6)
2  [8, 9]  (8, 9)

Tuple

工作正常
df.Tu == (1,2)
0     True
1    False
2    False
Name: Tu, dtype: bool

当它 List 时给出值错误

df.Li == [1,2]

ValueError: Lengths must match to compare

问题是 lists 不可散列,所以有必要比较 tuples:

print (df.Li.map(tuple) == (1,2))
0     True
1    False
2    False
Name: Li, dtype: bool

或者在列表理解中:

mask = [tuple(x) == (1,2) for x in df.Li]
#alternative
mask = [x == [1,2] for x in df.Li]
print (mask)
[True, False, False]

如果所有列表的长度都相同:

mask = (np.array(df.Li.tolist()) == [1,2]).all(axis=1)
print (mask)
[ True False False]

问题是 pandas 正在将 [1, 2] 视为 类系列 对象,并试图将 df.Li 的每个元素与[1, 2] 的每个元素,因此错误:

ValueError: Lengths must match to compare

您不能将大小为 2 的列表与大小为 3 的列表进行比较 (df.Li)。为了验证这一点,您可以执行以下操作:

print(df.Li == [1, 2, 3])

输出

0    False
1    False
2    False
Name: Li, dtype: bool

它不会抛出任何错误并且可以正常工作,但是 returns False 对所有的都如预期的那样。为了使用列表进行比较,您可以执行以下操作:

# this creates an array where each element is [1, 2]
data = np.empty(3, dtype=np.object)
data[:] = [[1, 2] for _ in range(3)]

print(df.Li == data)

输出

0     True
1    False
2    False
Name: Li, dtype: bool

总而言之,这似乎是 pandas 方面的 bug

我的专栏 'vectors' 包含 numpy ndarray,当我想与另一个 ndarray 'centroid' 进行比较时,我遇到了同样的错误。以下适用于 numpy ndarrays:

df['vectors'].apply(lambda x: ((vec==centroid).sum() == centroid.shape[0]))

这也适用于列表:

df.Li.apply(lambda x: x==[1,2])