Kurs
Ein Leitfaden für reguläre Ausdrücke in R
Das Konzept der regulären Ausdrücke, auch Regex genannt, gibt es in vielen Programmiersprachen, z. B. in R, Python, C, C++, Perl, Java und JavaScript. Du kannst die Funktionalität von regex entweder in der Basisversion dieser Sprachen oder über Bibliotheken nutzen. In den meisten Programmiersprachen ist die Syntax von Regex-Mustern ähnlich.
In diesem Tutorial erfahren wir, was reguläre Ausdrücke in R sind, warum sie wichtig sind, mit welchen Werkzeugen und Funktionen wir mit ihnen arbeiten können, welche Regex-Muster am häufigsten vorkommen und wie man sie verwendet. Zum Schluss geben wir noch einen Überblick über einige fortgeschrittene Anwendungen von R Regex.
Was sind R Regex und warum solltest du sie verwenden?
Ein regulärer Ausdruck, Regex, ist in R eine Folge von Zeichen (oder auch nur ein Zeichen), die ein bestimmtes Muster in einem Text beschreibt. Regex-Muster können so kurz wie "a" oder so lang wie das in diesem StackOverflow-Thread erwähnte sein.
Im Großen und Ganzen bezieht sich die obige Definition der Regex nicht nur auf R, sondern auch auf jede andere Programmiersprache, die reguläre Ausdrücke unterstützt.
Regex ist ein sehr flexibles und leistungsstarkes Werkzeug, das häufig für die Verarbeitung und Auswertung unstrukturierter Textdaten verwendet wird. Sie werden zum Beispiel in Suchmaschinen, lexikalischen Analysen, Spam-Filtern und Texteditoren eingesetzt.
Werkzeuge und Funktionen für die Arbeit mit R Regex
Während Regex-Muster für die meisten Programmiersprachen ähnlich sind, unterscheiden sich die Funktionen für die Arbeit mit ihnen.
In R können wir die Funktionen der R-Basis nutzen, um Regex zu erkennen, abzugleichen, zu lokalisieren, zu extrahieren und zu ersetzen. Im Folgenden findest du die wichtigsten Funktionen, die nach Regex-Übereinstimmungen in einem Zeichenvektor suchen und dann Folgendes tun:
- grep(), grepl() - geben die Indizes der Zeichenketten zurück, die einen Treffer enthalten (grep()) oder einen logischen Vektor, der zeigt, welche Zeichenketten einen Treffer enthalten (grepl()).
- regexpr(), gregexpr() - geben den Index für jede Zeichenkette zurück, an dem die Übereinstimmung beginnt, sowie die Länge dieser Übereinstimmung. Während regexpr() diese Informationen nur für die erste Übereinstimmung (von links) liefert, tut gregexpr() das Gleiche für alle Übereinstimmungen.
- sub(), gsub() - ersetzt eine erkannte Übereinstimmung in jeder Zeichenfolge durch eine angegebene Zeichenfolge (sub() - nur für die erste Übereinstimmung, gsub() - für alle Übereinstimmungen).
- regexec() - funktioniert wie regexpr(), gibt aber die gleichen Informationen auch für einen bestimmten Unterausdruck innerhalb der Übereinstimmung zurück.
- regmatches() - funktioniert wie regexec(), gibt aber die genauen Zeichenfolgen zurück, die für die Gesamtübereinstimmung und einen angegebenen Unterausdruck gefunden wurden.
Anstatt die nativen R-Funktionen zu verwenden, ist es jedoch bequemer und konsistenter, mit R-Regex zu arbeiten, wenn du ein spezielles stringr-Paket aus der tidyverse-Sammlung verwendest. Diese Bibliothek baut auf dem Paket stringi auf. In der stringr-Bibliothek beginnen alle Funktionen mit str_ und haben viel intuitivere Namen (wie auch die Namen ihrer optionalen Parameter) als die der Basis-R.
Um das stringr-Paket zu installieren und zu laden, führe Folgendes aus:
install.packages('stringr')
library(stringr)
Die folgende Tabelle zeigt die Entsprechungen zwischen den Funktionen von stringr und den Funktionen von R, die wir weiter oben in diesem Abschnitt besprochen haben:
stringr |
Basis R |
str_subset() |
grep() |
str_detect() |
grepl() |
str_extract() |
regexpr(), regmatches(), grep() |
str_match() |
regexec() |
str_locate() |
regexpr() |
str_locate_all() |
gregexpr() |
str_replace() |
sub() |
str_replace_all() |
gsub() |
Eine vollständige Liste der stringr-Funktionen und regulären Ausdrücke findest du in diesen Spickzetteln, aber wir werden einige von ihnen in diesem Lernprogramm näher erläutern.
Hinweis: In den stringr-Funktionen übergeben wir zuerst die Daten und dann eine Regex, während wir bei den R-Basisfunktionen genau das Gegenteil tun.
R Regex-Muster
Jetzt werden wir einen Überblick über die beliebtesten R-Regex-Muster und ihre Verwendung geben und gleichzeitig einige der stringr-Funktionen üben.
Bevor wir das tun, lass uns einen Blick auf ein sehr einfaches Beispiel werfen. Überprüfen wir nämlich, ob ein Einhorn mindestens ein Korn hat 😉 .
str_detect('unicorn', 'corn')
Output:
TRUE
In diesem Beispiel haben wir die Funktion str_detect() stringr verwendet, um das Vorhandensein der Zeichenkette corn in der Zeichenkette unicorn zu überprüfen.
Normalerweise suchen wir aber nicht nach einer bestimmten Zeichenkette in einem Text, sondern nach einem bestimmten Muster - einem regulären Ausdruck. Lass uns eintauchen und solche Muster erforschen.
Charakter Fluchten
Es gibt ein paar Zeichen, die eine besondere Bedeutung haben, wenn sie in regulären Ausdrücken in R verwendet werden. Genauer gesagt, sie passen nicht zu sich selbst, wie alle Buchstaben und Ziffern, sondern sie tun etwas anderes:
str_extract_all('unicorn', '.')
Output:
1. 'u' 'n' 'i' 'c' 'o' 'r' 'n'
Wir sehen deutlich, dass unser Einhorn keine Punkte hat. Die Funktion str_extract_all() hat jedoch jedes einzelne Zeichen aus dieser Zeichenkette extrahiert. Das ist die genaue Aufgabe des Zeichens . - es passt auf jedes einzelne Zeichen, außer auf eine neue Zeile.
Was ist, wenn wir einen wörtlichen Punkt extrahieren wollen? Zu diesem Zweck müssen wir ein Regex-Fluchtzeichen vor dem Punkt verwenden - einen Backslash (\). Allerdings gibt es hier einen Fallstrick, den du beachten musst: Ein Backslash wird auch in den Strings selbst als Fluchtzeichen verwendet. Das bedeutet, dass wir zuerst das Escape-Zeichen mit einem doppelten Backslash"entkommen" müssen. Schauen wir mal, wie es funktioniert:
str_extract_all('Eat. Pray. Love.', '\\.')
Output:
1. '.' '.' '.'
Daher hilft der Backslash dabei, eine besondere Bedeutung einiger Symbole in regulären Ausdrücken in R zu vernachlässigen und sie wörtlich zu interpretieren. Sie hat auch die gegenteilige Aufgabe: einigen Zeichen eine besondere Bedeutung zu geben, die sonst wörtlich interpretiert werden würden. Im Folgenden findest du eine Tabelle mit den am häufigsten verwendeten Escape-Zeichenfolgen:
R regex |
Welche Spiele |
\b |
Eine Wortgrenze (eine Grenze zwischen einem \w und einem \W) |
\B |
Eine Nicht-Wort-Grenze(\w-\w oder \W-\W) |
\n |
Eine neue Linie |
\t |
A tab |
\v |
Ein vertikaler Reiter |
Schauen wir uns einige Beispiele an und beachten wir, dass wir auch in solchen Fällen einen doppelten Backslash verwenden müssen. Gleichzeitig werden wir zwei weitere stringr-Funktionen einführen: str_view() und str_view_all() (um die HTML-Wiedergabe des ersten Treffers oder aller Treffer anzuzeigen):
str_view('Unicorns are so cute!', 's\\b')
str_view('Unicorns are so cute!', 's\\B')
Output:
Einhörner sind so süß!
Einhörner sind sosüß!
In der Zeichenkette Einhörner sind so süß! gibt es zwei Stellen, an denen der Buchstabe s vorkommt. Oben hat das erste R-Regex-Muster das erste Vorkommen des Buchstabens s hervorgehoben (da ihm ein Leerzeichen folgt), während das zweite Muster das zweite Vorkommen hervorhebt (da ihm ein anderer Buchstabe folgt, keine Wortgrenze).
Ein paar weitere Beispiele:
cat('Unicorns are\nso cute!')
str_view_all('Unicorns are\nso cute!', '\\n')
Output:
Unicorns are
so cute!
Einhörner sind_sosüß!
cat('Unicorns are\tso cute!')
str_view_all('Unicorns are\tso cute!', '\\t')
Output:
Unicorns are so cute!
Einhörner sind_sosüß!
Charakter-Klassen
Eine Zeichenklasse entspricht einem beliebigen Zeichen aus einer vordefinierten Menge von Zeichen. Eingebaute Zeichenklassen haben die gleiche Syntax wie die Escape-Sequenzen, die wir im vorigen Abschnitt gesehen haben: ein Backslash, gefolgt von einem Buchstaben, dem er eine besondere Bedeutung gibt, anstatt seiner wörtlichen Bedeutung. Die beliebtesten dieser Konstruktionen sind unten aufgeführt:
R regex |
Welche Spiele |
\w |
Jedes Wortzeichen (jeder Buchstabe, jede Ziffer oder jeder Unterstrich) |
\W |
Jedes Nicht-Wort-Zeichen |
\d |
Jede Ziffer |
\D |
Jede nicht-zifferige |
\s |
Ein beliebiges Leerzeichen (ein Leerzeichen, ein Tabulator, eine neue Zeile, etc.) |
\S |
Jedes Zeichen ohne Leerzeichen |
Schauen wir uns ein paar selbsterklärende Beispiele an:
str_view_all('Unicorns are so cute!', '\\w')
str_view_all('Unicorns are so cute!', '\\W')
Output:
Einhörner sind so süß!
Unicorns_are_so_cute!
str_view_all('Unicorns are\nso cute!', '\\s')
str_view_all('Unicorns are\nso cute!', '\\S')
Output:
Einhörner_sind_so_niedlich!
Einhörner sind so süß!
str_detect('Unicorns are so cute!', '\\d')
Output:
FALSE
Eingebaute Zeichenklassen können auch in einer alternativen Form erscheinen - [:character_class_name:]. Einige dieser Zeichenklassen haben ein Äquivalent unter denjenigen mit einem Backslash, andere nicht. Die häufigsten sind:
R regex |
Welche Spiele |
[:alpha:] |
Jeder Brief |
[:lower:] |
Jeder Kleinbuchstabe |
[:upper:] |
Jeder Großbuchstabe |
[:digit:] |
Beliebige Ziffer (entspricht \d) |
[:alnum:] |
Jeder Buchstabe oder jede Zahl |
[:xdigit:] |
Jede hexadezimale Ziffer |
[:punct:] |
Jedes Interpunktionszeichen |
[:graph:] |
Ein beliebiger Buchstabe, eine Zahl oder ein Interpunktionszeichen |
[:space:] |
Ein Leerzeichen, ein Tabulator, eine neue Zeile, usw. (entspricht \s) |
Schauen wir uns einige Beispiele an und beachten wir dabei, dass wir jedes der oben genannten R-Regex-Muster in eckige Klammern setzen müssen:
str_view('Unicorns are so cute!', '[[:upper:]]')
str_view('Unicorns are so cute!', '[[:lower:]]')
Output:
Einhörnersind so süß!
Einhörnersind so süß!
str_detect('Unicorns are so cute!', '[[:digit:]]')
Output:
FALSE
str_extract_all('Unicorns are so cute!', '[[:punct:]]')
Output:
1. '!'
str_view_all('Unicorns are so cute!', '[[:space:]]')
Output:
Einhörner_sind_so_niedlich!
Es ist auch möglich, eine benutzerdefinierte Zeichenklasse zu erstellen, indem du eine beliebige Menge von Zeichen in eckige Klammern setzt, aus der wir ein beliebiges Zeichen finden wollen. Wir können einen Bereich von Buchstaben oder Zahlen (in Unicode-Reihenfolge), mehrere verschiedene Bereiche oder eine beliebige sequentielle oder nicht sequentielle Menge von Zeichen oder Zeichengruppen in eckige Klammern einschließen.
Zum Beispiel passt [A-D] auf alle Großbuchstaben von A bis einschließlich D, [k-r] auf alle Kleinbuchstaben von k bis einschließlich r,[0-7] auf alle Ziffern von 0 bis einschließlich 7 und [aou14%9] auf alle Zeichen, die in eckigen Klammern stehen. Wenn wir das Caret (^) als erstes Zeichen in eckige Klammern setzen, wird unser R-Regex-Muster auf alles außer den angegebenen Zeichen passen. Beachte, dass die obigen Abgleichmechanismen zwischen Groß- und Kleinschreibung unterscheiden.
str_view_all('Unicorns Are SOOO Cute!', '[O-V]')
str_view_all('Unicorns Are SOOO Cute!', '[^O-V]')
Output:
Einhörnersind SOOO niedlich!
Einhörner sind SOOO niedlich!
str_view_all('3.14159265359', '[0-2]')
Output:
3.14159265359
str_view_all('The number pi is equal to 3.14159265359', '[n2e9&]')
Output:
DieZahlPi ist gleich3.14159265359
Quantoren
Oft müssen wir ein bestimmtes R-Regex-Muster wiederholt abgleichen, anstatt nur einmal. Zu diesem Zweck verwenden wir Quantifizierer. Ein Quantifizierer steht immer nach dem Regex-Muster, mit dem er verbunden ist. Die häufigsten Quantoren sind in der folgenden Tabelle aufgeführt:
R regex |
Anzahl der Musterwiederholungen |
* |
0 oder mehr |
+ |
mindestens 1 |
? |
höchstens 1 |
{n} |
genau n |
{n,} |
mindestens n |
{n,m} |
mindestens n und höchstens m |
Lass sie uns alle ausprobieren:
str_extract('dog', 'dog\\d*')
Output:
'dog'
Wir haben den anfänglichen String Hund: Es gibt keine Ziffern am Ende des Strings, aber wir sind damit einverstanden (0 oder mehr Instanzen von Ziffern).
str_extract('12345', '\\d+')
Output:
'12345'
str_extract('12345', '\\d?')
Output:
'1'
str_extract('12345', '\\d{3}')
Output:
'123'
str_extract('12345', '\\d{7,}')
Output:
NA
Wir haben NA, weil wir nicht mindestens 7 Ziffern in der Zeichenkette haben, sondern nur 5 davon.
str_extract('12345', '\\d{2,4}')
Output:
'1234'
Anker
Standardmäßig passt R regex auf jeden Teil einer angegebenen Zeichenkette. Wir können dieses Verhalten ändern, indem wir eine bestimmte Position eines R-Regex-Musters innerhalb des Strings angeben. Meistens wollen wir die Übereinstimmung vom Anfang oder Ende der Zeichenkette aus erzwingen. Zu diesem Zweck verwenden wir die beiden wichtigsten Anker in den regulären Ausdrücken von R:
- ^ - entspricht dem Anfang der Zeichenkette (bei mehrzeiligen Zeichenketten - dem Anfang jeder Zeile)
- $ - entspricht dem Ende der Zeichenkette (bei mehrzeiligen Zeichenketten dem Ende jeder Zeile)
Lass uns sehen, wie sie am Beispiel eines Palindroms funktionieren , das keine Brieftasche gewonnen hat:
str_view('stella won no wallets', '^s')
str_view('stella won no wallets', 's$')
Output:
stellagewann keine Brieftaschen
stella won no wallets
Wenn wir die Zeichen ^ oder $ selbst abgleichen wollen, müssen wir dem betreffenden Zeichen einen Backslash voranstellen(und es verdoppeln):
str_view_all('Do not have 100$, have 100 friends', '\\$')
Output:
Habe keine 100$, habe 100 Freunde
Es ist auch möglich, Übereinstimmungen an Wort- oder Nicht-Wort-Grenzen innerhalb der Zeichenkette zu verankern(\b bzw. \B ):
str_view_all('road cocoa oasis oak boa coach', '\\boa')
str_view_all('road cocoa oasis oak boa coach', 'oa\\b')
str_view_all('road cocoa oasis oak boa coach', 'oa\\B')
Output:
Straße Kakao Oase EicheBoa Coach
Straße Kakao Oase EicheBoa Coach
StraßeKakao Oase EicheBoaCoach
Oben haben wir die Buchstabenkombination oa gefunden:
- 1. Beispiel - am Anfang der Wörter
- 2. Beispiel - am Ende der Wörter
- 3. Beispiel - immer dann, wenn ein Wortzeichen folgt (in unserem Fall - ein Buchstabe)
Abwechslung
Mit dem Alternationsoperator(|) können wir mehr als ein R-Regex-Muster in derselben Zeichenfolge finden. Wenn wir diesen Operator als Teil einer benutzerdefinierten Zeichenklasse verwenden, wird er wortwörtlich interpretiert und führt daher keine Änderung durch.
str_view_all('coach koala board oak cocoa road boa load coat oasis boat', 'boa|coa')
Output:
CoachKoala BoardEiche Kakao Straße Boa Last MantelOase Boot
Im obigen Beispiel haben wir alle Instanzen von entweder boa oder coa gefunden.
Gruppierung
R-Regex-Muster folgen bestimmten Vorrangregeln. Zum Beispiel hat die Wiederholung (mit Quantoren) Vorrang vor der Verankerung, während die Verankerung Vorrang vor der Alternation hat. Um diese Regeln außer Kraft zu setzen und den Vorrang einer bestimmten Operation zu erhöhen, sollten wir die Gruppierung verwenden. Dies kann geschehen, indem du einen Teilausdruck von Interesse in runde Klammern einschließt.
Die Gruppierung funktioniert am besten in Kombination mit dem Alternationsoperator. Die folgenden Beispiele zeigen deutlich, welche Wirkung eine solche Kombination hat:
str_view_all('code rat coat cot cat', 'co|at')
str_view_all('code rat coat cot cat', 'c(o|a)t')
Output:
Code RattenfellbettchenKatze
Code Rattenfellbettchen Katze
Fortgeschrittene Anwendungen von R Reguläre Ausdrücke
Alles, was wir bisher besprochen haben, gibt uns eine gute Grundlage für die Arbeit mit regulären Ausdrücken in R. Aber es gibt noch viel mehr, was wir mit diesem mächtigen Werkzeug tun können. Ohne ins Detail zu gehen, wollen wir nur einige fortgeschrittene Operationen erwähnen, die wir mit R Regex durchführen können:
- Überschreiben der Standardeinstellungen der stringr-Funktionen
- Passende Graphem-Cluster
- Rückverweis auf die Gruppe
- Passende Unicode-Eigenschaften
- Anwendung der erweiterten Zeichenumwandlung
- Überprüfen der Existenz eines Musters, ohne es in die Ausgabe aufzunehmen (sogenannte Lookarounds)
- Den Mechanismus der Musterwiederholung nicht gierig, sondern träge machen
- Arbeiten mit atomaren Gruppen
Lerne mehr in unserem Kurs Reguläre Ausdrücke in R für Fortgeschrittene.
R Regex Herausforderung
Jetzt bist du an der Reihe, die R-Regex-Muster zu üben, die wir in diesem Tutorium besprochen haben. Verwende dazu unseren Datensatz: Internet News and Consumer Engagement, und versuche Folgendes: Extrahiere die Top-Level-Domains (TLDs) aus allen URLs. Einige Beispiele für TLDs sind com, net, uk, etc.
Es gibt mehr als einen Ansatz, um diese Aufgabe zu erledigen, darunter auch elegante und kompakte Ein-Zeilen-Lösungen (Tipp: Du kannst mehr über die im vorherigen Abschnitt erwähnten Lookarounds in R Regex erfahren und sie zur Lösung dieses Problems verwenden). Betrachte die folgende sehr lockere Anleitung für einen relativ "unbedarften" Ansatz:
- Untersuche einige URLs im Datensatz und stelle fest, welche Muster in jeder URL vor der TLD immer vorhanden sind und welche optional sind
- Beachte, ob es in jeder URL nach der TLD obligatorische Muster gibt (und wenn ja, welche) und welche Muster optional sind
- Entferne alles vor der TLD der URL
- Entferne alles nach der TLD der URL
Um das Problem mit dem obigen Algorithmus zu lösen, musst du nichts weiter tun oder lernen. Frische einfach alles auf, was wir in diesem Tutorial besprochen haben und setze dein Wissen in die Praxis um. Du brauchst vor allem die Funktionen stringr, Zeichen-Escapes, Zeichenklassen, Quantifizierer und Gruppierungen.
Bonus: Herausforderung #2
Wenn du noch mehr üben willst, diesmal ohne Hinweise, versuche Folgendes: Benutze den gleichen Datensatz wie bei der vorherigen Aufgabe und extrahiere die Domainnamen aus allen URLs. Ein Beispiel für einen Domainnamen ist Google in der URL www.google.com.
Fazit
Abschließend haben wir in diesem Tutorium viel über reguläre Ausdrücke in R gelernt. Wir haben vor allem diskutiert:
- Was R Regex sind
- Warum sie wichtig sind und wo sie angewendet werden
- Welche Funktionen (sowohl aus R als auch aus einer speziellen Bibliothek) werden für die Arbeit mit regulären Ausdrücken in R verwendet?
- Die gebräuchlichsten R-Regex-Muster und ihr Umfang, ihre Feinheiten und Fallstricke
- Wann und wie man Zeichen-Escapes, Zeichenklassen, Quantifizierer, Anker, Alternation und Gruppierung mit R Regex verwendet
- Verschiedene Beispiele für die Anwendung von R Regex und Funktionen
- Einige fortgeschrittene Operationen mit regulären Ausdrücken in R
Diese Kenntnisse und Begriffe werden dir bei der Arbeit in R und in vielen anderen Programmiersprachen helfen, da das Konzept der regulären Ausdrücke in all diesen Sprachen gleich ist und auch die Syntax der Regex in den meisten Sprachen sehr ähnlich ist.
Wenn du daran interessiert bist, deine R-Kenntnisse zu verbessern, solltest du die folgenden Kurse, Lernpfade und Artikel von DataCamp kennenlernen:
Top R Kurse
Kurs
Einführung in die Regression in R
Kurs