Игнорирование NaN с помощью str.contains

118

Я хочу найти строки, содержащие строку, например:

DF[DF.col.str.contains("foo")]

Однако это не удается, потому что некоторые элементы имеют NaN:

ValueError: невозможно проиндексировать вектор, содержащий значения NA / NaN

Поэтому я прибегаю к запутанному

DF[DF.col.notnull()][DF.col.dropna().str.contains("foo")]

Есть ли способ лучше?

Эмре
источник

Ответы:

228

Для этого есть флаг:

In [11]: df = pd.DataFrame([["foo1"], ["foo2"], ["bar"], [np.nan]], columns=['a'])

In [12]: df.a.str.contains("foo")
Out[12]:
0     True
1     True
2    False
3      NaN
Name: a, dtype: object

In [13]: df.a.str.contains("foo", na=False)
Out[13]:
0     True
1     True
2    False
3    False
Name: a, dtype: bool

См. str.replaceДокументы:

na: по умолчанию NaN, заполните пропущенные значения.


Итак, вы можете сделать следующее:

In [21]: df.loc[df.a.str.contains("foo", na=False)]
Out[21]:
      a
0  foo1
1  foo2
Энди Хайден
источник
2
Здесь у меня была ситуация, когда aбыло заполнено из CSV, а aстолбец содержал строку «nan». pandas«разумно» преобразовал это в NaNи начал жаловаться, когда я попытался это сделать df.a.str.contains(). Так что да совет: не забудьте установить тип столбца read_csv()или после этого сделать что-нибудь вроде df = df.where(pandas.notnull(df), "nan")LOL
dmn
Почему df.locи не только df?
PascalVKooten 02
@PascalVKooten либо в порядке, ilike .loc, так как imo он немного более явный.
Энди Хайден
1
Я спас меня ... если бы этого не было, я бы пережил двухнедельный кошмар, когда бился головой об стену :-) определенно стоит +1, смеется
U10-Нападающий
5
Лол, почему это не по умолчанию?
ifly6 02
8

В дополнение к приведенным выше ответам я бы сказал, что для столбцов, не имеющих имени из одного слова, вы можете использовать: -

df[df['Product ID'].str.contains("foo") == True]

Надеюсь это поможет.

Harry_pb
источник
0

Я не на 100% объясняю, почему (на самом деле пришел сюда, чтобы искать ответ), но это тоже работает и не требует замены всех значений nan.

import pandas as pd
import numpy as np

df = pd.DataFrame([["foo1"], ["foo2"], ["bar"], [np.nan]], columns=['a'])

newdf = df.loc[df['a'].str.contains('foo') == True]

Работает с или без .loc.

Я понятия не имею, почему это работает, поскольку я понимаю, что когда вы индексируете скобки, pandas оценивает все, что находится внутри скобок, как Trueили False. Я не могу сказать, почему фраза в скобках «лишнее логическое значение» вообще имеет какой-либо эффект.

Нейт Тейлор
источник
0

Вы также можете патерн:

DF[DF.col.str.contains(pat = '(foo)', regex = True) ]
Алиакбар Хоссейнзаде
источник
0

DF [DF.col.str.contains ("foo"). Fillna (Ложь)]

щедрый
источник
-3
import folium
import pandas

data= pandas.read_csv("maps.txt")

lat = list(data["latitude"])
lon = list(data["longitude"])

map= folium.Map(location=[31.5204, 74.3587], zoom_start=6, tiles="Mapbox Bright")

fg = folium.FeatureGroup(name="My Map")

for lt, ln in zip(lat, lon):
c1 = fg.add_child(folium.Marker(location=[lt, ln], popup="Hi i am a Country",icon=folium.Icon(color='green')))

child = fg.add_child(folium.Marker(location=[31.5204, 74.5387], popup="Welcome to Lahore", icon= folium.Icon(color='green')))

map.add_child(fg)

map.save("Lahore.html")


Traceback (most recent call last):
  File "C:\Users\Ryan\AppData\Local\Programs\Python\Python36-32\check2.py", line 14, in <module>
    c1 = fg.add_child(folium.Marker(location=[lt, ln], popup="Hi i am a Country",icon=folium.Icon(color='green')))
  File "C:\Users\Ryan\AppData\Local\Programs\Python\Python36-32\lib\site-packages\folium\map.py", line 647, in __init__
    self.location = _validate_coordinates(location)
  File "C:\Users\Ryan\AppData\Local\Programs\Python\Python36-32\lib\site-packages\folium\utilities.py", line 48, in _validate_coordinates
    'got:\n{!r}'.format(coordinates))
ValueError: Location values cannot contain NaNs, got:
[nan, nan]
Фахим Альви
источник
Это не ответ.
ifly6 02