Wie kann man in Pandas testen, ob eine Zeichenfolge eine der Teilzeichenfolgen in einer Liste enthält?

Lesezeit: 3 Minuten

Benutzer-Avatar
Ari

Gibt es eine Funktion, die einer Kombination von entspricht df.isin() und df[col].str.contains()?

Angenommen, ich habe die Serie
s = pd.Series(['cat','hat','dog','fog','pet'])und ich möchte alle Orte finden, an denen s enthält eines von ['og', 'at']ich würde alles außer ‘Haustier’ haben wollen.

Ich habe eine Lösung, aber es ist ziemlich unelegant:

searchfor = ['og', 'at']
found = [s.str.contains(x) for x in searchfor]
result = pd.DataFrame[found]
result.any()

Gibt es einen besseren Weg, dies zu tun?

  • Notiz: Es gibt eine von @unutbu beschriebene Lösung, die effizienter ist als die Verwendung pd.Series.str.contains. Wenn die Leistung ein Problem darstellt, kann es sich lohnen, dies zu untersuchen.

    – jpp

    6. Mai 2018 um 22:09 Uhr

  • Es wird dringend empfohlen, diese Antwort für die Suche nach Teilzeichenfolgen mit mehreren Schlüsselwörtern/Regexes zu überprüfen (scrollen Sie nach unten zum “Suche nach mehreren Teilzeichenfolgen„Untertitel).

    – cs95

    7. April 2019 um 21:04 Uhr


Benutzer-Avatar
Alex Riley

Eine Möglichkeit besteht darin, nur die Regex zu verwenden | Zeichen, um zu versuchen, jede der Teilzeichenfolgen in den Wörtern in Ihrer Serie zu finden s (nutze es noch str.contains).

Sie können die Regex konstruieren, indem Sie die Wörter verbinden searchfor mit |:

>>> searchfor = ['og', 'at']
>>> s[s.str.contains('|'.join(searchfor))]
0    cat
1    hat
2    dog
3    fog
dtype: object

Wie @AndyHayden in den Kommentaren unten angemerkt hat, achten Sie darauf, ob Ihre Teilzeichenfolgen Sonderzeichen wie z $ und ^ die Sie buchstäblich zusammenbringen möchten. Diese Zeichen haben im Zusammenhang mit regulären Ausdrücken spezifische Bedeutungen und wirken sich auf den Abgleich aus.

Sie können Ihre Liste von Teilstrings sicherer machen, indem Sie nicht-alphanumerische Zeichen mit maskieren re.escape:

>>> import re
>>> matches = ['$money', 'x^y']
>>> safe_matches = [re.escape(m) for m in matches]
>>> safe_matches
['\\$money', 'x\\^y']

Die Zeichenfolgen mit in dieser neuen Liste stimmen mit jedem Zeichen buchstäblich überein, wenn sie mit verwendet werden str.contains.

  • Vielleicht gut, diesen Link hinzuzufügen pandas.pydata.org/pandas-docs/stable/… zu. Ab Pandas 0.15 sind die String-Operationen noch einfacher

    – Gutd

    26. Oktober 2014 um 21:19 Uhr

  • Eine Sache, auf die Sie achten müssen, ist, ob eine Zeichenfolge in searchfor spezielle Regex-Zeichen enthält (Sie können mit re.escape abbilden).

    – Andy Hayden

    26. Oktober 2014 um 21:24 Uhr

  • Ich weiß nicht, warum Ihre Methode nicht mit “str.startswith(‘|’.join(searchfor))” funktioniert.

    – Doo-Hyun-Shin

    17. Februar 2019 um 12:59 Uhr

  • In diesem Fall verstehe ich, dass wir “|” verwenden. für OR, wie könnten wir AND verwenden?

    – Der Dan

    11. Februar 2021 um 23:31 Uhr

Sie können verwenden str.contains allein mit einem Regex-Muster mit OR (|):

s[s.str.contains('og|at')]

Oder Sie könnten die Serie zu a hinzufügen dataframe dann benutze str.contains:

df = pd.DataFrame(s)
df[s.str.contains('og|at')] 

Ausgabe:

0 cat
1 hat
2 dog
3 fog 

  • wie macht man das für AND?

    – JacoSolari

    25. März 2020 um 17:07 Uhr

  • @JacoSolari sehen Sie sich diese Antwort an stackoverflow.com/questions/37011734/…

    – James

    26. März 2020 um 10:08 Uhr

  • @James ja danke. Zum Abschluss ist hier der am meisten positiv bewertete Einzeiler in dieser Antwort. df.col.str.contains(r'(?=.*apple)(?=.*banana)',regex=True)

    – JacoSolari

    26. März 2020 um 14:13 Uhr

Hier ist ein einzeiliges Lambda, das auch funktioniert:

df["TrueFalse"] = df['col1'].apply(lambda x: 1 if any(i in x for i in searchfor) else 0)

Eingang:

searchfor = ['og', 'at']

df = pd.DataFrame([('cat', 1000.0), ('hat', 2000000.0), ('dog', 1000.0), ('fog', 330000.0),('pet', 330000.0)], columns=['col1', 'col2'])

   col1  col2
0   cat 1000.0
1   hat 2000000.0
2   dog 1000.0
3   fog 330000.0
4   pet 330000.0

Wenden Sie Lambda an:

df["TrueFalse"] = df['col1'].apply(lambda x: 1 if any(i in x for i in searchfor) else 0)

Ausgabe:

    col1    col2        TrueFalse
0   cat     1000.0      1
1   hat     2000000.0   1
2   dog     1000.0      1
3   fog     330000.0    1
4   pet     330000.0    0

  • Ich habe es so gemacht df.loc[df.col1.apply(lambda x: True if any(i in x for i in searchfor) else False)] und es ist gut gegangen, danke.

    – Emremra

    21. Dezember 2020 um 5:53 Uhr

1033440cookie-checkWie kann man in Pandas testen, ob eine Zeichenfolge eine der Teilzeichenfolgen in einer Liste enthält?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy