{ "cells": [ { "cell_type": "markdown", "id": "05254a11", "metadata": {}, "source": [ "# Manipulation von Zeichenketten\n", "\n", "pandas bietet die Möglichkeit, String-Methoden und reguläre Ausdrücke von Python prägnant auf ganze Arrays von Daten anzuwenden.\n", "\n", "
\n", "\n", "**See also:**\n", "\n", "* [Zeichenketten](https://python-basics-tutorial.readthedocs.io/de/latest/types/strings.html)\n", "* [re](https://python-basics-tutorial.readthedocs.io/de/latest/types/strings.html#re)\n", "
" ] }, { "cell_type": "markdown", "id": "96aee19e", "metadata": {}, "source": [ "## Vektorisierte String-Funktionen in pandas\n", "\n", "Das Aufräumen eines unübersichtlichen Datensatzes für die Analyse erfordert oft eine Menge an String-Manipulationen. Erschwerend kommt hinzu, dass eine Spalte, die Strings enthält, manchmal fehlende Daten enthält:" ] }, { "cell_type": "code", "execution_count": 1, "id": "96e414d4", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Veit NaN\n", "Veit Schiele veit.schiele@cusy.io\n", "cusy GmbH info@cusy.io\n", "dtype: object" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import numpy as np\n", "import pandas as pd\n", "\n", "\n", "addresses = {\n", " \"Veit\": np.nan,\n", " \"Veit Schiele\": \"veit.schiele@cusy.io\",\n", " \"cusy GmbH\": \"info@cusy.io\",\n", "}\n", "addresses = pd.Series(addresses)\n", "\n", "addresses" ] }, { "cell_type": "code", "execution_count": 2, "id": "8145c00e", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Veit True\n", "Veit Schiele False\n", "cusy GmbH False\n", "dtype: bool" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "addresses.isna()" ] }, { "cell_type": "markdown", "id": "8eae55f6", "metadata": {}, "source": [ "Ihr könnt Methoden für Zeichenketten und reguläre Ausdrücke auf jeden Wert anwenden (durch Übergabe eines Lambdas oder einer anderen Funktion), indem ihr `data.map` verwendet, aber dies schlägt bei `NA`-Werten fehl. Um dies zu bewältigen, verfügt `Series` über array-orientierte Methoden für String-Operationen, die `NA`-Werte überspringen und weiterleiten. Auf diese wird über das `str`-Attribut von `Series` zugegriffen; zum Beispiel könnten wir mit `str.contains` prüfen, ob jede E-Mail-Adresse `veit` enthält:" ] }, { "cell_type": "code", "execution_count": 3, "id": "755d7852", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Veit NaN\n", "Veit Schiele True\n", "cusy GmbH False\n", "dtype: object" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "addresses.str.contains(\"veit\")" ] }, { "cell_type": "markdown", "id": "9f2c8a6e", "metadata": {}, "source": [ "Reguläre Ausdrücke können ebenfalls verwendet werden, zusammen mit Optionen wie `IGNORECASE`:" ] }, { "cell_type": "code", "execution_count": 4, "id": "13538428", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Veit NaN\n", "Veit Schiele [(veit.schiele, cusy, io)]\n", "cusy GmbH [(info, cusy, io)]\n", "dtype: object" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import re\n", "\n", "\n", "pattern = r\"([A-Z0-9._%+-]+)@([A-Z0-9.-]+)\\.([A-Z]{2,4})\"\n", "\n", "addresses.str.findall(pattern, flags=re.IGNORECASE)" ] }, { "cell_type": "markdown", "id": "e3331cd1", "metadata": {}, "source": [ "Es gibt mehrere Möglichkeiten, ein vektorisiertes Element abzurufen. Entweder verwendet ihr `str.get` oder den Index von `str`:" ] }, { "cell_type": "code", "execution_count": 5, "id": "796c8df2", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Veit NaN\n", "Veit Schiele (veit.schiele, cusy, io)\n", "cusy GmbH (info, cusy, io)\n", "dtype: object" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "matches = addresses.str.findall(pattern, flags=re.IGNORECASE).str[0]\n", "\n", "matches" ] }, { "cell_type": "code", "execution_count": 6, "id": "5dc7ca5a", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Veit NaN\n", "Veit Schiele cusy\n", "cusy GmbH cusy\n", "dtype: object" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "matches.str.get(1)" ] }, { "cell_type": "markdown", "id": "14ea2de4", "metadata": {}, "source": [ "In ähnlicher Weise könnt ihr mit dieser Syntax auch Zeichenketten zerschneiden:" ] }, { "cell_type": "code", "execution_count": 7, "id": "b5f44157", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Veit NaN\n", "Veit Schiele veit.\n", "cusy GmbH info@\n", "dtype: object" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "addresses.str[:5]" ] }, { "cell_type": "markdown", "id": "cc9d6f18", "metadata": {}, "source": [ "Die [pandas.Series.str.extract](https://pandas.pydata.org/docs/reference/api/pandas.Series.str.extract.html)-Methode gibt die erfassten Gruppen eines regulären Ausdrucks als DataFrame zurück:" ] }, { "cell_type": "code", "execution_count": 8, "id": "4460bdec", "metadata": {}, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
012
VeitNaNNaNNaN
Veit Schieleveit.schielecusyio
cusy GmbHinfocusyio
\n", "
" ], "text/plain": [ " 0 1 2\n", "Veit NaN NaN NaN\n", "Veit Schiele veit.schiele cusy io\n", "cusy GmbH info cusy io" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "addresses.str.extract(pattern, flags=re.IGNORECASE)" ] }, { "cell_type": "markdown", "id": "74061d8e", "metadata": {}, "source": [ "Weitere vektorisierten Pandas-String-Methoden:\n", "\n", "Methode | Beschreibung\n", ":------ | :-----------\n", "`cat` | verknüpft Zeichenketten elementweise mit optionalem Trennzeichen\n", "`contains` | gibt ein boolesches Array zurück, wenn jede Zeichenkette ein Muster/Regex enthält\n", "`count` | zählt Vorkommen des Musters\n", "`extract` | verwendet einen regulären Ausdruck mit Gruppen, um eine oder mehrere Zeichenketten aus einer Reihe von Zeichenketten zu extrahieren; das Ergebnis ist ein DataFrame mit einer Spalte pro Gruppe\n", "`endswith` | Äquivalent zu `x.endswith(pattern)` für jedes Element\n", "`startswith` | Äquivalent zu `x.startswith(pattern)` für jedes Element\n", "`findall` | berechnet Liste aller Vorkommen von Muster/Regex für jede Zeichenkette\n", "`get` | Index in jedem Element (`i`-tes Element abrufen)\n", "`isalnum` | Äquivalent zu eingebautem `str.alnum`\n", "`isalpha` | Entspricht dem eingebauten `str.isalpha`\n", "`isdecimal` | Äquivalent zu eingebautem `str.isdecimal`\n", "`isdigit` | Gleichwertig zu eingebautem `str.isdigit`\n", "`islower` | Gleichwertig zu eingebautem `str.islower`\n", "`isnumeric` | Gleichwertig zu eingebautem `str.isnumeric`\n", "`isupper` | Äquivalent zur eingebauten `str.isupper`\n", "`join` | verbindet Zeichenketten in jedem Element der Serie mit dem übergebenen Trennzeichen\n", "`len` | berechnet die Länge jeder Zeichenkette\n", "`lower`, `upper` | konvertiert Groß- und Kleinschreibung; entspricht `x.lower()` oder `x.upper()` für jedes Element\n", "`match` | verwendet `re.match` mit dem übergebenen regulären Ausdruck für jedes Element, wobei `True` oder `False` zurückgegeben wird, wenn es übereinstimmt.\n", "`extract` | erfasst Gruppenelemente (falls vorhanden) nach Index aus jeder Zeichenkette\n", "`pad` | fügt Leerzeichen auf der linken, rechten oder beiden Seiten von Zeichenketten ein\n", "`center` | Äquivalent zu `pad(side='both')`\n", "`repeat` | Doppelte Werte (z.B. `s.str.repeat(3)` entspricht `x * 3` für jede Zeichenkette)\n", "`replace` | ersetzt Muster/Regex durch eine andere Zeichenfolge\n", "`slice` | schneidet jede Zeichenkette in der Serie auf\n", "`split` | teilt Zeichenketten anhand von Begrenzungszeichen oder regulären Ausdrücken\n", "`strip` | schneidet Leerzeichen auf beiden Seiten ab, einschließlich Zeilenumbrüchen\n", "`rstrip` | schneidet Leerzeichen auf der rechten Seite ab\n", "`lstrip` | schneidet Leerzeichen auf der linken Seite ab" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3.13 Kernel", "language": "python", "name": "python313" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.13.0" }, "widgets": { "application/vnd.jupyter.widget-state+json": { "state": {}, "version_major": 2, "version_minor": 0 } } }, "nbformat": 4, "nbformat_minor": 5 }