Matemaatika ja statistika instituut
Logi sisse
  • English
  • Kursused
  • 2026/27 sügis
  • Rakendustarkvara: R (LTMS.00.016)

Rakendustarkvara: R 2026/27 sügis

  • Pealeht
  • Praktikum 1
  • Praktikum 2
  • Praktikum 3
  • Praktikum 4
  • Praktikum 5
  • Praktikum 6
  • Praktikum 7
  • Praktikum 8
  • Praktikum 9
  • Projekt

Praktikum 8

Praktikumi kood: praktikum8_kood.r.

Sõnetöötlus paketiga stringr

R- i baaspaketiga on kaasas mitmeid sõnede töötlemise käske, näiteks grep(.) ja substr(.); pikemat loetelu näeb, kui trükkida konsooli ?grep ja ?substr. Olenevalt olukorrast võivad baaspaketi käskude tulemused olla kohati soovimatud, niisiis tutvume ka stringr paketiga ja võrdleme selle käskude tulemusi baaspaketi omadega. Antud praktikumis on paketi stringr käskude ette lisatud stringr::, et oleks lihtsam eristada paketti kuuluvaid käske (seetõttu pole antud praktikumis ka vajalik paketti aktiveerida pärast installeerimist).

#install.packages("stringr") #  kui paketti arvutis veel pole
#library(stringr) # paketi aktiveerimine

Sõne pikkus, sõnede kokkukleepimine ja eraldamine, alamsõne eraldamine

  • Sõnede pikkust saab teada käsuga nchar(.) või stringr::str_length(.).
  • Sõnesid saab kokku kleepida üheks käsuga paste(.) või stringr::str_c(.), mõlema puhul saab argumendiga sep määrata, milline sümbol pannakse kokkukleebitavate sõnede vahele. Kui anda argumendi collapse väärtuseks mingi sümbol, siis kleebitakse kõik sõned üheks ainsaks sõneks, mis on selle sümboliga eraldatud. Baaspaketi paste(.) puhul koheldakse puuduvaid väärtuseid NA kui sõnesid, stringr::str_c(.) käsitleb neid siiski puuduvate väärtustena ja seetõttu on ka kleepimise tulemuseks puuduv väärtus.
  • Sõne saab tükeldada käsuga strsplit(.) või stringr::str_split(.). Mõlema käsu teise argumendiga (baaspaketi puhul split, stringr puhul pattern) saab määrata, mis on tükkide eraldaja, kui see on tühi sõne (nt split = ""), tükeldatakse sõna üksikuteks tähtedeks. Mõlema käsu tulemusena tekib list , mida saab vektoriks muuta käsuga unlist(.). Kui aga lisada käsku stringr::str_split(.) argument simplify = TRUE on tulemuseks maatriks.
  • Alamsõne eraldamiseks on käsud substr(.) või stringr::str_sub(.), mille teise ja kolmanda argumendiga (mõlemal juhul on teine argument start, baaspaketis on kolmas stop ja stringr-s end) saab määrata alamsõne alguse ja lõpu indeksid. Andes käsus stringr::str_sub(.) neile argumentidele negatiivsed indeksi väärtused alustatakse loendamist sõne lõpust st indeks -2 märgib sõne eelviimast kohta (baaspaketi puhul see nii ei ole).
sõnad <- c("Õun", "Apelsin", "Porrulauk", NA, "")
nchar(sõnad)
stringr::str_length(sõnad)
## [1]  3  7  9 NA  0
paste(sõnad, 1:5, sep="=")
stringr::str_c(sõnad, 1:5, sep = "=")
## [1] "Õun=1"       "Apelsin=2"   "Porrulauk=3" "NA=4"        "=5"
## [1] "Õun=1"       "Apelsin=2"   "Porrulauk=3" NA            "=5"
(x = paste(sõnad, 1:5, sep = "=", collapse = ". "))
## [1] NA
(x <- stringr::str_c(sõnad, 1:5, sep = "=", collapse = ". "))
(x <- stringr::str_c(stringr::str_replace_na(sõnad), 1:5,
                     sep = "=", collapse = ". "))
## [1] "Õun=1. Apelsin=2. Porrulauk=3. NA=4. =5"
strsplit(x, split = ". ")
stringr::str_split(x, pattern = ". ")
## [[1]]
## [1] "Õun=1"       "Apelsin=2"   "Porrulauk=3" "NA=4"        "=5"
unlist(strsplit(x, ". "))
## [1] "Õun=1"       "Apelsin=2"   "Porrulauk=3" "NA=4"        "=5"
strsplit(sõnad, "")
stringr::str_split(sõnad, "")
## [[1]]
## [1] "Õ" "u" "n"
## 
## [[2]]
## [1] "A" "p" "e" "l" "s" "i" "n"
## 
## [[3]]
## [1] "P" "o" "r" "r" "u" "l" "a" "u" "k"
## 
## [[4]]
## [1] NA
## 
## [[5]]
## character(0)
unlist(strsplit(sõnad, ""))
##  [1] "Õ" "u" "n" "A" "p" "e" "l" "s" "i" "n" "P" "o" "r" "r" "u" "l" "a" "u" "k" NA
lause1 <- "see ja teine ja kolmas ja neljas"; lause2 <- "üks või kaks või kolm"
strsplit(c(lause1, lause2), c("ja", "või"))
stringr::str_split(c(lause1, lause2), c("ja", "või"))
## [[1]]
## [1] "see "     " teine "  " kolmas " " nel"     "s"       
## 
## [[2]]
## [1] "üks "   " kaks " " kolm"
substr(sõnad, 1:5, 3:7)
stringr::str_sub(sõnad, 1:5, 3:7)
## [1] "Õun" "pel" "rru" NA    ""
substr(sõnad, start = 1, stop = nchar(sõnad)-2)
stringr::str_sub(sõnad, end = -3)
## [1] "Õ"       "Apels"   "Porrula" NA        ""

Ülesanded

Loe sisse Massatchusettsi andmestik:

link <- "https://courses.ms.ut.ee/LTMS.00.016/2026_fall/uploads/Main/"
mass <- read.table(str_c(link, "mass.txt"), sep = "\t", header = T)
  1. Andmetabelis on veerus OCCP iga inimese amet, sealjuures kolme esimese tähega on kodeeritud vastav valdkond; näiteks kõik puhastusteenustega seotud ametid algavad tähtedega CLN. Mitu erinevat valdkonda on selles andmetabelis?
  2. Kasutades sama tunnnust (OCCP) lisa andmestikku uus veerg OCCP1, mille väärtused oleks samad kui OCCP-l, kuid töötutel oleks tunnuse väärtus kujul '"UNE-UNEMPLOYED, LAST WORKED 5 YEARS AGO OR EARLIER OR NEVER".

Alamsõne otsimine ja muutmine

Et teada saada, kas üks sõne sisaldub teises sõnes, saab kasutada käske grepl(.) või stringr::str_detect(.). Sisaldumiste esinemiste kokkuloendamiseks sobib käsk stringr::str_count(.). Juhul, kui on soov otsitava alamsõne teksti kujul leida ja väljastada, saab kasutada käsku stringr::str_extract(.). Et teada saada, millisel positsioonil asub otsitav alamsõne, võiks kasutada käsku stringr::str_locate(.), mis tagastab kõige esimesel positsioonil leitud alamsõne (kui sellist alamsõne üldse leidub) algus- ja lõpuindeksid matrix-tüüpi objektina. Kui tahame kätte saada kõigil positsioonidel olevate alamsõnede algus- ja lõpuindeksid, sobib käsk stringr::str_locate_all(.), mis tagastab listi. Samaväärseid tulemusi on võimalik ka R-i baaspaketi käskudega saavutada, kuid mõnikord võib see olla üsna vaevarikas. Järgnevatele stringr-i käskudele on võrdluseks lisatud ka sarnase tulemusega baaspaketi käskude tulemused.

# Vaatame üle oma vektori
sõnad
## [1] "Õun"       "Apelsin"   "Porrulauk" NA          ""
stringr::str_detect(sõnad, "r")
#grepl("r", sõnad)
## [1] FALSE FALSE  TRUE    NA FALSE
stringr::str_count(sõnad, "r")
#lengths(regmatches(sõnad, gregexpr("r", sõnad)))
## [1]  0  0  2 NA  0
stringr::str_extract(sõnad, "r")
#regmatches(sõnad, regexec("r", sõnad))
## [1] NA  NA  "r" NA  NA
stringr::str_extract_all(sõnad, "r")
#regmatches(sõnad, gregexpr("r", sõnad))
## [[1]]
## character(0)
## 
## [[2]]
## character(0)
## 
## [[3]]
## [1] "r" "r"
## 
## [[4]]
## [1] NA
## 
## [[5]]
## character(0)
stringr::str_locate(sõnad, "r")
#regexpr("r", sõnad)
##      start end
## [1,]    NA  NA
## [2,]    NA  NA
## [3,]     3   3
## [4,]    NA  NA
## [5,]    NA  NA
stringr::str_locate_all(sõnad, "r")
#gregexpr("r", sõnad)
## [[1]]
##      start end
## 
## [[2]]
##      start end
## 
## [[3]]
##      start end
## [1,]     3   3
## [2,]     4   4
## 
## [[4]]
##      start end
## [1,]    NA  NA
## 
## [[5]]
##      start end

Mõnikord on sõnede alguses või lõpus liiga palju tühikuid, neid saab eemaldada käsuga trimws(.) või stringr::str_trim(.). Käsuga stringr::str_pad(.) aga saab sõne algusesse või lõppu panna tühikuid (või muid sümboleid) juurde, nii et sõne saavutaks argumendiga width ette antud pikkuse. Sarnase tulemuse saaks ka format(.) ja gsub(.) käske kasutades, kuid järgnev lihtne variant ei töötaks kui muudetavas sõnes esineks tühikuid mida me sooviks alles jätta.

trimws(" siin on palju tühjust ")
stringr::str_trim(" siin on palju tühjust ")

format(sõnad, 9, justify = "centre", na.encode = F) |> gsub(" ", "_", x = _)
stringr::str_pad(sõnad, width = 9, side = "both", pad = "_")
## [1] "siin on palju tühjust"
## [1] "___Õun___" "_Apelsin_" "Porrulauk" NA          "_________"

Kõige üldisemad sõnede muutmise käsud on sub(.) ja stringr::str_replace(.), mis proovivad argumendiga pattern ette antud ja leitud mustrit asendada argumendiga replacement määratud mustriga; asendatakse ainult esimene leidumine. Kõiki leidumisi saab asendada käskudega gsub(.) või stringr::str_replace_all(.)

sub("r", "l", sõnad)
stringr::str_replace(sõnad, "r", "l")

gsub("r", "l", sõnad)
stringr::str_replace_all(sõnad, "r", "l")
## [1] "Õun"       "Apelsin"   "Polrulauk" NA          ""         
## [1] "Õun"       "Apelsin"   "Pollulauk" NA          ""

Kõigile stringr paketi käskudele võib argumentidega pattern ja replacement ette anda ka regulaaravaldisi1.

Ülesanded

link <- "https://courses.ms.ut.ee/LTMS.00.016/2026_fall/uploads/Main/"
mass <- read.table(str_c(link, "mass.txt"), sep = "\t", header = T)
  1. Massatchusettsi andmestikus on veerus COW ära toodud, kelle heaks inimene töötab. Kui tegemist on palgatöötajaga, sisaldab COW väärtus vastava inimese puhul sõna Employee või employee. Milline on palgatöötajate keskmine palk (WAGP)?
  2. Eesti isikukoodi formaat2 on järgmine: abcdefghijk, kus a - sugu ja sajand (paaritu arv mees, paarisarv naine, 1,2 - 1800, 3,4 - 1900, 5,6 - 2000); bc - aasta, de - kuu, fg - päev, hij - (haigla) sel päeval (selles haiglas) sündimise järjekord, k - kontrollnumber.
    • Loe sisse komaga eraldatud isikukoodide jada: isikukoodid <- read.table(paste0(link, "isikukoodid.txt"))[1,]
    • Eralda isikukoodid üksteisest ja salvesta tekkiv vektor mingi nimega.
    • Tekita uus andmetabel (data.frame), millesse lisa isikukoodide veerg.
    • Lisa veerg, kus oleks kirjas, mis sugu iga inimene selles andmetabelis on.

Kuupäevadega töötamine

R-is on kuupäevade jaoks Date andmetüüp. See on omapärane andmetüüp: näiliselt on tegemist tekstiga, ent sisuliselt arvuga - kuupäevi saab liita-lahutada, arvutada keskmist. ISO standardile vastav kuupäev on kujul aasta-kuu-päev, sealjuures aasta on nelja numbriga, kuu ja päev kumbki kahe numbriga. Sageli on sisse loetavates andmestikes aga kuupäev teisiti vormindatud. Suvalises formaadis kuupäevalise sõna saab Date-tüüpi väärtuseks teisendada käsuga as.Date(.), mille argumendiga format saab määrata, millises formaadis kuupäev ette antakse. Kui formaati ei ole käsus täpsustatud, siis proovib funktsioon esmalt formaadi "%Y-%m-%d" ehk aasta-kuu-päev (2018-02-01), seejärel "%Y/%m/%d" ehk aasta/kuu/päev (2018/03/01) sobivust, kui kumbki ei klapi antakse veateade.

d1 <- as.Date("22.04.2009", "%d.%m.%Y")
d2 <- as.Date("30.04.2009", "%d.%m.%Y")
d2 - d1
## Time difference of 8 days
as.numeric(d2 - d1)
## [1] 8

Näites kasutatud formaadi tähiste %d, mis tähendab päeva numbrit, %m mis näitab kuu numbrit, %Y mis tähistab neljakohalist aastanumbrit ja teiste formaadi võimaluste kohta saab täpsemalt lugeda käsu strptime(.) abifailist ?strptime.

Kuupäevaks formaaditud objektidega saab teha kõiki mõistlikke operatsioone, näiteks leida miinimum, keskmine, võrrelda hulki:

d3 <- Sys.Date()
paevad <- c(d1, d2, d3)
mean(paevad)
## [1] "2013-06-14"
d2 %in% paevad
## [1] TRUE

Küll aga ei saa näiteks leida kuupäevast logaritmi või ruutjuurt.Põhjus on selles, et R talletab kuupäevi tegelikult päevade arvuna alates nullpunktist, sealjuures nullpunktiks loetakse vaikimisi 1970-01-01. Selles võime veenduda as.numeric(.) käsku kasutades.

d1:d2
## [1] 14356 14357 14358 14359 14360 14361 14362 14363 14364
as.numeric(as.Date("1970-01-02"))
## [1] 1
as.numeric(as.Date("1969-12-30"))
## [1] -2

Date-tüüpi muutuja väärtuse saab sobival kujul sõneks teisendada käsuga format(.), see võimaldab kombineerida teksti ja kuupäeva elemente:

format(Sys.Date(), "Kuupäev: %d. %B, (aastal %Y). Nädal nr %V.")

Ülesanded

Vaatame edasi isikukoodide vektori (isikukoodid eelmisest ülesandest) põhjal tekitatud isikute info andmestikku.

  1. Lisa isikute andmestikku veerg, mis sisaldaks iga inimese sünnikuupäeva Date-tüüpi muutujana.
  2. Lisa veerg, mis annab inimese vanuse täisaastates tänasel päeval (arvestades, et aastas on ~365,25 päeva).
  3. Leia kuupäev, mil said/saad 10 000 päeva vanuseks.
  4. Kuupäevadega töötamiseks saab kasutada ka lisapaketi lubridate funktsioone. Vaata infot lehelt lubridate.

  1. Regulaaravaldiste Vikipeedia leht
  2. Isikukoodi Vikipeedia leht
  • Matemaatika ja statistika instituut
  • Loodus- ja täppisteaduste valdkond
  • Tartu Ülikool
Tehniliste probleemide või küsimuste korral kirjuta:

Kursuse sisu ja korralduslike küsimustega pöörduge kursuse korraldajate poole.