Ignorar los NaN con str.contains

117

Quiero encontrar filas que contengan una cadena, así:

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

Sin embargo, esto falla porque algunos elementos son NaN:

ValueError: no se puede indexar con un vector que contiene valores NA / NaN

Entonces recurro a lo ofuscado

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

¿Existe una forma mejor?

Emre
fuente

Respuestas:

226

Hay una bandera para eso:

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

Ver los str.replacedocumentos:

na: NaN predeterminado, valor de relleno para los valores perdidos.


Entonces puedes hacer lo siguiente:

In [21]: df.loc[df.a.str.contains("foo", na=False)]
Out[21]:
      a
0  foo1
1  foo2
Andy Hayden
fuente
2
Aquí tuve una situación en la que ase completó desde un CSV, y la acolumna contenía la cadena "nan". pandas"inteligentemente" convirtió esto en NaNy comencé a quejarme cuando traté de hacerlo df.a.str.contains(). Entonces sí, protip: asegúrese de configurar el tipo de columna read_csv()o luego haga algo como df = df.where(pandas.notnull(df), "nan")LOL
dmn
¿Por qué df.locy no solo df?
PascalVKooten
@PascalVKooten está bien, como .loc ya que en mi opinión es un poco más explícito.
Andy Hayden
1
Ya me salvaste ... si esto no estuviera aquí, creo que habría pasado por una pesadilla de dos semanas golpeándome la cabeza contra la pared :-) definitivamente vale un +1, lol
U10-Forward
5
Lol, ¿por qué no es esto predeterminado?
ifly6
8

Además de las respuestas anteriores, diría que para las columnas que no tienen un nombre de una sola palabra, puede usar: -

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

Espero que esto ayude.

Harry_pb
fuente
0

No estoy al 100% de por qué (en realidad vine aquí para buscar la respuesta), pero esto también funciona y no requiere reemplazar todos los 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 con o sin .loc.

No tengo idea de por qué funciona esto, ya que lo entiendo cuando indexa con corchetes, pandas evalúa lo que esté dentro del corchete como Trueo False. No puedo decir por qué hacer que la frase entre corchetes sea 'extra booleana' tiene algún efecto.

Nate Taylor
fuente
0

También puedes patern:

DF[DF.col.str.contains(pat = '(foo)', regex = True) ]
Aliakbar Hosseinzadeh
fuente
-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
fuente
Ésta no es una respuesta.
ifly6