Ignorer les NaN avec str.contains

117

Je veux trouver des lignes qui contiennent une chaîne, comme ceci:

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

Cependant, cela échoue car certains éléments sont NaN:

ValueError: impossible d'indexer avec un vecteur contenant des valeurs NA / NaN

Alors je recourt à l'obscurcissement

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

Y a-t-il un meilleur moyen?

Emre
la source

Réponses:

226

Il y a un drapeau pour ça:

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

Voir la str.replacedocumentation:

na: NaN par défaut, remplissez la valeur pour les valeurs manquantes.


Vous pouvez donc faire ce qui suit:

In [21]: df.loc[df.a.str.contains("foo", na=False)]
Out[21]:
      a
0  foo1
1  foo2
Andy Hayden
la source
2
Ici, j'ai eu une situation où aétait rempli à partir d'un CSV, et la acolonne contenait la chaîne "nan". pandas"intelligemment" converti cela en NaNet commencé à me plaindre quand j'ai essayé de le faire df.a.str.contains(). Alors oui protip: assurez-vous de définir le type de colonne read_csv()ou ensuite faites quelque chose comme df = df.where(pandas.notnull(df), "nan")LOL
dmn
Pourquoi df.locet pas juste df?
PascalVKooten
@PascalVKooten non plus, c'est bien, ilike .loc puisque imo c'est un peu plus explicite.
Andy Hayden
1
Tu m'as sauvé ... si ce n'était pas là, je pense que j'aurais vécu un cauchemar de deux semaines en me cognant la tête contre le mur :-) vaut vraiment un +1, lol
U10-Forward
5
Lol pourquoi n'est-ce pas par défaut?
ifly6
8

En plus des réponses ci-dessus, je dirais que pour les colonnes n'ayant pas de nom de mot unique, vous pouvez utiliser: -

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

J'espère que cela t'aides.

Harry_pb
la source
0

Je ne suis pas à 100% sur le pourquoi (en fait je suis venu ici pour chercher la réponse), mais cela fonctionne également et ne nécessite pas de remplacer toutes les valeurs 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]

Fonctionne avec ou sans .loc.

Je n'ai aucune idée de pourquoi cela fonctionne, si je comprends bien lorsque vous indexez avec des crochets, pandas évalue tout ce qui se trouve à l'intérieur du crochet comme étant soit Trueou False. Je ne peux pas dire pourquoi faire de la phrase entre crochets «extra booléen» a un effet quelconque.

Nate Taylor
la source
0

Vous pouvez également paterner:

DF[DF.col.str.contains(pat = '(foo)', regex = True) ]
Aliakbar Hosseinzadeh
la source
-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
la source
Ce n'est pas une réponse.
ifly6