Ein String (Zeichenkette) ist ein Stück Text zwischen Anführungszeichen. Jede derzeit unterstützte Version von R kodiert Strings in UTF-8, sodass die meisten Sprachen der Welt unterstützt werden können.
mystring <- "some text"
mystring
#> [1] "some text"
typeof(mystring)
#> [1] "character"
Leider kann die Terminologie für Programmierer verwirrend sein, die andere Sprachen kennen.
Obwohl der type character ist, macht R keinen Unterschied zwischen einem einzelnen Buchstaben (in mehreren anderen Sprachen char genannt, in R aber nicht) und einem langen String.
Beides ist ein einzelnes Element und kann austauschbar in einfache ' ' oder doppelte " " Anführungszeichen gesetzt werden.
Der Styleguide empfiehlt doppelte Anführungszeichen, außer wenn du doppelte Anführungszeichen innerhalb des Strings verwenden möchtest, ohne sie zu escapen.
str2 <- 'String with "quotes"' # convenience format
str2
#> [1] "String with \"quotes\"" # standard format
Ein character vector ist also ein Vektor von Strings, wobei jeder String ein einzelnes Element ist.
s <- c("some", "strings")
s
#> [1] "some" "strings"
length(s)
#> [1] 2
length(s[1]) # the number of vector elements, not the string length
#> [1] 1
nchar(s[1]) # the number of characters in the string "some"
#> [1] 4
Im obigen Beispiel ist length(s[1]) gleichbedeutend mit length("some"): die Anzahl der Vektorelemente, nicht die Stringlänge.
Einen einzelnen String zu manipulieren ist natürlich möglich, wie nchar() im obigen Beispiel zeigt, erfordert aber bestimmte Funktionen, die weiter unten besprochen werden.
In Base R ist fast alles möglich, aber viele Programmierer finden die Unterstützung für String-Manipulation ziemlich begrenzt und verwirrend.
Zum Glück gibt es die tidyverse-Pakete, die viel intuitiver, flexibler und in sich stimmiger sind.
Es gibt noch viel Legacy-Code, der String-Funktionen im alten Stil verwendet. Dazu gehören die meisten Community-Lösungen auf Exercism.
Außerdem kann es bei kleinen Aufgaben nützlich sein, eingebaute Funktionen zu verwenden, statt eine große Bibliothek zu importieren. Die Maintainer des R-Tracks wählen gerne diesen Ansatz, wenn sie Musterlösungen schreiben, um die Übungen zu validieren.
Daher lohnt es sich, ein wenig über die alten Ansätze zu wissen.
ncharGibt die Anzahl der Zeichen in einem String zurück.
nchar("string")
#> [1] 6
nchar("Hrōðgār") # a person in Beowulf, written in Old English
#> [1] 7
Das (komplizierte!) Thema, was „Zeichen“ eigentlich bedeutet, sprengt unseren Rahmen. Merke dir nur ein paar Punkte aus den obigen Beispielen:
\0-terminiert (was die Länge um 1 erhöhen würde).paste und paste0
Fügt eine beliebige Anzahl von Strings zu einem einzigen String zusammen.
Optional kann für paste ein Trennzeichen angegeben werden: Standard ist ein Leerzeichen.
paste0(v) ist gleichbedeutend mit paste(v, sep = "").
paste("bits", "of", "a", "string")
#> [1] "bits of a string"
paste0("bits", "of", "a", "string")
#> [1] "bitsofastring"
sprintfFür eine feinere Kontrolle beim Zusammenbauen von Strings übernimmt R die Funktion sprintf aus C (und aus mehreren späteren Sprachen: Wikipedia listet etwa 30 auf).
r <- 5.3
pi <- 3.14159
sprintf("A circle of radius %.1f has area %.2f", r, pi * r^2)
#> [1] "A circle of radius 5.3 has area 88.25"
trimwsFührende und/oder nachfolgende Leerzeichen lassen sich mit trimws() entfernen:
s <- " messy string "
trimws(s)
#> [1] "messy string"
Es gibt einen Parameter which = "left" (oder „right“), damit nicht beide Enden gekürzt werden.
substrWirkt auf einen einzelnen String und gibt einen Teilstring zwischen zwei (einschließlich) Grenzen zurück.
substr("Exercism", 5, 7)
#> [1] "cis"
strsplitTeilt einen String anhand eines Trenn-Strings in eine R-Liste auf. Der Trenner ist erforderlich (es gibt keinen Standardwert), kann aber ein leerer String sein.
strsplit("R, Python, Julia", ", ")
[[1]]
#> [1] "R" "Python" "Julia"
strsplit("Exercism", "")
[[1]]
#> [1] "E" "x" "e" "r" "c" "i" "s" "m"
Listen werden in einem eigenen Konzept behandelt.
Wenn du diesen Teil des Lehrplans noch nicht erreicht hast, merke dir vorerst nur, dass die Funktion unlist() (in diesem Fall) eine Liste in einen Vektor umwandelt.
unlist(strsplit("Exercism", ""))
#> [1] "E" "x" "e" "r" "c" "i" "s" "m"
Wohlwollend formuliert könnte man sagen, dass die String-Funktionen im alten Stil nicht das Beste sind, was R zu bieten hat (weniger wohlwollende Ansichten gibt es auch).
Um die Lage zu verbessern, wird die Bibliothek stringr seit 2009 entwickelt und ist heute ein zentraler Teil der Tidyverse-Sammlung.
Importiere sie mit library(stringr) oder library(tidyverse) in deinen Namensraum.
Einige wichtige Merkmale:
str_ und versuchen, den Zweck klar zu machen.Wie alle Tidyverse-Pakete hat stringr eine gute Dokumentation, die meist von den Autor(inn)en des Pakets geschrieben wird.
Die Verwendung von Pipes |> zum Verbinden von Funktionen wird an anderen Stellen des Lehrplans ausführlicher besprochen.
Für den Moment ist es nützlich zu wissen, dass:
Das folgende Beispiel veranschaulicht die Syntax. Die einzelnen Funktionen werden später besprochen.
library(stringr)
"Monday-25-February" |>
str_split("-") |>
unlist() |> # [1] "Monday" "25" "February"
str_sub(1, 3) |> # [1] "Mon" "25" "Feb"
str_to_upper() |> # [1] "MON" "25" "FEB"
str_flatten(collapse = ", ")
#> [1] "MON, 25, FEB"
str_length zählt Code Points (ähnlich wie nchars).
Verschiedene andere Funktionen bearbeiten Leerzeichen, darunter str_trim() und str_squish().
Das ist oft ein wichtiger Aufräumschritt am Anfang jedes Data-Science-Projekts.
# The first 3 kernels in JuPyteR notebooks:
str_length(c("Julia", "Python", "R")) #> [1] 1 6 5
#> [1] 5 6 1
str_pad(c("Julia", "Python", "R"), 8, "right") # add spaces if necessary
#> [1] "Julia " "Python " "R "
str_trim("Julia Python R ") # remove leading & trailing whitespace
#> [1] "Julia Python R"
str_squish("Julia Python R ") # trim, collapse multiple spaces
#> [1] "Julia Python R"
Die Funktion str_sub(string, start, end) gibt den Teilstring von start bis end (einschließlich) zurück, während str_sub_all() auf mehrere Strings gleichzeitig wirken kann.
Es gibt viel Spielraum.
start und end stehen standardmäßig für das erste bzw. letzte Zeichen.
Sie können Vektoren von Indizes sein.
Im wohltuenden Gegensatz zur Vektorindizierung zählen negative Werte wie in Python vom Ende des Strings rückwärts.
s <- "abcdefgh"
str_sub(s, 2, 4)
#> [1] "bcd"
str_sub(s, 5)
#> [1] "efgh"
str_sub(s, -3, -2)
#> [1] "fg"
str_sub(s, c(1, 4), c(2, 5))
#> [1] "ab" "de"
str_sub(s, c(1, 4, 6), c(2, 5, -1))
#> [1] "ab" "de" "fgh"
s |> str_sub(2, 4) # these functions are designed for pipes
#> [1] "bcd"
str_flatten wandelt einen Character-Vektor in einen einzelnen String um.
Das Argument collapse wird zwischen jedes Element eingefügt und ist standardmäßig "".
c("R", "Julia", "Python") |> str_flatten()
#> [1] "RJuliaPython"
c("R", "Julia", "Python") |> str_flatten(collapse = " - ")
#> [1] "R - Julia - Python"
str_c wandelt mehrere Character-Vektoren in einen einzelnen Character-Vektor um, wobei bei Bedarf recycelt wird.
str_c(LETTERS[1:8], 1:8, sep = ":")
#> [1] "A:1" "B:2" "C:3" "D:4" "E:5" "F:6" "G:7" "H:8"
str_glue bringt einfache String-Interpolation nach R.
Ausdrücke in geschweiften Klammern { } werden ausgewertet und durch ihre Textdarstellung ersetzt.
r <- 5.3
pi <- 3.14159
str_glue("A circle of radius {r} has area {pi * r^2}")
A circle of radius 5.3 has area 88.2472631
Eine sehr häufige Verwendung von R ist es, unordentliche Daten für die Analyse in ein einheitliches Format zu bringen. Um das zu erleichtern, gibt es mehrere Möglichkeiten, Text in Teilstrings aufzuteilen. Die meisten sprengen den aktuellen Rahmen.
str_split_1 ist die einfachste: Sie wandelt einen einzelnen String in einen Vektor von Teilen um, aufgeteilt an einem angegebenen Muster (es gibt kein Standardmuster).
s <- "R Julia Python"
str_split_1(s, " ")
#> [1] "R" "Julia" "Python"
Einige Sprachen (vor allem europäische) unterscheiden zwischen GROSS- und Kleinbuchstaben.
Es gibt eine Reihe von stringr-Funktionen, um diese umzuwandeln, und zwar passend zur jeweiligen Locale:
str_to_lower()str_to_upper()str_to_title() : erster Buchstabe jedes Wortes großstr_to_sentence() : erster Buchstabe des Satzes großstr_to_upper("elixir") # defaults to locale = "en"
#> [1] "ELIXIR"
str_to_upper("ελληνικά") # infers Greek
#> [1] "ΕΛΛΗΝΙΚΆ"
str_to_title("the cat sat on the mat")
#> [1] "The Cat Sat On The Mat"
str_to_sentence("the cat sat on the mat")
#> [1] "The cat sat on the mat"
Für das Ersetzen von Teilstrings auf Basis von Musterabgleich ändert str_replace() das erste Vorkommen des Musters, str_replace_all() alle Vorkommen.
Für das Ersetzen von Teilstrings auf Basis von Zeichenindizes gibt es eine Zuweisungsform von str_sub().
s <- "abcde"
str_sub(s, 3, 4) <- "yz"
s
#> [1] "abyze"
In dieser Übung verarbeitest du Logzeilen.
Jede Logzeile ist ein String mit folgendem Format: "[<LEVEL>]: <MESSAGE>".
Es gibt drei verschiedene Log-Level:
INFOWARNINGERRORDu hast drei Aufgaben. Jede bekommt eine Logzeile, und du sollst etwas damit machen.
Du kannst entweder die alten Funktionen aus base R oder die Bibliothek stringr verwenden. Beide führen zu kurzen, brauchbaren Lösungen.
Implementiere die Funktion message, die die Nachricht einer Logzeile zurückgibt:
message("[ERROR]: Invalid operation")
#> "Invalid operation"
Führender und nachfolgender Leerraum soll entfernt werden:
message("[WARNING]: Disk almost full\r\n")
#> "Disk almost full"
Implementiere die Funktion log_level, die das Log-Level einer Logzeile zurückgibt. Es soll in Kleinbuchstaben zurückgegeben werden:
log_level("[ERROR]: Invalid operation")
#> "error"
Implementiere die Funktion reformat, die die Logzeile umformatiert. Die Nachricht steht zuerst, danach folgt das Log-Level in Klammern:
reformat("[INFO]: Operation completed")
#> "Operation completed (info)"
Melde dich bei Exercism an, um R mit 21 Konzepte111 Übungen und echtem menschlichen Mentoring zu lernen und zu meistern, alles kostenlos.