Ignorando NaNs com str.contains

117

Quero encontrar linhas que contenham uma string, assim:

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

No entanto, isso falha porque alguns elementos são NaN:

ValueError: não é possível indexar com vetor contendo valores NA / NaN

Então eu recorro ao ofuscado

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

Existe uma maneira melhor?

Emre
fonte

Respostas:

226

Existe uma bandeira para isso:

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

Veja a str.replacedocumentação:

na: NaN padrão, valor de preenchimento para valores ausentes.


Portanto, você pode fazer o seguinte:

In [21]: df.loc[df.a.str.contains("foo", na=False)]
Out[21]:
      a
0  foo1
1  foo2
Andy Hayden
fonte
2
Aqui eu tive uma situação em que afoi preenchido a partir de um CSV, e a acoluna continha a string "nan". pandas"inteligentemente" converti isso para NaNe comecei a reclamar quando tentei fazer df.a.str.contains(). Então, sim, protop: certifique-se de definir o tipo de coluna em read_csv()ou depois faça algo como df = df.where(pandas.notnull(df), "nan")LOL
dmn
Por que df.loce não apenas df?
PascalVKooten
@PascalVKooten também é bom, ilike .loc, já que é um pouco mais explícito.
Andy Hayden,
1
Você me salvou ... se isso não fosse aqui, eu acho que teria passado por um pesadelo de duas semanas batendo minha cabeça na parede :-) definitivamente vale a pena +1, lol
U10-Forward
5
Lol por que isso não é padrão?
ifly6
8

Além das respostas acima, eu diria que, para colunas sem um único nome de palavra, você pode usar: -

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

Espero que isto ajude.

Harry_pb
fonte
0

Não estou 100% esclarecido por que (na verdade, vim aqui para pesquisar a resposta), mas isso também funciona e não requer a substituição de todos os valores 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]

Funciona com ou sem .loc.

Não tenho ideia de por que isso funciona, pois entendo que, quando você indexa com colchetes, o pandas avalia o que quer que esteja dentro do colchete como Trueou False. Eu não posso dizer por que tornar a frase dentro dos colchetes 'booleano extra' tem algum efeito.

Nate Taylor
fonte
0

Você também pode padronizar:

DF[DF.col.str.contains(pat = '(foo)', regex = True) ]
Aliakbar Hosseinzadeh
fonte
-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]
Faheem Alvi
fonte
Isso não é uma resposta.
ifly6