LAB 02 - 1.10.2014 Pokracujeme v praci s viacrozmernymi datami "cars" z minuleho tyzdna. Cielom je vytvorit vizualizaciu typu "timeline", zobrazujucu niekolko premennych naraz tak aby sa dali vidiet trendy v case. Pripravil som pre Vas pociatocne kroky, Vasou ulohou bude ich rozvinut dalej. Pripravena je ukazka konstrukcie jednoduchej linearnej casovej osi a grafickych prvkov nad nou. Nasleduje idea spiralovitej casovej osi, s ktorou budete mat za ulohu dalej pracovat a vytvorit vlastnu vizualizaciu. Mozete napriklad menit podla dat hrubku a farbu spiraly, umiestnovat nu body roznej velkosti alebo doplnit ju obrazkami ilustrujucimi trendy v datach. Zmente kod smerom k vyssej estetickej urovni, pouzite lepsiu paletu farieb a podobne. Vysledky prace zaslite e-mailom vyucujucemu, budu hodnotene bodovo. Ulohy, ktore splnia minimalne parametre budu zoradene podla celkoveho dojmu, kvality a narocnosti dodatocnych zmien a ohodnotene 2 bodmi (dolnych 50%) alebo 3 bodmi (hornych 50%). V pripade minimalnych uprav oproti verzii v cviceni moze dolnych 20% ziskat len 1 bod. Ak Vam budu pri praci chybat nejake balicky v R, mali by ste byt schopni si ich nainstalovat prikazom install.packages()". Budu instalovane vo Vasom domovskom adresari. Pokial nemate uchovanu historiu z minuleho tyzdna: cardata <- read.table("cars.data") names(cardata) <- c("mpg","cylinders","displacement","horsepower","weight","acceleration","model.year","origin") carnames <- read.table("cars.names") names(carnames) <- c("name") cars <- data.frame(c(carnames,cardata)) Naucite sa pouzivat graficke prikazy z balika grid. Pracu z jeho funkciami vykonavame vzdy v ramci nejakej podoblasti zobrazovacej plochy - tzv. viewport, ktory ma vlastnu velkost, orientaciu a suradnicovy system. Tieto podoblasti sa aktivuju prikazom pushViewport() a deaktivuju popViewport(), po ktorom nastane navrat do predchadzajucej nadradenej podoblasti. Vytvorime si oblast s okrajmi: library(grid) grid.newpage() pushViewport(plotViewport()) V nom si vytvorime podoblast pre data od roku 1969 do 1983 pushViewport(viewport(xscale=c(1969,1983))) years <- c(1969:1983) Vykreslime body pre jednotlive roky, kazdy desiaty vyraznejsie grid.circle(years,0,0.15,default.units="native",gp=gpar(fill="red")) syears <- years[which(years/10 == floor(years/10))] grid.circle(syears,0,0.25,default.units="native",gp=gpar(fill="blue")) Popiseme modre body rokmi grid.text(syears,syears,-0.1,default.units="native",rot=90,gp=gpar(fontsize=14,fontface="bold")) Aby sme mohli opakovat rozne vizualizacie s tou istou casovou osou, ulozime si predchadzajuce prikazy ako funkciu initTimeline() initTimeline <- function(years){ ... } Vytvorime farebnu plochu, ktora bude znazornovat spotrebu aut v danom roku Najprv ale potrebujeme funkciu, ktora spocita pocet aut pre dany rok countCars <- function(year){ length(which(cars$model.year == year-1900)) } Vyskusajte, ci funguje: countCars(1971) vysledok by mal byt 29. Vyborne! podobna funkcia nam spocita priemerny pocet valcov pre dany rok countCylinders <- function(year){ mean(cars$cylinders[which(cars$model.year == year-1900)]) } countCylinders(1971) Je vysledok 5.517241? a priemernu spotrebu countMpg <- function (year) { if(countCars(year)>0){ mean(cars$mpg[which(cars$model.year == year-1900)],na.rm=TRUE) } else { 0 } } Mozeme zobrazit oblast podla poctu aut v danom roku grid.polygon(years,mapply(countMpg,years)/100+0.05,default.units="native",gp=gpar(fill="grey")) Nad nou zobrazime prislusny pocet valcov tak, aby sa zdoraznilo, ze jedna klesa zatial co druha stupa. Potrebujeme funkciu drawCyl() drawCyl <- function(){ grid.rect(x=0.5,y=0.7,width=0.8,height=0.6,gp=gpar(fill="brown")) grid.rect(x=0.5,y=0.9,width=0.8,height=0.08,gp=gpar(fill="brown")) grid.rect(x=0.5,y=0.3,width=0.1,height=0.2,gp=gpar(fill="brown")) grid.circle(0.5,0.1,0.2,gp=gpar(fill="grey")) } ... a mozeme zacat vykreslovat, viewport vzdy nastavime na spravne miesto pomocou x= a y= drawSymbols <- function(year){ n <- round(countCylinders(year)) for(i in 1:n){ pushViewport(viewport(x=year,y=1.0-i*0.075,width=0.5,height=0.06,default.units="native")) drawCyl() popViewport() } } Funkcia mapply aplikuje funkciu drawSymbols na vsetky prvky vektora (roky) mapply(drawSymbols,c(1970:1982)) Pokuste sa dokoncit nasledovne vyobrazenie casovych trendov, kde casova os je vytvorena vo forme spiraly: Prevod roka na polohu na spirale v suradnicovej sustave: time2pos <- function (time,size=50,spacing=30,density=7.3) { dif <- (time-1950)/density angle <- 2*pi*dif n <- floor(dif) x <- sin(angle) y <- cos(angle) as.table(trunc(size*c(x,y) * angle*spacing/2/pi)) } Suradnice pre jednotlive roky ulozime do d: d <- data.frame(years,t(mapply(time2pos,years))) Funkcia spiralplot vykresli roky v spirale na plochu: spiralplot <- function (years) { d <- data.frame(years,t(mapply(time2pos,years))) plot(d[,2:3],type="b", col=c("yellow","orange","red","brown","black")) text(d[,2:3]+500,labels=d[,1], col=c("yellow","orange","red","brown","black")) } S pouzitim grafickych primitiv balicka grid mame k dispozicii krajsie graficke prvky: newspiralplot <- function (years) { d <- data.frame(years,t(mapply(time2pos,years))) grid.newpage() pushViewport(plotViewport(xscale=c(-3000,3000),yscale=c(-3000,3000))) pushViewport(dataViewport(d[,2],d[,3])) grid.circle(d[,2],d[,3],100,default.units="native",gp=gpar(fill="red")) grid.text(d[,1],d[,2],d[,3],default.units="native",just=c("left","bottom")) grid.xspline(d[,2],d[,3],default.units="native",shape=-0.8,open=TRUE) } Funkcia, ktora sa moze hodit pri zobrazovani vykresli obrazok vo formate GIF na lubovolne miesto suradnicoveho systemu library(pixmap) f1 <- read.pnm("car_f1.pnm") show(f1) plot(f1) Cvicny obrazok najdete medzi datami v ISe. Ine obrazky je potrebne do formatu pnm konvertovat pomocou programov balika ImageMagick plotImage <- function (image,xpos,ypos,size) { require(pixmap) require(RGraphics) require(colorspace) imagemat <- getChannels(image,colors="all") pushViewport(viewport(x=xpos,y=ypos,width=size,height=0.65*size,default.units="native")) grid.imageFun(130,200,byrow=FALSE,t(hex(RGB(as.vector(imagemat[,,1]),as.vector(imagemat[,,2]),as.vector(imagemat[,,3]))))) popViewport() } plotImage(f1,100,100,100)