Як визначити, чи містить стовпчик Pandas певне значення


156

Я намагаюся визначити, чи є запис у стовпці Pandas, який має певне значення. Я намагався це зробити if x in df['id']. Я думав, що це працює, за винятком випадків, коли я вводив його значення, яке я знав, що він не знаходиться в стовпці, до якого 43 in df['id']він все одно повертається True. Коли я підмножиться у кадр даних, що містить лише записи, що відповідають відсутньому ідентифікатору df[df['id'] == 43], очевидно, в ньому немає записів. Як визначити, чи стовпець у кадрі даних Pandas містить певне значення, і чому мій поточний метод не працює? (FYI, у мене така ж проблема, коли я використовую реалізацію в цій відповіді на подібне запитання).

Відповіді:


183

in серії Series перевіряє, чи є значення в індексі:

In [11]: s = pd.Series(list('abc'))

In [12]: s
Out[12]: 
0    a
1    b
2    c
dtype: object

In [13]: 1 in s
Out[13]: True

In [14]: 'a' in s
Out[14]: False

Один із варіантів полягає в тому, щоб побачити, чи він в унікальних значеннях:

In [21]: s.unique()
Out[21]: array(['a', 'b', 'c'], dtype=object)

In [22]: 'a' in s.unique()
Out[22]: True

або набір пітона:

In [23]: set(s)
Out[23]: {'a', 'b', 'c'}

In [24]: 'a' in set(s)
Out[24]: True

Як зазначає @DSM, може бути більш ефективним (особливо, якщо ви це робите лише для одного значення), просто використовувати безпосередньо ці значення:

In [31]: s.values
Out[31]: array(['a', 'b', 'c'], dtype=object)

In [32]: 'a' in s.values
Out[32]: True

2
Я не хочу знати, чи обов'язково він унікальний, головним чином, я хочу знати, чи він є.
Майкл

24
Я думаю, що 'a' in s.valuesдовгі серії повинні бути швидшими.
DSM

4
@AndyHayden Чи знаєте ви, чому, 'a' in sпанда, вибирає, щоб перевірити індекс, а не значення ряду? У словниках вони перевіряють ключі, але серія панд повинна поводитись більше як список чи масив, ні?
Лей

3
Починаючи з панд 0,24,0, використовуючи s.valuesта df.valuesсильно видаляючись. Дивіться це . Крім того, s.valuesнасправді набагато повільніше в деяких випадках.
Qusai Alothman

1
@QusaiAlothman ні .to_numpyабо .arrayне доступні на серіях, тому я не зовсім впевнений, яку альтернативу вони пропагують (я не читаю "сильно обескуражений"). Насправді вони говорять, що .values ​​може не повернути нумерований масив, наприклад, у випадку категоричного ... але це добре, як inі раніше працюватиме як очікувалося (дійсно ефективніше, що це колега з нумерованого масиву)
Енді Хейден

27

Ви також можете використовувати pandas.Series.isin, хоча він трохи довший, ніж 'a' in s.values:

In [2]: s = pd.Series(list('abc'))

In [3]: s
Out[3]: 
0    a
1    b
2    c
dtype: object

In [3]: s.isin(['a'])
Out[3]: 
0    True
1    False
2    False
dtype: bool

In [4]: s[s.isin(['a'])].empty
Out[4]: False

In [5]: s[s.isin(['z'])].empty
Out[5]: True

Але такий підхід може бути більш гнучким, якщо для DataFrame потрібно зіставити відразу декілька значень (див. DataFrame.isin )

>>> df = DataFrame({'A': [1, 2, 3], 'B': [1, 4, 7]})
>>> df.isin({'A': [1, 3], 'B': [4, 7, 12]})
       A      B
0   True  False  # Note that B didn't match 1 here.
1  False   True
2   True   True

Ви можете також використовувати DataFrame.any () функції:s.isin(['a']).any()
thando

17
found = df[df['Column'].str.contains('Text_to_search')]
print(found.count())

found.count()волі містить кількість збігів

А якщо це 0, значить рядок не знайдено у стовпці.


2
працював на мене, але я використав len (знайдений), щоб отримати рахунок
kztd

1
Так, len (знайдено) - дещо кращий варіант.
Шахір Ансарі

1
Цей підхід спрацював для мене, але мені довелося включити параметри na=Falseта regex=Falseдля мого випадку використання, як пояснено тут: pandas.pydata.org/pandas-docs/stable/reference/api/…
Mabyn

1
Але string.contains здійснює пошук підрядків. Наприклад: Якщо є значення під назвою "head_hunter". Передача "голови" в str. містить матчі і дає True, що неправильно.
karthikeyan

@karthikeyan Це не помиляється. Залежить від контексту вашого пошуку. Що робити, якщо ви шукаєте адреси чи товар. Вам знадобиться весь продукт, який відповідає опису.
Шахір Ансарі

6

Я зробив кілька простих тестів:

In [10]: x = pd.Series(range(1000000))

In [13]: timeit 999999 in x.values
567 µs ± 25.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [15]: timeit x.isin([999999]).any()
9.54 ms ± 291 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [16]: timeit (x == 999999).any()
6.86 ms ± 107 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [17]: timeit 999999 in set(x)
79.8 ms ± 1.98 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [21]: timeit x.eq(999999).any()
7.03 ms ± 33.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [22]: timeit x.eq(9).any()
7.04 ms ± 60 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [24]: timeit 9 in x.values
666 µs ± 15.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Цікаво, що це не має значення, якщо ви шукаєте 9 або 999999, здається, що це займає приблизно стільки ж часу, використовуючи синтаксис (потрібно використовувати двійковий пошук)

In [24]: timeit 9 in x.values
666 µs ± 15.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [25]: timeit 9999 in x.values
647 µs ± 5.21 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [26]: timeit 999999 in x.values
642 µs ± 2.11 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [27]: timeit 99199 in x.values
644 µs ± 5.31 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [28]: timeit 1 in x.values
667 µs ± 20.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Здається, використання x.values ​​є найшвидшим, але, можливо, є більш елегантний спосіб у пандах?


Було б чудово, якби ви змінили порядок результатів від найменшого до найбільшого. Хороша робота!
smm

4

Або використовувати Series.tolistабо Series.any:

>>> s = pd.Series(list('abc'))
>>> s
0    a
1    b
2    c
dtype: object
>>> 'a' in s.tolist()
True
>>> (s=='a').any()
True

Series.tolistскладає список про Series, а інший я просто отримую булеве значення Seriesвід звичайного Series, а потім перевіряє, чи є Trueбулеві s Series.



1

Використовуйте

df[df['id']==x].index.tolist()

Якщо xвін присутній, idто він поверне список індексів там, де він присутній, інакше він видасть порожній список.



0

Припустимо, такий кадр даних виглядає так:

введіть тут опис зображення

Тепер ви хочете перевірити, чи є ім'я файлу "80900026941984" у фреймі даних чи ні.

Ви можете просто написати:

if sum(df["filename"].astype("str").str.contains("80900026941984")) > 0:
    print("found")
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.