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?

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

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.


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.



-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]

Ce n'est pas une réponse.
ifly6
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.