4 Podatkovni okviri i faktori


4.1 Podatkovni okviri

Kao što je već rečeno, podatkovni okvir je daleko najpopularniji element programskog jezika R. Jezik R predviđen je primarno analizi podataka, a podatkovni okvir zapravo predstavlja objektnu reprezentaciju podatkovnog skupa kojeg namjeravamo analizirati. Drugim riječima, podatkovni okvir je objekt slične funkcije kao tablica u Microsoft Excel-u ili relacijskoj bazi podataka. Gotovo svaka “sesija” u R-u svodi se na manipuliranje podatkovnim okvirima - no dok u Excel-u tablicom upravljamo uz pomoć grafičkog sučelja, a u bazi uz pomoć upitnog jezika SQL, u R-u podatkovnim okvirima upravljamo gotovo isključivo programski.

Uzmimo za primjer sljedeću tablicu:

pbr nazivMjesta prosjPlacaKn brojStanovnika prirez
10000 Zagreb 6359.00 790017 18
51000 Rijeka 5418.00 128384 15
21000 Split 5170.00 167121 10
31000 Osijek 4892.00 84104 13
20000 Dubrovnik 5348.00 28434 10

Ovdje se radi o podatkovnom skupu koji sadržava određene parametre vezane uz gradove u Republici Hrvatskoj (navedene vrijednosti ne odgovaraju nužno trenutnom stanju već ih koristimo samo za demonstraciju). Lako možemo zamisliti kako ove podatke zapisujemo u Excel ili stvaramo relacijsku tablicu naziva npr. MJESTO u koju onda pohranjujemo navedene podatke. Pokažimo sada kako bi sa istim podacima manipulirati u sklopu jezika R, tj. pokušajmo stvoriti podatkovni okvir koji će sadržavati ove podatke.


U prošloj lekciji smo napomenuli da je lista kao složeni tip zapravo svojevrsni “predložak” uz pomoć kojeg možemo raditi nove objekte. Podatkovni okvir tako zapravo nije ništa drugo nego lista – tj. “spremnik” koji može sadržavati u sebi druge spremnike podataka različitog tipa. No dok je “lista“ zapravo univerzalni spremnik, tj. nemamo ograničenja što”trpamo" u nju, podatkovni okvir ima određene restrikcije.

Najvažnije ograničenje koje podatkovni okvir nameće jest da svaki element unutar podatkovnog okvira mora imati isti broj elemenata. Zašto je tome tako? Zamislimo listu u kojoj svaki element ima isti broj podelemenata. Ako svaki element skiciramo vertikalno, sa podelementima napisanim jedan ispod drugog, onda će ti podelementi biti “poravnati” po retcima čime smo postigli klasičnu organizaciju podataka u stupce (elemente liste) i retke (poravnati podelementi). Dakle, ova restrikcija zapravo direktno nameće “tabličnu” ili “matričnu” strukturu liste sa jasno definiranim retcima i stupcima, što nam zapravo omogućuje da podatkovnim okvirom upravljamo i uz pomoć metoda vezanih uz liste, ali i uz pomoć metoda primarno namijenjenih matricama.


Postoji više načina stvaranja podatkovnih okvira, a mi ćemo prikazati dva u praksi najčešće susretana scenarija:

  • programsko stvaranje uz pomoć funkcije data.frame
  • učitavanje podataka iz vanjskog izvora uz pomoć funkcije read.csv

Prikažimo oba slučaja. Prvo ćemo stvoriti podatkovni okvir programski.


Zadatak 4.1 - programsko stvaranje podatkovnog okvira

##     pbr nazivMjesta prosjPlacaKn brojStanovnika prirez
## 1 10000      Zagreb         6359         790017     18
## 2 51000      Rijeka         5418         128384     15
## 3 21000       Split         5170         167121     10
## 4 31000      Osijek         4892          84104     13
## 5  2000   Dubrovnik         5348          28434     10

Ukoliko želite, pokušajte ponovo stvoriti gornji podatkovni okvir ali uz različite brojeve elemenata vektora koji čine stupce. Ova operacija rezultirati će greškom uz prikladnu poruku a podatkovni okvir neće biti stvoren - R se trudi da matrična priroda okvira uvijek bude očuvana.

Mala napomena glede terminologije: u nastavku ćemo zbog jednostavnosti “podatkovni okvir” često zvati jednostavno “okvir” ili “tablica”. Isto tako, često ćemo za elemente podatkovnog okvira jednakopravno koristiti izraze “stupac”, “varijabla” ili “atribut”, dok ćemo paralelne podelemente elemenata okvira nazivati “retcima” ili “obzervacijama”. Ovi termini u skladu su sa standardnim načinom referenciranja elemenata tablice te statističkim terminima koji se odnose na tablične podatkovne skupove. Ukoliko iz konteksta postoji šansa za dvosmislenost, koristiti će se onaj termin koji jasno opisuje element koji se referencira.


Pokušajmo sada učitati tablicu iz vanjskog izvora. Iako R dopušta različite oblike “vanjskih” podataka, mi ćemo pretpostaviti da podatke dobivamo u tzv. “CSV obliku” (engl. CSV - comma-separated values). Ovaj oblik jedan je od najpopularnijih načina pohrane podataka u čistom tekstualnom obliku koji ima prednosti da se lako izrađuje ručno, a većina alata za upravljanje podacima implementira i logiku za izvoz podataka u obliku CSV datoteke.

U nastavku možemo vidjeti primjer CSV datoteke koja odgovara podatkovnom okviru izrađenom u prethodnom primjeru. Pretpostavimo da se datoteka zove mjesto.csv. Podaci su odvojeni zarezom (bez razmaknice!), svaka obzervacija u svojem retku, a opcionalni prvi redak predstavlja nazive stupaca.



Jedan od potencijalnih problema sa CSV datotekama jest taj što one koriste zarez kao razdvojnik (delimiter) elemenata zapisa, a na određenim govornim područjima kao standard se umjesto decimalne točke koristi upravo “decimalni zarez”. Zbog ove činjenice postoji i “alternativni” CSV standard koji kao razdvojnik koristi “točku-zarez”, tako da bi naša CSV datoteka u tom slučaju izgledala ovako (nazovimo ju mjestoAlt.csv):



Obzirom da je “decimalni zarez” propisani standard i na području Republike Hrvatske, u radu sa CSV datotekama moramo biti oprezni koji od dva standarda zapisa se koristi. Na sreću, jezik R nudi funkcije za podršku oba standarda, tako da ne moramo posebno prilagođavati ulazne datoteke, tek biti oprezni koju funkciju ćemo odabrati.

Pretpostavimo da u radnoj mapi imamo ove dvije datoteke:

  • mjesto.csv
  • mjestoAlt.csv

Ukoliko nemamo dostupne ove datoteke lako ih možemo samostalno napraviti uz pomoć običnog uređivača teksta (npr. Notepad ili gedit) i kopiranja gore navedenih redaka.


Za stvaranje podatkovnih okvira iz CSV datoteka koristimo funkcije: - read.csv - za “normalne” CSV datoteke sa zarezom kao razdvojnikom - read.csv2 - za alternativni CSV standard koji koristi točku-zarez

Osnovni parametar ovih funkcija je staza do CSV datoteke koju učitavamo. Funkcije imaju i bogati niz dodatnih parametara koje omogućuju prilagodbu raznim scenarijima, a ukoliko smo dobili neki od “egzotičnijih” oblika CSV datoteke, isplati se pogledati i funkciju read.table koja je vrlo fleksibilna glede broja različitih parametara i postavki kod učitavanja podataka (read.csv i read.csv2 su zapravo izvedene iz funkcije read.table fiksiranjem određenih parametara na standardne CSV značajke).


Neke od parametara i pripadajućih vrijednosti funkcija read.csv (ili read.table) koje je korisno znati su:

  • header = FALSE - za datoteke bez zaglavlja
  • sep = "#" - za datoteke koje koriste “egzotični” razdvojnik, u ovom slučaju #
  • na.strings = "NULL" - naznaka koji standard podaci koriste za reprezentaciju nedostajućih vrijednosti a koji će u R-u postati NA
  • nrows = 2000 - maksimalan broj redaka koji će se pročitati, u ovom slučaju 2000
  • stringsAsFactors = F - sprječavanje automatskog stvaranja faktorskih stupaca (o kojima ćemo učiti u nastavku ove lekcije)
  • encoding = "UTF-8" - za standarde kodiranja teksta koji nisu ASCII (osobito bitno ako radimo sa podacima sa hrvatskog govornog područja koji koriste dijakritičke znakove)

Pokušajmo sada učitati podatke iz dostupnih CSV datoteka. Ovi podaci neće zahtijevati posebne parametre te će se moći učitati samo pružanjem staze do pripadnih datoteka (jedne koja koristi zarez i druge koja koristi točku-zarez kao razdvojnik).


Zadatak 4.2 - čitanje podataka iz CSV datoteke

##     pbr nazivMjesta prosjPlacaKn brojStanovnika prirez
## 1 10000      Zagreb         6359         790017     18
## 2 51000      Rijeka         5418         128384     15
## 3 21000       Split         5170         167121     10
## 4 31000      Osijek         4892          84104     13
## 5 20000   Dubrovnik         5348          28434     10
## -----------
##     pbr nazivMjesta prosjPlacaKn brojStanovnika prirez
## 1 10000      Zagreb         6359         790017     18
## 2 51000      Rijeka         5418         128384     15
## 3 21000       Split         5170         167121     10
## 4 31000      Osijek         4892          84104     13
## 5 20000   Dubrovnik         5348          28434     10

Pogledajmo sada neke korisne funkcije za rad sa podatkovnim okvirima tj. tablicama. Dobar dio njih će nam već otprije biti poznat iz iskustva u radu sa listama i matricama:

  • nrow - broj redaka
  • ncol ili length - broj stupaca (budući da se okvir ponaša i kao matrica i kao lista)
  • dim - dimenzije tablice
  • names - imena stupaca
  • head - ispis nekoliko redaka s početka tablice
  • tail - ispis nekoliko redaka s kraja tablice
  • str - ispis strukture tablice
  • summary - sažete statističke informacije o stupcima tablice

Isprobajmo neke od ovih funkcija:


Zadatak 4.3 - funkcije za rad sa podatkovnim okvirima

## [1] 5 5
## -----------
## 'data.frame':    5 obs. of  5 variables:
##  $ pbr           : num  10000 51000 21000 31000 2000
##  $ nazivMjesta   : Factor w/ 5 levels "Dubrovnik","Osijek",..: 5 3 4 2 1
##  $ prosjPlacaKn  : num  6359 5418 5170 4892 5348
##  $ brojStanovnika: num  790017 128384 167121 84104 28434
##  $ prirez        : num  18 15 10 13 10
## -----------
##     pbr nazivMjesta prosjPlacaKn brojStanovnika prirez
## 1 10000      Zagreb         6359         790017     18
## 2 51000      Rijeka         5418         128384     15
## 3 21000       Split         5170         167121     10
## 4 31000      Osijek         4892          84104     13
## 5  2000   Dubrovnik         5348          28434     10
## -----------
##       pbr           nazivMjesta  prosjPlacaKn  brojStanovnika  
##  Min.   : 2000   Dubrovnik:1    Min.   :4892   Min.   : 28434  
##  1st Qu.:10000   Osijek   :1    1st Qu.:5170   1st Qu.: 84104  
##  Median :21000   Rijeka   :1    Median :5348   Median :128384  
##  Mean   :23000   Split    :1    Mean   :5437   Mean   :239612  
##  3rd Qu.:31000   Zagreb   :1    3rd Qu.:5418   3rd Qu.:167121  
##  Max.   :51000                  Max.   :6359   Max.   :790017  
##      prirez    
##  Min.   :10.0  
##  1st Qu.:10.0  
##  Median :13.0  
##  Mean   :13.2  
##  3rd Qu.:15.0  
##  Max.   :18.0

4.2 Odabir redaka i stupaca podatkovnih okvira

Već smo rekli da se podatkovni okviri ponašaju i kao matrice i kao liste, što je svojstvo kojim se posebno često služimo kod odabira redaka i stupaca podatkovnih okvira. Konkretno, za “rezanje” okvira najčešće koristimo:

  • dvodimenzionalno referenciranje uz pomoć indeksnih vektora
  • odabir pojedinog stupca uz pomoć operatora $

Ovdje smo zapravo dosta fleksibilni - možemo npr. prvo “izrezati” određene retke matrice uz pomoć lokacijskog referenciranja i potom izdvojiti samo jedan stupac uz pomoć operatora $. U praksi je jedna od najčešćih kombinacija uvjetni odabir redaka uz imenski odabir stupaca (poznavatelji SQL-a prepoznati će ovo kao standardnu kombinaciju WHERE uvjeta i SELECT liste).

Pokušajmo primijeniti naše znanje o indeksnim vektorima, matricama i listama na rezanje podatkovnih okvira.


Zadatak 4.4 - rezanje podatkovnih okvira

##     pbr nazivMjesta prosjPlacaKn brojStanovnika prirez
## 1 10000      Zagreb         6359         790017     18
## 2 51000      Rijeka         5418         128384     15
## 3 21000       Split         5170         167121     10
## 4 31000      Osijek         4892          84104     13
## 5  2000   Dubrovnik         5348          28434     10
## -----------
##   prosjPlacaKn prirez
## 1         6359     18
## 2         5418     15
## 3         5170     10
## -----------
## [1] 18 15 10 13 10
## -----------
##     pbr nazivMjesta
## 1 10000      Zagreb
## 2 51000      Rijeka

Uočite sličnost između zadnjeg izraza i SQL upita: `

Odabir stupaca i redaka nije težak ako dobro baratamo znanjem o indeksnim vektorima, no kao što se vidi u zadnjem primjeru sintaksa često nije previše čitljiva (u usporedbi sa npr. SQL-ovom sintaksom koja obavlja isti posao). Zbog toga postoje različita proširenja R-a koji ovaj posao uvelike olakšavaju, a koja ćemo detaljno obraditi u jednoj od budućih lekcija koja će se baviti upravljanjem podatkovnim skupovima.


4.3 Dodavanje i brisanje redaka i stupaca

Za dodavanje i brisanje redaka i stupaca opet se dovoljno sjetiti da je podatkovni okvir svojevrsni hibrid matrice i liste tj. ako znamo dodavati retke i stupce u matricu ili nove elemente u listu onda ekvivalentnim načinom možemo podatke dodavati i u podatkovni okvir. U radu sa podatkovnim okvirima nešto češće dodajemo nove stupce (obično kao transformacije postojećih stupaca) nego retke tako da možemo primjere započeti sa dodavanjem stupaca.

Kao što je rečeno, stupce u podatkovni okvir dodajemo na isti način kao što dodajemo elemente liste - uz pažnju da dodani stupac ima isti broj elemenata kao i ostali stupci. Novi stupci često su izvedenice postojećih stupaca koje predstavljaju binarne indikatore, rezultate aritmetičkih izraza podataka u drugim stupcima i sl.


Zadatak 4.5 - dodavanje novih stupaca u tablicu


Retke i stupce smo također mogli dodati slično dodavanju redaka i stupaca u matricu - uz pomoć funkcija rbind i cbind. Kod funkcije rbind obično dodajemo novi podatkovni okvir sa retcima koji imaju odgovarajući redoslijed i vrstu elemenata, dok kod funkcije cbind možemo dodati i obični vektor no moramo paziti da broj elemenata odgovara broju redaka originalnog okvira.

Isprobajmo ove funkcije na malim “umjetnim” podatkovnim okvirima kako bi lakše predočili njihovu funkcionalnost.


Zadatak 4.6 - funkcije rbind/cbind i podatkovni okviri


Za brisanje redaka i stupaca također se možemo koristiti istim metodama za upravljanje matricama i listama. Konkretno:

  • brisanje redaka i stupaca možemo obaviti dvodimenzionalnim referenciranjem redaka i stupaca koje želimo “zadržati”
  • brisanje stupaca možemo obaviti pridjeljivanjem vrijednosti NULL odabranom stupcu

Isprobajmo ovo na primjeru.


Zadatak 4.7 - brisanje redaka i stupaca


Podatkovnim okvirima ćemo se nastaviti baviti u poglavlju o upravljanju podatkovnim skupovima, gdje ćemo naučiti kako raditi sa okvirima sa daleko više podataka od primjera koje smo koristili u ovoj lekciji, te kako raditi sa dodatnim paketima koji značajno olakšavaju česte radnje nad podacima u podatkovnim okvirima. U nastavku ćemo se pozabaviti još jednim novim (i ponešto kontroverznim) tipom podatkovne strukture.


4.4 Faktori

Faktor u R-u je zapravo tip podataka koji predstavlja ono onoga što se u statistici naziva nominalnom ili kategorijskom varijablom. Naime, atribut neke obzervacije često poprima neku vrijednost iz skupa otprije poznatih kategorija (npr. varijabla spola, dobne kategorije, obrazovanja, mjesta rođenja, stranačke preferencije i sl.). Kategorije se često identificiraju jedinstvenim nizom znakova, a u procesu analize uz pomoć njih često provodimo razna agregiranja i grupacije (npr. u nekoj utrci možemo gledati prosječno vrijeme ovisno o spolu ili dobnoj kategoriji) ili pak dijelimo skup podataka ovisno o kategorijskoj pripadnosti.

Faktori u R-u su često i predmet rasprava budući da se radi o konstruktu koji može olakšati rad nad podacima, ali i uzrokovati brojne probleme, pogotovo ako nismo svjesni da u nekom trenutku radimo sa faktorom (ovaj scenarij se zapravo vrlo lako izbjegava, što ćemo objasniti na kraju ovog poglavlja).


Za početak ćemo predočiti što su zapravo faktori uz pomoć jednostavnog primjera. Zamislimo da sljedeći znakovni vektor opisuje razinu krvnog tlaka kod deset pacijenata:

Ovo je očito “kategorijska” varijabla budući da može poprimiti jednu od tri diskretne vrijednosti - "nizak", "normalan" i "visok". Prema tome, ovaj vektor je tipičan kandidat za “faktoriziranje”, tj. za pretvorbu u objekt klase factor. Faktorizaciju znakovnog vektora provodimo uz pomoć funkcije factor kojoj prosljeđujemo (u pravilu) znakovni vektor kao parametar.


Zadatak 4.8 - faktoriziranje znakovnog vektora

##  [1] "nizak"    "visok"    "visok"    "normalan" "normalan" "nizak"   
##  [7] "visok"    "nizak"    "normalan" "normalan"
## [1] "character"
## -----------
##  [1] nizak    visok    visok    normalan normalan nizak    visok   
##  [8] nizak    normalan normalan
## Levels: nizak normalan visok
## [1] "factor"

Vidimo da je ispis faktora dobio dodatni atribut Levels. To znači da se sada ovdje radi o “pravoj” kategorijskoj varijabli sa točno definiranim kategorijama koje smije poprimiti. Ako pokušamo dodati novu vrijednost u faktor koja nije zastupljena u trenutnim kategorijama (npr. “prenizak”) dobiti ćemo upozorenje, a umjesto kategorije koju smo naveli nova stavka imati će vrijednost NA.

Ovo ponekad nije scenarij kojeg priželjkujemo. Ukoliko unaprijed znamo da znakovni vektor kojeg kategoriziramo ne sadrži sve moguće kategorije koje se općenito mogu pojaviti, imamo opciju dodavanja parametra levels u kojem ćemo uz pomoć znakovnog vektora eksplicitno navesti niz “mogućih” kategorija.


Zadatak 4.9 - nezastupljene kategorije i parametar levels

## Warning in `[<-.factor`(`*tmp*`, 11, value = "prenizak"): invalid factor
## level, NA generated
##  [1] nizak    visok    visok    normalan normalan nizak    visok   
##  [8] nizak    normalan normalan <NA>    
## Levels: nizak normalan visok
## -----------
##  [1] nizak    visok    visok    normalan normalan nizak    visok   
##  [8] nizak    normalan normalan prenizak
## Levels: prenizak nizak normalan visok previsok

Koja je prednost faktora? Zašto varijable ne bismo ostavili u originalnom, “znakovnom” obliku? Razlog potrebe za faktoriziranjem kategorijskih stupaca tj. varijabli je poglavito u tome što određene statističke i vizualizacijske funkcije “znaju” na ispravan način interpretirati i koristiti faktore te ih tretiraju drugačije od običnih “znakovnih” stupaca. Zbog toga je vrlo dobra dugoročna strategija već u početku učenja R-a naviknuti se da kod rada sa podatkovnim okvirima faktoriziramo stupce koji su zaista kategorijske varijable (ali također i pripazimo da nemamo faktorizirane stupce koji nisu kategorijske varijable, što se može događati ako nismo pažljivi).

Jedno od pitanja koje se često pitamo vezano uz kategorijske varijable jest - kolika je zastupljenost pojedinih kategorija? Odgovor na ovo pitanje daje nam funkcija table kojoj prosljeđujemo odabrani faktor.


Zadatak 4.10 - funkcija table

## tlak.f2
## prenizak    nizak normalan    visok previsok 
##        1        3        4        3        0

Funkcija table ne zahtijeva nužno faktor i uredno će raditi čak i sa znakovnim vektorom. No u tom slučaju ne bismo dobili informaciju o kategorijama koje nisu uopće zastupljene.


Kategorijska varijabla iz naših primjera zapravo ima prirodu tzv. ordinalne kategorijske varijable, što znači da kategorije imaju prirodni poredak (nizak tlak je “manji” od normalnog koji je “manji” od visokog). Ukoliko želimo, ovu činjenicu možemo “ugraditi” u faktor kod njegove inicijalizacije, jednostavnim dodavanjem parametra ordered postavljenog na TRUE. Prednost ordinalnog faktora jest ta što nam omogućuje usporedbu vrijednosti faktora uz pomoć usporednih operatora.


Zadatak 4.11 - ordinalni faktor


Već smo uvidjeli da je u R-u zapravo “sve vektor” - brojevi su jednodimenzionalni numerički vektori, matrice su vektori sa dodanim parametrom dimenzionalnosti, liste su vektori malih listi, podatkovni okviri su liste za dodanom restrikcijom. Možemo se zapitati - što su zapravo faktori?

Implementacijski, faktor je zapravo kodirani ili enumerirani skup vrijednosti inicijalno definiranih znakovnih nizova, uz pridruženu kodnu tablicu istih. Jednostavnije rečeno, faktorizacija znakovnog vektora uključuje:

  • “popisivanje” svih uočenih kategorija (ili preuzimanje eksplicitnog popisa iz parametra levels)
  • pridjeljivanje numeričkih vrijednosti redom svakoj kategoriji (npr: "nizak" -> 1, "normalan" -> 2 itd.)
  • “pakiranje” novostvorenog numeričkog vektora i pripadajuće “kodne tablice”

Iako ove korake R radi automatski, u internu strukturu faktora možemo se uvjeriti ako faktor probamo pretvoriti u čisti numerički, odnosno čisti znakovni tip.


Zadatak 4.12 - interna struktura faktora

##  [1] "nizak"    "visok"    "visok"    "normalan" "normalan" "nizak"   
##  [7] "visok"    "nizak"    "normalan" "normalan"
##  [1] 2 4 4 3 3 2 4 2 3 3

Pretvaranjem faktora u znakovni tip zapravo radimo operaciju inverznu faktoriziranju, tj. dobijamo originalni znakovni vektor. S druge strane pretvaranjem faktora u numerički tip zapravo dobivamo “prekodirane” brojke koje faktor interno koristi za reprezentaciju kategorija. Možemo se zapitati - zašto bi nam ovo bilo korisno? Odgovor je - ne, od ovog u praksi nema neke direktne koristi. Zapravo je ovo nešto što nam može stvoriti vrlo velike probleme ako to unaprijed ne očekujemo.

Ovdje se krije već prije navedena “kontroverza” oko faktora kao tipa podataka. Ona zapravo uopće nije povezana sa samim faktorima, već sa nekim nazivnim postavkama R-a i njegovim funkcijama učitavanja podataka iz vanjske datoteke. Navedimo sada detaljne korake koji se odvijaju tijekom stvaranja podatkovnog okvira iz datoteke i pokušajmo zaključiti gdje nastaje potencijalni problem:

  1. R otvara CSV datoteku
  2. na osnovu pročitanih podataka R pokušava zaključiti kojeg je tipa koji stupac
  3. svi znakovni stupci se automatski faktoriziraju osim ako nije naveden parametar stringsAsFactors - FALSE
  4. Formira se konačni podatkovni okvir

Vidimo li mogući problem? Pretpostavimo sljedeći scenarij: u jednom numeričkom stupcu potkrala se nenumerička vrijednost (npr. niz znakova NULL zbog nedostajućih vrijednosti iz baze). Ovo može biti samo jedna vrijednost od više milijuna redaka, no to je dovoljno da R klasificira stupac kao “znakovni”. Budući da R automatski faktorizira znakovne stupce, u konačnom podatkovnom okviru taj numerički stupac postaje kategorijski (iako su nazivi kategorija zapravo brojevi). Nepažljivi analitičar (ili automatska skripta) ne uočava da se radi o faktoru već provodi konverziju navedenog stupca u numerički tip - i dobija potpuno semantički besmisleni niz “prekodiranih” cijelih brojeva koji, ako nisu pravovremeno uočeni, mogu biti korišteni kao ulazni podaci za daljnje analize.



Zadatak 4.13 - važnost parametra stringsAsFactors = F

##     pbr nazivMjesta prosjPlacaKn brojStanovnika prirez
## 1 10000      Zagreb      6359.00         790017     18
## 2 51000      Rijeka         NULL         128384     15
## 3 21000       Split      5170.00         167121     10
## 4 31000      Osijek      4892.00          84104     13
## 5 20000   Dubrovnik      5348.00          28434     10

Ponovimo - kako izbjeći ovaj scenarij? Procedura je vrlo jednostavna:

  • kod korištenja funkcija read.csv ili read.table uvijek koristiti parametar stringsAsFactors = FALSE
  • pažljivo pregledati tipove podataka stupaca učitanog okvira
  • provesti odgovarajuće konverzije stupaca
  • provjeriti dobivene rezultate

Ako se pridržavamo ovih koraka gotovo nikada nećemo doći u situaciju da nam faktori prave probleme. Postoje i alternativne procedure (npr. eksplicitno navođenje tipova stupaca kod čitanja iz datoteke uz pomoć parametara colClasses, ili korištenje sintagme as.numeric(as.character()) za pretvaranje stupaca u numerički tip koja će provesti ispravnu konverziju neovisno o tome radi li se o znakovnom stupcu ili “prikrivenom” faktoru), no gore navedeni koraci bi u većini slučajeva trebali biti potpuno dovoljni. Najvažnija stvar za zapamtiti jest ključna uloga parametra stringsAsFactors = FALSE (koja se u literaturi zna navoditi kao obavezni parametar, bez dodatnih objašnjenja).


Zadaci za vježbu

  1. U mapi zajedno sa ovom bilježnicom pronađite datoteku mjestoNOHEADER.csv koja predstavlja datoteku istovjetnu datoteci mjesto.csv osim sljedećih značajki:
  • nedostaju imena stupaca
  • korišten je razmak kao razdvojnik

Pokušajte uz pomoć dokumentacije učitati podatke iz ove datoteke u varijablu mjestoNH koja će biti istovjetna varijabli mjesto korištenoj u lekciji.

  1. U mapi zajedno sa ovom bilježnicom pronađite datoteku racun.csv i učitajte ju u varijablu racun. Pripazite da nizovi znakova nisu automatski pretvoreni u faktore. Ispišite na zaslon:
  • broj redaka ove tablice
  • broj stupaca tablice
  • imena stupaca tablice
  1. Za tablicu racun napravite sljedeće:
  • faktorizirajte stupac katArtikl
  • ispišite šifru, naziv i cijenu svih artikala kategorije “slatkisi i grickalice” jeftinijih od 12 Kn
  • ispišite koliko proizvoda koje kategorije se nalazi u računu
  • dodajte stupac ukupno koji će sadržavati ukupnu cijenu pojedine stavke uračunavajući i cijenu i količinu
  • izračunajte ukupni iznos računa

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/