Ignorowanie NaNs za pomocą str.contains


117

Chcę znaleźć wiersze zawierające ciąg, na przykład:

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

Jednak to się nie udaje, ponieważ niektóre elementy są NaN:

Błąd wartości: nie można indeksować wektorem zawierającym wartości NA / NaN

Więc uciekam się do zaciemnionego

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

Czy jest lepszy sposób?

Odpowiedzi:


227

Jest na to flaga:

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

Zobacz str.replacedokumentację:

na: domyślny NaN, uzupełnij brakujące wartości.


Możesz więc wykonać następujące czynności:

In [21]: df.loc[df.a.str.contains("foo", na=False)]
Out[21]:
      a
0  foo1
1  foo2

2
Tutaj miałem sytuację, w której azostał wypełniony z pliku CSV, a akolumna zawierała ciąg „nan”. pandas„inteligentnie” przekonwertował to na NaNi zacząłem narzekać, kiedy próbowałem to zrobić df.a.str.contains(). Więc tak, protip: upewnij się, że ustawiłeś typ kolumny read_csv()lub później zrób coś takiego jak df = df.where(pandas.notnull(df), "nan")LOL
dmn

Dlaczego df.loci nie tylko df?
PascalVKooten

@PascalVKooten też jest w porządku, ilike .loc, ponieważ imo jest trochę bardziej jednoznaczne.
Andy Hayden

1
Uratowałeś mnie ... gdyby tego nie było, myślę, że przeżyłbym koszmar dwóch tygodni uderzania głową w ścianę :-) zdecydowanie warte +1, lol
U10-napastnik

5
Lol, dlaczego nie jest to domyślne?
ifly6

8

Oprócz powyższych odpowiedzi, powiedziałbym, że dla kolumn bez nazwy jednego słowa można użyć: -

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

Mam nadzieję że to pomoże.


0

Nie wiem w 100% dlaczego (w rzeczywistości przyszedłem tutaj, aby szukać odpowiedzi), ale to również działa i nie wymaga zastępowania wszystkich wartości 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]

Działa z lub bez .loc.

Nie mam pojęcia, dlaczego to działa, ponieważ rozumiem, że podczas indeksowania w nawiasach pandy ocenia to, co znajduje się w nawiasie jako albo Truealbo False. Nie potrafię powiedzieć, dlaczego ustawienie wyrażenia w nawiasach jako „extra boolean” ma jakikolwiek wpływ.




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

To nie jest odpowiedź.
ifly 6
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.