Как определить, содержит ли столбец Pandas определенное значение


157

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

Ответы:


183

in Серии проверяет, есть ли значение в индексе:

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
Я не хочу знать, является ли он уникальным обязательно, главным образом, я хочу знать, есть ли он там.
Майкл

25
Я думаю, 'a' in s.valuesдолжно быть быстрее для длинных серий.
DSM

4
@AndyHayden Знаете ли вы, почему 'a' in spandas предпочитает проверять индекс, а не значения ряда? В словарях они проверяют ключи, но ряды панд должны вести себя больше как список или массив, не так ли?
Лей

3
Начиная с панды 0.24.0, используя s.valuesи df.valuesочень обескуражен. Смотрите это . Кроме того, s.valuesна самом деле намного медленнее в некоторых случаях.
Qusai Alothman

1
@QusaiAlothman ни .to_numpyили .arrayдоступны на серии, так что я не совсем уверен , что альтернативы они выступают (я не читал «крайне нежелательно»). На самом деле они говорят , что .values не может возвращать Numpy массив, например , в случае категорического ... но это нормально , как inвсе равно будет работать , как и ожидалось ( на самом деле более эффективно , что это NumPy коллега массив)
Энди Hayden

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

1
Вы также можете использовать функцию 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
Да, лен (найден) - несколько лучший вариант.
Шахир Ансари

1
Этот подход работал для меня, но мне пришлось включить параметры na=Falseи regex=Falseдля моего варианта
Mabyn

1
Но string.contains выполняет поиск по подстроке. Пример: если присутствует значение с именем "head_hunter". Передача "head" в str. содержит совпадения и дает True, что неверно.
Картикеян

@ 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 занимает примерно столько же времени (должно быть, используется бинарный поиск)

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делает список о a Series, а другой я просто получаю логическое значение Seriesот обычного Series, затем проверяю, есть ли какие-либо Trues в логическом значении 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.