pandas оператор сравнения `==` не работает должным образом, когда столбец содержит `List` вместо` Tuple` - PullRequest
2 голосов
/ 16 апреля 2020
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: длины должны совпадать для сравнения

Ответы [ 2 ]

2 голосов
/ 16 апреля 2020

Проблема в том, что list s не является хэшируемыми, поэтому необходимо сравнить tuple s:

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]
1 голос
/ 16 апреля 2020

Проблема в том, что pandas рассматривает [1, 2] как рядоподобный объект и пытается сравнить каждый элемент df.Li с каждым элементом [1, 2], поэтому возникает ошибка:

ValueError: длины должны совпадать для сравнения

Невозможно сравнить список размера два со списком размера 3 (df.Li). Чтобы убедиться в этом, вы можете сделать следующее:

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

Вывод

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

Он не выдает никакой ошибки и работает, но возвращает 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)

Output

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

В целом это похоже на bug в сторону pandas.

...