A string idézőjelek közé zárt szövegrész. Az R minden jelenleg támogatott verziója UTF-8-ban kódolja a stringeket, így a világ nyelveinek többsége támogatható.
mystring <- "some text"
mystring
#> [1] "some text"
typeof(mystring)
#> [1] "character"
Sajnos a terminológia zavaró lehet azoknak a programozóknak, akik más nyelveket ismernek.
Bár a type értéke character, az R nem tesz különbséget egyetlen betű (amit több más nyelvben char-nak hívnak, de R-ben nem) és egy hosszú string között.
Mindkettő egyetlen elem, és felváltva állhat aposztrófok ' ' vagy idézőjelek " " között.
A stílusútmutató a kettős idézőjelek használatát javasolja, kivéve, ha kettős idézőjelet szeretnél a stringen belül elhelyezni anélkül, hogy escape-elned kellene őket.
str2 <- 'String with "quotes"' # convenience format
str2
#> [1] "String with \"quotes\"" # standard format
A character vector tehát stringek vektora, ahol minden string egyetlen elem.
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
A fenti példában a length(s[1]) ugyanaz, mint a length("some"): a vektorelemek számát adja meg, nem a string hosszát.
Egy-egy string módosítása természetesen lehetséges, ahogy a fenti példában a nchar() is mutatja, de ehhez speciális függvények kellenek, amelyeket alább tárgyalunk.
A base R-ben szinte minden lehetséges, de sok programozó szerint a stringkezelés támogatása meglehetősen korlátozott és zavaró.
Szerencsére vannak tidyverse csomagok, amelyek sokkal intuitívabbak, rugalmasabbak és önmagukban konzisztensebbek.
Még mindig sok régi kód használ régi stílusú stringfüggvényeket. Ide tartozik az Exercism közösségi megoldásainak nagy része is.
Ráadásul kis feladatoknál hasznos lehet a beépített függvények használata egy nagy csomag importálása helyett. Az R-kurzus karbantartói jellemzően ezt a megközelítést választják, amikor mintamegoldásokat írnak a feladatok ellenőrzéséhez.
Ezért érdemes megismerkedni a régi megközelítésekkel is.
ncharEgy string karaktereinek számát adja vissza.
nchar("string")
#> [1] 6
nchar("Hrōðgār") # a person in Beowulf, written in Old English
#> [1] 7
Az, hogy mit is jelent pontosan a »karakter«, (bonyolult!) téma, és meghaladja ennek az anyagnak a kereteit. Csak jegyezz meg néhány dolgot a fenti példákból:
\0-termináltak (ami 1-gyel növelné a hosszukat).paste és paste0
Tetszőleges számú stringet fűz össze egyetlen stringgé.
A paste esetében opcionálisan megadható egy elválasztó: az alapértéke egy szóköz.
A paste0(v) ugyanaz, mint a paste(v, sep = "").
paste("bits", "of", "a", "string")
#> [1] "bits of a string"
paste0("bits", "of", "a", "string")
#> [1] "bitsofastring"
sprintfA stringek összeállításának finomabb szabályozásához az R a C-ből vette át a sprintf függvényt (és több későbbi nyelv is: a Wikipédia mintegy 30-at sorol fel).
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"
trimwsA kezdő és/vagy záró whitespace eltávolítható a trimws() függvénnyel:
s <- " messy string "
trimws(s)
#> [1] "messy string"
Van egy which = "left" (vagy „right”) paraméter, amellyel elkerülhető mindkét vég levágása.
substrEgyetlen stringen működik, és visszaadja a két határ közötti részstringet (a határokat is beleértve).
substr("Exercism", 5, 7)
#> [1] "cis"
strsplitEgy stringet R listává bont szét egy elválasztó string alapján. Az elválasztó megadása kötelező (nincs alapértéke), de lehet üres string is.
strsplit("R, Python, Julia", ", ")
[[1]]
#> [1] "R" "Python" "Julia"
strsplit("Exercism", "")
[[1]]
#> [1] "E" "x" "e" "r" "c" "i" "s" "m"
A listákról egy külön fogalom szól majd.
Ha még nem jutottál el a tantervnek ahhoz a részéhez, egyelőre elég annyit tudnod, hogy az unlist() függvény (ebben az esetben) listát alakít vektorrá.
unlist(strsplit("Exercism", ""))
#> [1] "E" "x" "e" "r" "c" "i" "s" "m"
Ha jóindulattal akarunk fogalmazni, azt mondhatjuk, hogy a régi stílusú stringfüggvények nem az R legjobbjai (kevésbé jóindulatú vélemények is léteznek).
A helyzet javítására a stringr csomag 2009 óta fejlődik, és mára a Tidyverse gyűjtemény kulcsfontosságú része.
Töltsd be a névtérbe a library(stringr) vagy a library(tidyverse) hívással.
Néhány fontos jellemzője:
str_ előtaggal kezdődik, és igyekszik világossá tenni a célját.Mint minden Tidyverse-csomagnak, a stringr-nek is jó dokumentációja van, amelyet jellemzően a csomag szerzője (szerzői) írt.
A függvények összekapcsolására szolgáló |> pipe-okról a tanterv más részein lesz szó részletesebben.
Egyelőre ennyit érdemes tudni:
Az alábbi példa szemlélteti a szintaxist. Az egyes függvényeket később tárgyaljuk.
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"
A str_length kódpontokat számol (hasonlóan az nchars-hoz).
Több más függvény is foglalkozik a whitespace-szel, például a str_trim() és a str_squish().
Ez gyakran nélkülözhetetlen tisztítási feladat bármely adatelemzési projekt elején.
# 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"
A str_sub(string, start, end) függvény a start-tól end-ig (a határokat is beleértve) visszaadja a részstringet, míg a str_sub_all() több stringen is működhet.
Nagy a rugalmasság.
A start és az end alapértéke az első, illetve az utolsó karakter.
Lehetnek indexek vektorai is.
Kellemes ellentétben a vektorindexeléssel, a negatív értékek a string végétől számolódnak visszafelé, a Python mintájára.
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"
A str_flatten egy karaktervektort alakít egyetlen stringgé.
A collapse argumentum minden elem közé bekerül, alapértéke pedig "".
c("R", "Julia", "Python") |> str_flatten()
#> [1] "RJuliaPython"
c("R", "Julia", "Python") |> str_flatten(collapse = " - ")
#> [1] "R - Julia - Python"
A str_c több karaktervektort alakít egyetlen karaktervektorrá, szükség szerinti újrahasznosítással.
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"
A str_glue egyszerű string-interpolációt hoz az R-be.
A kapcsos zárójelek { } közötti kifejezések kiértékelődnek, és a szöveges megjelenítésük kerül a helyükre.
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
Az R igen gyakori felhasználási módja a rendszertelen adatok egységes formátumra alakítása elemzéshez. Ezt segítendő többféle módon bonthatunk szöveget részstringekre. A legtöbbjük túlmutat a jelenlegi kereteken.
A str_split_1 a legegyszerűbb: egyetlen stringet alakít darabok vektorává, egy megadott minta mentén felbontva (nincs alapértelmezett minta).
s <- "R Julia Python"
str_split_1(s, " ")
#> [1] "R" "Julia" "Python"
Egyes nyelvek (főként az európaiak) megkülönböztetik a NAGY- és a kisbetűket.
A stringr függvénykészlete ezek átalakítására szolgál, a területi beállításnak megfelelő módon:
str_to_lower()str_to_upper()str_to_title() : minden szó első betűje nagybetűstr_to_sentence() : a mondat első betűje nagybetű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"
Mintára illeszkedő részstringek cseréjére a str_replace() a minta első előfordulását cseréli, a str_replace_all() pedig az összeset.
A karakterindexen alapuló részstringcseréhez a str_sub() értékadó változata használható.
s <- "abcde"
str_sub(s, 3, 4) <- "yz"
s
#> [1] "abyze"
Ebben a feladatban naplósorok feldolgozásával foglalkozsz.
Minden naplósor egy string, amelynek formátuma a következő: "[<LEVEL>]: <MESSAGE>".
Három különböző naplózási szint van:
INFOWARNINGERRORHárom részfeladatot kapsz, mindegyik kap egy naplósort, és valamit tenned kell vele.
Szabadon választhatsz, hogy a base R régi függvényeit vagy a stringr csomagot használod, mindkettővel rövid, működő megoldást kaphatsz.
Valósítsd meg a message függvényt, amely egy naplósor üzenetét adja vissza:
message("[ERROR]: Invalid operation")
#> "Invalid operation"
A sor elején és végén lévő szóközöket el kell távolítani:
message("[WARNING]: Disk almost full\r\n")
#> "Disk almost full"
Valósítsd meg a log_level függvényt, amely egy naplósor naplózási szintjét adja vissza, méghozzá csupa kisbetűvel:
log_level("[ERROR]: Invalid operation")
#> "error"
Valósítsd meg a reformat függvényt, amely újraformázza a naplósort: az üzenet kerül előre, utána pedig zárójelben a naplózási szint következik:
reformat("[INFO]: Operation completed")
#> "Operation completed (info)"
Iratkozz fel az Exercism-re, hogy megtanuld és elsajátítsd a(z) R nyelvet 21 fogalom111 feladat segítségével, valódi emberi mentorálással, mindez ingyen.