10 Rad sa datumima i znakovnim nizovima


10.1 Rad sa datumima

Upravljanje datumima i vremenskim oznakama uvijek predstavlja izazov kod rada sa podatkovnim skupovima budući da moramo voditi računa o stvarima kao što su:

  • različiti oblici prikaza datuma i vremena
  • različite interne reprezentacije
  • različite vremenske zone
  • razlika između matematičkog i kalendarskog poimanja vremenskih perioda

Jedan od češće korištenih standarda je tzv “unix vrijeme” (ili “POSIX vrijeme”) koja vrijeme računa kao broj sekundi protekao od ponoći 1. siječnja 1970. UTC (Coordinated Universal Time). Ne koriste svi informacijski sustavi POSIX vrijeme; npr. Microsoft Excel ima svoj format gdje broji dane od 1.1.1900., a onda za određeni dan broj sati, minuta i sekundi protekao od ponoći.

Programski jezik R ima tri klase za upravljanje datumima / vremenskim oznakama:

  • Date za prikaz datuma
  • POSIXct za kompaktni prikaz vremenske oznake
  • POSIXlt za “dugi” prikaz vremenske oznake (u obliku liste)

10.1.1 Klasa Date

Klasu Date koristimo kada nas zanima datum ali ne i vrijeme neke obzervacije ili poslovnog događaja. Ova klasa nema svoj konstruktor, već objekte ovog tipa (najčešće) stvaramo uz pomoć sljedećih funkcija:

  • Sys.Date() koja vraća današnji datum
  • as.Date() kojoj kao parametar prosljeđujemo znakovni niz koji reprezentira datum

Funkcija as.Date() po default-u prihvaća datume oblika %Y-%m-%d, gdje %Y predstavlja četveroznamenkastu godinu a %m i %d dvoznamenkasti mjesec i dan. Ukoliko želimo interpretirati datum koji je zapisan u nekom drugom obliku onda moramo funkciji dodati parametar format koji će parametarski opisati oblik kojeg koristimo (npr. za 28/10/1978 bi vrijednost parametra format trebala biti %d/%m/%Y). Sve moguće oblikovne specifikacije mogu se pogledati uz pomoć naredbe ?strptime iako, kao što ćemo se uvjeriti kasnije, jednostavnija metoda jest koristiti se funkcijama paketa lubridate.


Zadatak 10.1 - klasa Date


Sa datumima možemo raditi jednostavne računske operacije kao što je dodavanje i oduzimanje dana (koristimo operatore + i - i cijele brojeve) ili razliku u danima između dva datuma (operator -).


Zadatak 10.2 - aritmetika s datumima


Zadnji izraz će zapravo rezultirati objektom klase difftime koja označava vremenski interval. Ispis koristi tzv. “automatski” odabir jedinice (konkretno, parametar units postavljen na "auto") koji će pokušati odabrati najprikladniju vremensku jedinicu za ispis. Ukoliko želimo eksplicitno odabrati koju vremensku jedinicu želimo (sekunde, minute, sate, dane ili tjedne) onda možemo umjesto operatora - koristiti funkciju difftime uz parametar units postavljen na znakovni niz odabrane vremenski jedinice ("seconds", "minutes", itd.).


Zadatak 10.3 - funkcija difftime


Funkcija difftime zapravo radi i sa vremenskim oznakama, tj. ne moramo nužno raditi na razini datuma, već se možemo spustiti do razine sekunde. Ovo ćemo isprobati kada naučimo klasu POSIXct u nastavku. Isto tako, ako nam treba samo broj (sekundi, sati, dana i sl.), lako transformiramo izlaz u cijeli broj uz pomoć funkcije as.numeric.

Jezik R implementira i posebnu varijantu funkcije seq za rad sa datumima koja ima sljedeći potpis:

Parametri ove funkcije su sljedeći:

  • from - početni datum (obvezni parametar)
  • to - konačni datum
  • by - korak sekvence u danima ili znakovni niz tipa "7 days", "2 weeks" i sl. (za sve mogućnosti pogledati dokumentaciju!)
  • length.out - duljina sekvence
  • along.with - vektor čiju duljinu uzimamo za referencu

Isprobajmo ovu funkciju.


Zadatak 10.4 - funkcija seq i datumi

##  [1] "2010-01-01" "2010-07-01" "2011-01-01" "2011-07-01" "2012-01-01"
##  [6] "2012-07-01" "2013-01-01" "2013-07-01" "2014-01-01" "2014-07-01"
## [11] "2015-01-01" "2015-07-01" "2016-01-01" "2016-07-01" "2017-01-01"
## [16] "2017-07-01" "2018-01-01" "2018-07-01" "2019-01-01" "2019-07-01"
## [21] "2020-01-01" "2020-07-01" "2021-01-01" "2021-07-01" "2022-01-01"
## [26] "2022-07-01" "2023-01-01" "2023-07-01" "2024-01-01" "2024-07-01"
## [31] "2025-01-01" "2025-07-01" "2026-01-01" "2026-07-01" "2027-01-01"
## [36] "2027-07-01" "2028-01-01" "2028-07-01" "2029-01-01" "2029-07-01"
## [41] "2030-01-01"
##    broj_stana prezime   ciscenje
## 1           1   Ebert 2020-01-21
## 2           2 Ladovac 2020-02-11
## 3           3   Ceric 2020-03-03
## 4           4   Dikla 2020-03-24
## 5           5    Anic 2020-04-14
## 6           6   Peric 2020-05-05
## 7           7   Žužic 2020-05-26
## 8           8   Babic 2020-06-16
## 9           9    Ibiz 2020-07-07
## 10         10  Radler 2020-07-28

10.1.2 Klase POSIXct i POSIXlt

Klasa POSIXct nam je pogodna kada nam nije dosta samo pohraniti datum, već moramo znati i točno vrijeme za neku obzervaciju ili poslovni događaj. Objekt ove klase najčešće stvaramo uz pomoć sljedećih funkcija:

  • Sys.time() koja vraća trenutnu vremensku oznaku uzimajući u obzir postavljenu vremensku zonu
  • as.POSIXct() kojoj kao parametar prosljeđujemo znakovni niz koji predstavlja datum i vrijeme

Funkcija as.POSIXct() kao parametar očekuje vremensku oznaku tipa %Y-%m-%d %H:%M:%S gdje su prve tri oblikovne specifikacije istovjetne već poznatoj specifikaciji datuma, dok %H, %M i %S predstavljaju dvoznamenkaste sate, minute i sekunde (gleda se 24-satni oblik prikaza vremena). Za parsiranje drugih oblika vremenskih oznaka potrebno je - kao i kod klase Date - dodati parametar format sa oblikovnom specifikacijom kako intepretirati zadani znakovni niz. Opet, za popis svih parametara nam pomaže poziv ?strptime, iako je u praksi poželjna opcija za lakši rad proučiti paket lubridate kojeg ćemo raditi kasnije. Funkciji as.POSIXct možemo dodati i parametar tz postavljen na znakovni niz koji definira vremensku zonu.


Zadatak 10.5 - klasa POSIXct


Imena vremenskih zona su standardizirana (tzv. “Olsonove vremenske zone”) a dohvaćaju se uz pomoć operativnog sustava a možemo ih ispisati uz pomoć funkcije OlsonNames(). Trenutnu vremensku zonu platforme možemo ispisati uz pomoć funkcije Sys.timezone().


Zadatak 10.6 - vremenske zone

## [1] "Europe/Warsaw"
##  [1] "Pacific/Kosrae"       "America/Havana"       "Asia/Aqtau"          
##  [4] "Africa/Timbuktu"      "Israel"               "America/Campo_Grande"
##  [7] "Asia/Hong_Kong"       "Pacific/Johnston"     "Asia/Tashkent"       
## [10] "Etc/GMT-2"

Vremenske oznake također mogu koristiti operatore + i - uz cjelobrojne vrijednosti kao drugi operand pri čemu se od vremenske oznake oduzimaju ili dodaju sekunde. Isto tako, možemo oduzimati dvije vremenske oznake kako bi dobili razliku u sekundama, ili koristiti funkciju difftime sa odabranom vrijednosti vremenske jedinice.


Zadatak 10.7 - aritmetika sa vremenskim oznakama


Klasa POSIXlt se ponaša isto kao i POSIXct (za stvaranje se koristimo funkcijom as.POSIXlt), no zapravo se radi o listi koja nam omogućuje jednostavno izvlačenje određenih parametara iz vremenske oznake, kao što su broj sekundi, broj minuta, dan u tjednu i sl. Sve elemente liste lako možemo vidjeti ako napravimo POSIXlt objekt i onda pozovemo funkciju unclass nad njim, pri čemu će se on pretvoriti u “običnu” listu. Možemo ići i korak dalje - ako listu ubacimo u funkciju unlist, kao rezultat dobivamo obični znakovni vektor.


Zadatak 10.8 - klasa POSIXlt


10.1.3 Paket lubridate

Iako jezik R ima relativno dobru podršku za rad sa datumima i vremenskim oznakama, upravljanje istima možemo učiniti znatno učinkovitijim uz paket lubridate. Ukoliko analiziramo podatke gdje je vremenska komponenta jako bitna, ili upravljamo podatkovnim skupovima koji koriste različite oblike zapisa datuma i vremenskih oznaka, onda si proces analize uvelike olakšavamo i ubrzavamo korištenjem funkcija iz ovog paketa.

Jedna od stvari koja je možda najkorisnija programerima koji ne vole pisati oblikovne specifikacije za parsiranje datuma je porodica funkcija za parsiranje datuma čija imena odgovaraju okvirnom izgledu zapisa kojeg želimo parsirati. Npr. funkcija imena ymd zna parsirati znakovne nizove u kojima je datum zapisan redoslijedom godina-mjesec-dan. Funkcija je dovoljno “pametna” da sama interpretira pojedinosti oko zapisa, kao što su delimiteri, znakovna polja i sl. Ukoliko zapis ima drugi raspored dana, mjeseca i godine, potrebno je samo adekvatno razmjestiti slova u nazivu funkcije.


Zadatak 10.9 - funkcije paketa lubridate za parsiranje datuma


Navedeni koncept može se koristiti i za vremenske oznake, samo imenu funkcije dodamo podcrtu i “specifikaciju” sati, minuta i sekundi (npr. ymd_hms).


Zadatak 10.10 - funkcije paketa lubridate za parsiranje vremenskih oznaka


Uočimo da ove funkcije uvijek za vremensku zonu postavljaju UTC. Ovo je namjerno napravljeno s ciljem da se motivira korištenje jedinstvene vremenske zone u podatkovnom skupu kojeg analiziramo. Ukoliko želimo, tijekom parsiranja možemo postaviti vremensku zonu uz pomoć parametra tz. Isto tako, kod već inicijaliziranih vremenskih oznaka možemo upravljati vremenskim zonama uz pomoć sljedećih funkcija

  • force_tz - “nameće” novu vremensku zonu tj. ostavlja iste vrijednosti vremenske oznake ali postavlja vremensku zonu koju definiramo
  • with_tz - provodi transformaciju vremenske oznake u onu koja odgovara traženoj vremenskoj zoni
## [1] "2016-11-29 10:05:17 EST"
## [1] "2016-11-29 10:05:17 CET"
## [1] "2016-11-29 16:05:17 CET"

Paket lubridate također uvelike olakšava izvlačenje segmenata datuma i vremena iz vremenskih oznaka uz pomoć funkcija kao što su year, week, month i sl. Uz pomoć istih funkcija možemo lako i izmijeniti neku od komponenti vremena.


Zadatak 10.11 - izvlacenje elemenata vremenskih oznaka


Za potpuni popis funkcija pogledajte dokumentaciju paketa lubridate.

Za trenutni datum i vrijeme lubridate nudi alternative funkcijama Sys.Date() i Sys.time() koje se jednostavno zovu today() i now().


Zadatak 10.12 - funkcije today i now


Već smo rekli da upravljanje vremenskom komponentom u podacima može postati vrlo kompleksno, pogotovo ako uzmemo u obzir da vremenski intervali mogu biti zadani generički (npr. “2 godine”) ili konkretno (raspon između dva datuma) te da se matematički i kalendarski način računanja vremena često ne poklapaju (npr. “za godinu dana” može značiti točan matematički izračun sekundi u 365 dana, ili kalendarski “isti datum iduće godine”).

Paket lubridate definira četiri mogućnosti kod definiranja vremena i vremenskih intervala:

  • trenutak (instant) - vremenska oznaka zaokružena na sekundu
  • trajanje (duration) - “generički” definiran interval u sekundama
  • period - slično trajanju, ali omogućuje definiranje trajanja koja matematički ne traju uvijek isto (npr. “3 mjeseca”)
  • interval - vrijeme omeđeno između dva točno određena trenutka

Trenutke smo već upoznali, to su vremenske oznake koje smo do sada stvarali. Za stvaranje trajanja i perioda imamo intuitivno definirane funkcije koje se nazivaju po engleskim nazivima za vremenske jedinice, pri čemu trajanja imaju dodano slovo d kao prefiks (od duration). Tako imamo funkcije minutes i dminutes, hours i dhours, weeks i dweeks i sl. (uočite da ne postoji funkcija dmonths, budući da “mjesec dana” ne možemo jednoznačno pretvoriti u sekunde!).


Zadatak 10.13 - trajanja i periodi


Uočite da gornji izraz nismo lako mogli dobiti “matematički”.

Konačno, interval stvaramo uz pomoć funkcije interval kojoj dajemo početni i konačni trenutak, ili uz pomoć funkcije as.interval kojoj dajemo trajanje/period i početni trenutak. Možemo također koristiti i operator %--% sa dvije vremenske oznake (tj. trenutka) kao operandima.


Zadatak 10.14 - intervali


Kod intervala je zgodno što između ostalog možemo:

  • provjeriti da li se neki trenutak nalazi unutar nekog intervala uz pomoć operatora %within%
  • provjeriti da li se intervali preklapaju uz pomoć funkcije int_overlaps()
  • lako dohvatiti početak i kraj intervala uz pomoć funkcija int_start() i int_end
  • “spojiti” dva intervala uz pomoć funkcije union ili naći presjek uz pomoć funkcije intersect
  • brojne druge mogućnosti koje možemo naučiti gledajući dokumentaciju

Zadatak 10.15 - pomoćne funkcije za rad sa intervalima


U ovom dijelu upoznali smo se sa jednim dijelom funkcionalnosti koje nude klase za upravljanje datumima i vremenskim oznakama jezika R te paket lubridate. Za dodatne informacije pogledajte službenu dokumentaciju jezika R i paketa lubridate, a dobar izvor je i članak “Dates and Times Made Easy with lubridate” kojeg je napisao sam autor paketa Hadley Wickham a koji je dostupan na ovoj poveznici.

10.2 Rad sa znakovnim nizovima

R ima jako dobru podršku za rad sa znakovnim nizovima, no funkcije koje nudi osnovni R nisu intuitivne niti konzistentne ako ih uspoređujemo sa sličnim funkcijama u drugim programskim jezicima.

Upravo iz ovih razloga pojavio se paket stringr koji nudi vrlo učinkovitu alternativu postojećim funkcijama vezanih uz znakovne nizove te predstavlja jedan od najpopularnijih “dodatnih” R paketa. No prije upoznavanja sa funkcijama koje nudi ovaj paket potrebno je kratko se osvrnuti na općenitu problematiku upravljanja znakovnim nizovima u analizi podataka te na tehnologiju bez koje je provedba analize znakovnih nizova gotovo nezamisliva - tzv. regularni izrazi.

10.2.1 Analiza teksta i regularni izrazi

Analiza teksta neizbježan je element kod analize podatkovnih skupova. Bilo da se radi o jednostavnoj identifikaciji kategorija, traženju podnizova ili nečem daleko složenijem kao što su specijalizirane metode rudarenja teksta (engl. text mining), teško je zamisliti bilo kakvu smislenu analizu podataka koja prije ili kasnije ne zahtijeva poznavanje barem osnovnih metoda analize znakovnih nizova.

Neovisno o razini složenosti analize znakovnih nizova koju želimo provesti, jedna tehnologija je sveprisutna i univerzalno primjenjiva - regularni izrazi. Ovdje se radi o posebnom jeziku uz pomoć kojeg definiramo “uzorke” (patterns) na osnovu kojih pretražujemo neki tekst, radimo izmjene i sl.

Detaljni pregled tehnologije regularnih izraza izlazi iz okvira ovog udžbenika. U nastavku ćemo navesti samo kratke informacije u svrhu brzog pregleda ili podsjetnika. Ukoliko se do sada uopće niste susretali s ovom tehnologijom, snažno preporučujemo ulaganje truda i svladavanje barem osnovnih koncepata, npr. uz pomoć nekog od dostupnih internetskih. Jedan od vrlo kratkih ali učinkovitih mini-tečajeva regularnih izraza možete naći ovdje .

Regularni izraz jednostavno je niz znakova koji predstavlja uzorak kojeg tražimo unutar nekog teksta. Npr. regularni izraz gram se nalazi u znakovnom nizu Programski jezik R ali se ne nalazi u znakovnom nizu Analiza teksta. Kažemo da smo pronašli “slaganje” (match) regularnog izraza sa prvim nizom ali ne i sa drugim.

Ovakav regularni izraz nije previše fleksibilan - prava moć regularnih izraza krije se u mogućnosti slaganja posebnih izraza koji će se uz pomoć posebnog opisa moći slagati sa “općenitijim” oblicima znakovnih nizova. Tipičan primjer je adresa elektroničke pošte - konkretnije, provjera da li je korisnik unio adresu koja odgovara “općenitom” obliku adrese elektroničke pošte. Jedno od mogućnosti je jednostavno izraz @ kojim zapravo samo provjeravamo postojanje tog znaka u danom znakovnom nizu. Time smo osigurali određenu razinu kontrole, ali isto tako smo dopustili “adrese” tipa @@@ i @23456. Uz malo “rada” na izrazu mogli bi doći do malo boljeg rješenja, koje npr. može izgledati ovako:

Iako izgleda kao niz nasumičnih znakova, osnovnim poznavanjem regularnih izraza možemo relativno lako interpretirati gornji izraz. Znak \w označava “slovo ili znamenku”, znak + znači “1 ili više” i sl. Ako bi htjeli “prepričati” gornji regularni izraz govornim jezikom, to bi bilo “jedno ili više slova ili znamenki, potom znak @, pa jedno ili više slova ili znamenki, zatim točka i onda konačno opet jedno ili više slova ili znamenki”. Iako ovo nije pretjerano sofisticirani izraz, on je ipak kvalitetniji od prvog pokušaja. Daljnje proširenje je itekako moguće i iako naknadnim dodavanjima sve više gubimo neposrednu čitljivost, isto tako postižemo sve višu i višu razinu kontrole koja se približava formalnim odrednicama kako adresa elektroničke pošte mora izgledati (za ovakve specifične uporabe često se isplati i provjeriti javno dostupne repozitorije regularnih izraza gdje možemo naći složene ali kvalitetne i pomno testirane izraze koje je dovoljno jednostavno prekopirati u naš programski kod).

Važno je napomenuti da nema jednog jedinstvenog standarda za regularne izraze. Postoji tzv. “POSIX standard” u dvije inačice - BRE i ERE (Basic Regular Expressions i Extended Regular Expressions) koje su zapravo gotovo iste, osim što BRE zahtjeva malo intenzivniju uporabu znaka \. Još jedan popularni standard je tzv. “Perl standard” koji predstavlja inačicu regularnih izraza implementiranih u jeziku Perl. Budući da je Perl jedan od vodećih jezika za upravljanje tekstom tako je i ovaj standard postao jedan od najšire prihvaćenih načina korištenja regularnih izraza.

U općenitom slučaju, gotovo svi popularniji programski jezici imaju podršku za regularne izraze, bilo već ugrađene u jezik, bilo uz pomoć dodatnih paketa. R je jedan od jezika koji već sadrži podršku za regularne izraze u svojem osnovnom paketu. Štoviše, R ima ugrađenu paralelnu podršku za tri najraširenija standarda - POSIX ERE, POSIX BRE i Perl. POSIX ERE je zadana postavka, a određenim parametrima možemo se lako “prebaciti” na BRE (extended = FALSE) ili Perl (perl = TRUE). U daljnjim poglavljima držati ćemo se ERE standarda, ali bitno je znati i za prethodno navedene postavke želimo li koristiti već gotove izraze koji su razvijeni u nekom drugom standardu (a ne želimo se zamarati sa prebacivanjem iz jednog standarda u drugi).

Sljedeća tablica daje kratki pregled nekih češće korištenih elemenata regularnih izraza u jeziku R:

Element Značenje
abcd niz slova “abcd”
1234 niz znamenki “1234”
\\d ili [:digit:] ili [0-9] bilo koja znamenka
\\D ili [:alpha:] ili [A-Za-z] bilo koje slovo
[:alnum:] bilo koje slovo ili znamenka
. bilo koji znak
\\. točka
[abc] samo navedeni znakovi
[^abc] svi znakovi osim navedenih
* nula ili više ponavljanja
+ jedno ili više ponavljanja
{n} točno n ponavljanja
{m, n} najmanje m, najviše n ponavljanja
? opcionalni znak
[:space:] ili \\s bilo kakva praznina
[:punct:] znakovi interpunkcije
^...$ oznaka za početak i kraj
(ab|cd) niz “ab” ili niz “cd”

Uočite da kod korištenja specijalnog znaka \ zapravo moramo koristiti “dvostruki znak” \\ (prvi put da naznačimo R-u da se radi o specijalnom znaku, drugi put da ga doslovno upotrijebimo kao dio regularnog izraza).

Osnovne funkcije jezika R za rad sa znakovnim nizovima (a time i regularnim izrazima) su između ostalog grep, grepl, regexrp, gregexrp, regmatches, sub, gsub itd. No budući da paket stringr nudi skup alternativnih funkcija sa gotovo istim funkcionalnostima ali uz daleko intuitivnija imena i konzistentnije potpise, mi ćemo se usredotočiti na upravo te funkcije a učenje osnovnih ostavljamo čitateljima koji žele upotpuniti svoje znanje učenjem svih dostupnih alata koje nudi jezik R.

10.2.2 Paket stringr

Već smo rekli da paket stringr zapravo u izvjesnoj mjeri reimplementira već postojeće funkcije jezika R, ali na intuitivniji i konzistentniji način. Ako želimo biti precizni, funkcije paketa stringr su zapravo funkcionalno nešto skromnije, no to je napravljeno s konkretnom namjerom - funkcionalnost je reducirana na poslove za koje se smatra da predstavljaju daleko najčešće korištene funkcionalnosti kod analize teksta. Funkcionalnost koja je “izbačena” tiče se specifičnih slučajeva za koje će programer morati potražiti alternativna rješenja (često u obliku osnovnih funkcija), no dobitak je u jednostavnijim, intuitivnijim funkcijama koje su lakše za učenje i učinkovito dugoročno korištenje.

Pored navedenih “popravljanja” paket stringr omogućuje i sljedeće:

  • konzistentno tretiranje faktora kao znakovnih nizova
  • lakše korištenje izlaza funkcija za ulaz nastupajuće funkcije, što je pogotovo korisno uz operator %>%

Možemo početi sa nekim jednostavnijim funkcijama za koje ne trebamo regularne izraze (navodimo pojednostavljene potpise funkcija, za potpune pogledajte dokumentaciju):

  • str_c(string1, string2, ...) - spajanje znakovnih nizova, alternativa funkciji paste0
  • str_length(string) - vraća duljinu znakovnog niza
  • str_sub(string, start, end) - vraća podniz
  • str_sub(string, start, end) <- string2 - umetanje novog podniza (ne mora biti iste duljine kao izbačeni podniz!)
  • str_trim(string) - uklanjanje praznina s početka i kraja niza

Zadatak 10.16 - osnovne funkcije za rad sa znakovnim nizovima


Funkcija str_c ima i parametar sep za dodavanje separatora, te parametar collapse za spajanje elemenata znakovnog vektora u jedinstveni niz uz vrijednost parametra kao separator.


Zadatak 10.17 - spajanje znakovnih nizova


Pogledajmo sada neke funkcije koje rade sa regularnim izrazima:

  • str_detect(string, pattern) - vraća TRUE ako niz sadrži uzorak, inače FALSE
  • str_extract(string, pattern) - vraća niz znakova koji odgovara prvoj pojavi uzorka
  • str_extract_all(string, pattern) - vraća listu sa svim pojavama koje odgovaraju uzorku
  • str_replace(string, pattern, replacement) - mijenja prvu pojavu uzorka sa zadanim novim nizom
  • str_replace_all(string, pattern, replacement) - mijenja sve pojave uzorka sa zadanim novim nizom

Sve ove funkcije su vektorizirane, tj. ponašaju se logično (tj. “paralelizirano”) kad im kao određeni parametar pošaljemo vektor - npr. ako funkciji str_replace pošaljemo vektor znakovnih nizova i vektor “zamjena”, svaka prva pojava uzorka biti će zamijenjena odgovarajućim elementom u poretku zamjena. Za detalje oko ovakvog proširenog korištenja uputno je pogledati dokumentaciju.


Zadatak 10.18 - funkcije i regularni izrazi


Konačno, naučimo jednu relativno korisnu funkciju nazvanu str_split. Ova funkcija rastavlja znakovni niz na vektor znakovnih nizova, ovisno o danom separatoru (koji može biti razmak, neki odabrani znak ali i regularni izraz), a često se koristi kao “primitivnija” alternativa funkcijama read.csv i read.table kada ulazne podatke želimo “ručno” rastaviti i parsirati, ili za analizu teksta kada paragrafe teksta “razbijamo” na pojedinačne riječi. Ova funkcija pretpostavlja da ćemo joj proslijediti niz znakovnih nizova za rastavljanje te nam kao rezultat vraća listu; ukoliko rastavljamo samo jedan niz, lako rezultat pretvaramo u vektor korištenjem funkcije unlist.

## [1] "Primjer"   "funkcije"  "str_split"

Pokažimo sada jedan vrlo jednostavni primjer analize teksta. Izračunati ćemo frekvenciju pojave različitih u riječi u sljedećem paragrafu teksta. Za potrebe ovog zadatka morati ćemo pročitati podatke iz tekstualne datoteke. Jedan od najjednostavnijih načina kako ovo možemo učiniti jest kombinacija funkcija file (koja otvara konekciju prema tekstualnoj datoteci, slično načinu upravljanja datotekama u C-u) i readLines koja čita određeni broj redaka iz datoteke i sprema ih u znakovni vektor. Ako je datoteka dovoljno mala da sve retke možemo čitati odjednom, onda ove dvije funkcije možemo pozvati ovako:

Sljedeći zadatak koristiti će dvije tekstualne datoteke

  • HobbitChapterOne.txt - datoteka čiji tekst analiziramo i
  • stopwords.txt - datoteka sa čestim riječima koje “nisu vrijedne” za analizu koju ćemo izvesti

Zadatak 10.19 - jednostavna analiza teksta


Zadaci za vježbu

Sljedeći zadaci odnose se na podatkovni skup pohranjen u CSV datoteci crimeSample.csv a koji predstavlja uzorak iz evidencije kriminalnih incidenata u gradu Philadelphiji (originalni podatkovni skup može se naći na ovoj poveznici). Originalni skup stupaca je reduciran a iz skupa svih obzervacija slučajnim odabirom uzorkovano je 1000 incidenata.

Prije rješavanja zadataka učitajte podatke u podatkovni okvir crimes i upoznajte se s podatkovnim skupom (str, head, itd.)

  1. Pretvorite stupac sa vremenskom oznakom iz znakovnog tipa u POSIXct tip.

  2. Podatkovnom okviru dodajte sljedeće stupce: Year, Month, Hour. Stupce popunite odgovarajućim informacijama iz vremenske oznake. Odgovorite na pitanje: u kojem mjesecu se događa najviše zločina? Koji sat u danu je prema podacima “najopasniji”?

  3. Odgovorite na pitanje: koliki je postotak incidenata gdje opis incidenta sadrži riječ "burglary" ili "robbery"? (savjet: pretvorite cijeli stupac sa opisom zločina u mala slova uz pomoć funkcije tolower()).

  4. Ispišite na zaslon sve jedinstvene četveroznamenkaste brojeve koje možete naći u nazivima ulica u kojima je evidentiran kriminalni incident.


Creative Commons License
Programirajmo u R-u by Damir Pintar is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.
Based on a work at https://ratnip.github.io/FER_OPJR/