Prilagođavanje izgleda

Sada ćemo se pozabaviti time kako da prilagodimo izgled najvažnijih komponenata grafika. Kada sve sklopimo, dobijemo poprilično sveobuhvatnu listu kako detaljno izvršiti sve zadatke prilagođavanja.

Počnimo sa scatterplot-om Population u odnosu na Area iz midwest baze. Boja i veličina tačaka variraju u zavisnosti od state(kategorička promenljiva) i popdensity (neprekidna promenljiva) kolona, redom.

Donji grafik ima lepo podešene osnovne komponente kao što su naslov, oznake osa i legenda. Ali kako da im promenimo izgled?

Većina zahteva vezanih za izgled može se postići korišćenjem funkcije theme(). Ona ima veliki broj argumenata. (Ukucajte ?theme u konzolu i uverite se i sami).

options(scipen=999)
data("midwest", package = "ggplot2")
theme_set(theme_bw())

# dodajemo komponente grafika
gg = ggplot(midwest, aes(x=area, y=poptotal)) + 
  geom_point(aes(col=state, size=popdensity)) + 
  geom_smooth(method="loess", se=F) + xlim(c(0, 0.1)) + ylim(c(0, 500000)) + 
  labs(title="Area Vs Population", y="Population", x="Area", caption="Source: midwest")

# crtamo grafik 
plot(gg)

Argumenti koji su prosleđeni komponentama theme() funkcije moraju biti podešeni korišćenjem specijalnih element_type() funkcija. Postoje četiri glavna tipa:

U narednoj diskusiji ćemo razmotriti ove slučajeve. Razmotrimo niz zadataka vezanih za promenu izlaznog grafika, počevsi od modifikacije teksta naslova i osi.

Naslov grafika i imena osa

Naslov grafika i imena osa, kao i oznake na osama su deo teme grafika. Zbog toga se oni mogu menjati korišćenjem funkcije theme(). Funkcija theme() prihvata jednu od četiri element_type() funkcija navedenu kao argument. Pošto su naslov grafika i imena osa tekstualne komponente, za njihovu modifikaciju se koristi element_text().

Menjamo boju, izgled, poravnanje, itd. Oznake na osama se mogu rotirati promenom ugla:

gg = ggplot(midwest, aes(x=area, y=poptotal)) + 
  geom_point(aes(col=state, size=popdensity)) + 
  geom_smooth(method="loess", se=F) + xlim(c(0, 0.1)) + ylim(c(0, 500000)) + 
  labs(title="Area Vs Population", y="Population", x="Area", caption="Source: midwest")

# prilagodjavamo komponente teme
gg + theme(plot.title=element_text(size=20, 
                                    face="bold", 
                                    family="American Typewriter",
                                    color="tomato",
                                    hjust=0.5,
                                    lineheight=1.2),  # naslov
            plot.caption=element_text(size=15),  # caption
            axis.title.x=element_text(vjust=10,  
                                      size=15),  # naziv x ose
            axis.title.y=element_text(size=15),  # naziv y ose
            axis.text.x=element_text(size=10, 
                                     angle = 30,
                                     vjust=.5),  # oznake x ose
            axis.text.y=element_text(size=10))  # oznake y ose

  • vjust podešava vertikalni razmak između naslova (ili oznake) i grafika.

  • hjust podešava horizontalni razmak. Postavljanjem na 0.5 centrira naslov.

  • family se koristi za postavljanje novog fonta.

  • face postavlja izgled fonta (“plain”, “italic”, “bold”, “bold.italic”).

Gore navedeni primeri pokrivaju neke od često korišćenih modifikacija tema, ali stvarna lista je predugačka. Dakle, ?theme je prvo mesto koje gledamo ako želimo da menjamo izgled bilo koje komponente.

Podešavanja legende

Kad god je geom našeg grafika (tačke, linije, pravougaonici, itd.) podešen da menja estetiku (boju, veličinu, boju punjenja, oblik, itd.) na osnovu kolone, kao npr. u geom_point(aes(col = state, size = popdensity)) legenda se crta automatski.

Ako kreiramo geom gde je estetika fiksna, legenda se ne crta automatski. U takvim slučajevima, moguće je ručno kreirati sopstvenu legendu. Sledeći primeri su za slučajeve u kojima se legenda kreira automatski.

Promena imena legende

Izmenimo sada naslov legende. Imamo dve legende, po jednu za boju i veličinu. Veličina je zasnovana na neprekidnoj promenljivoj, dok je boja zasnovana na kategoričkoj (diskretnoj) promenljivoj.

Postoje tri načina da se izmeni naziv legende:

Metod 1: Korišćenjem labs()

gg = ggplot(midwest, aes(x=area, y=poptotal)) + 
  geom_point(aes(col=state, size=popdensity)) + 
  geom_smooth(method="loess", se=F) + xlim(c(0, 0.1)) + ylim(c(0, 500000)) + 
  labs(title="Area Vs Population", y="Population", x="Area", caption="Source: midwest")

gg + labs(color="State", size="Density")  # modifikujemo naziv legende

Metod 2: Korišćenjem guides()

gg = ggplot(midwest, aes(x=area, y=poptotal)) + 
  geom_point(aes(col=state, size=popdensity)) + 
  geom_smooth(method="loess", se=F) + xlim(c(0, 0.1)) + ylim(c(0, 500000)) + 
  labs(title="Area Vs Population", y="Population", x="Area", caption="Source: midwest")

gg + guides(color=guide_legend("State"), size=guide_legend("Density"))  # modifikujemo naziv legnde

Metod 3: Korišćenjem scale_aesthetic_vartype() formata

Format scale_aesthetic_vartype() nam omogućava da isključimo legendu za neku estetiku, ostavljajući ostatak. Ovo se može uraditi postavljanjem guide = FALSE. Na primer, ako je legenda za veličinu tačaka zasnovana na neprekidnoj promenljivoj, onda je scale_size_continuous() funkcija koju treba koristiti.

Možete li pogoditi koju funkciju koristiti za legendu ako imamo boju koja je bazirana na kategoričkoj promenljivoj?

gg = ggplot(midwest, aes(x=area, y=poptotal)) + 
  geom_point(aes(col=state, size=popdensity)) + 
  geom_smooth(method="loess", se=F) + xlim(c(0, 0.1)) + ylim(c(0, 500000)) + 
  labs(title="Area Vs Population", y="Population", x="Area", caption="Source: midwest")

# modifikujemo legendu
gg + scale_color_discrete(name="State") + scale_size_continuous(name = "Density", guide = FALSE)  # sklanjamo legendu za velicinu

Promena oznaka u legendi i boja po kategorijama

Ovo se može izvršiti pomoću odgovarajuće scale_aesthetic_manual() funkcije. Nove oznake se novode u labels argumentu. Ako želimo da promenimo boju kategorija, ona se može dodeliti argumentu values kao što je prikazano u narednom primeru:

gg = ggplot(midwest, aes(x=area, y=poptotal)) + 
  geom_point(aes(col=state, size=popdensity)) + 
  geom_smooth(method="loess", se=F) + xlim(c(0, 0.1)) + ylim(c(0, 500000)) + 
  labs(title="Area Vs Population", y="Population", x="Area", caption="Source: midwest")

gg + scale_color_manual(name="State", 
                        labels = c("Illinois", 
                                   "Indiana", 
                                   "Michigan", 
                                   "Ohio", 
                                   "Wisconsin"), 
                        values = c("IL"="blue", 
                                   "IN"="red", 
                                   "MI"="green", 
                                   "OH"="brown", 
                                   "WI"="orange"))

Promena redosleda legendi

U slučaju da želimo da prikažemo legendu za veličinu (Density) pre legende za boju (State), to možemo uraditi pomoću guides() funkcije. Legende se navode u željenom redosledu.

Ako pak želimo da promenimo položaj oznaka unutar legende, podesimo ih u željeni redosled kao što je prikazano u prethodnom primeru.

gg = ggplot(midwest, aes(x=area, y=poptotal)) + 
  geom_point(aes(col=state, size=popdensity)) + 
  geom_smooth(method="loess", se=F) + xlim(c(0, 0.1)) + ylim(c(0, 500000)) + 
  labs(title="Area Vs Population", y="Population", x="Area", caption="Source: midwest")

gg + guides(size = guide_legend(order = 1),
            colour = guide_legend(order = 2))

Stilizovanje naslova, teksta, pozadine legende

Stilovi naslova legende, teksta i pozadina se takođe mogu podesiti. Boja pozadine je pravougaoni element, tako da se mora podesiti korišćenjem element_rect() funkcije.

gg = ggplot(midwest, aes(x=area, y=poptotal)) + 
  geom_point(aes(col=state, size=popdensity)) + 
  geom_smooth(method="loess", se=F) + xlim(c(0, 0.1)) + ylim(c(0, 500000)) + 
  labs(title="Area Vs Population", y="Population", x="Area", caption="Source: midwest")

gg + theme(legend.title = element_text(size=12, color = "firebrick"), 
           legend.text = element_text(size=10),
           legend.key = element_rect(fill='springgreen')) 

Promena položaja i uklanjanje legende

Položaj legende je aspekt teme, tako da se može modifikovati korišćenjem theme() funkcije. Ako želimo da legendu postavimo unutar grafika, možemo dodatno kontrolisati zglobnu tačku legende koristeći legend.justification. Argument legend.position predstavlja njene koordinate u oblasti grafika, gde je (0,0) donji levi ugao na grafiku, a (1,1) gornji desni.

gg = ggplot(midwest, aes(x=area, y=poptotal)) + 
  geom_point(aes(col=state, size=popdensity)) + 
  geom_smooth(method="loess", se=F) + xlim(c(0, 0.1)) + ylim(c(0, 500000)) + 
  labs(title="Area Vs Population", y="Population", x="Area", caption="Source: midwest")

# bez legende
gg + theme(legend.position="None") + labs(subtitle="No Legend")

# legendu postavljamo levo
gg + theme(legend.position="left") + labs(subtitle="Legend on the Left")

# legenda na dnu, horizontalno okrenuta
gg + theme(legend.position="bottom", legend.box = "horizontal") + labs(subtitle="Legend at Bottom")

# legenda u donjem desnom uglu, unutar grafika 
gg + theme(legend.title = element_text(size=12, color = "salmon", face="bold"),
           legend.justification=c(1,0), 
           legend.position=c(0.95, 0.05),  
           legend.background = element_blank(),
           legend.key = element_blank()) + 
  labs(subtitle="Legend: Bottom-Right Inside the Plot")

# legenda u gornjem levom uglu, unutar grafika
gg + theme(legend.title = element_text(size=12, color = "salmon", face="bold"),
           legend.background = element_blank(),
           legend.justification=c(0,1),
           legend.position=c(0.05, 0.95),
           legend.key = element_blank()) + 
  labs(subtitle="Legend: Top-Left Inside the Plot")

Dodavanje teksta, oznaka i napomena

Dodavanje teksta i oznaka oko tačaka

Pokušajmo sada da dodamo neki tekst. Dodaćemo tekst samo onim okruzima koji imaju preko 300K stanovnika. Da bismo to postigli, kreiramo drugu bazu podataka (podskup osnovne baze) (midwest_sub), koja sadrži samo okruge koji kvalifikuju navedeno stanje.

Zatim crtamo geom_text i geom_label sa ovom novom bazom kao izvorom podataka. Ovo će obezbediti da se oznake (geom_label) dodaju samo za tačke sadržane u novoj bazi.

library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:plyr':
## 
##     arrange, count, desc, failwith, id, mutate, rename, summarise,
##     summarize
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
# Izdvajamo odgovarajuce redove
midwest_sub = filter(midwest, poptotal>300000)

gg = ggplot(midwest, aes(x=area, y=poptotal)) + 
  geom_point(aes(col=state, size=popdensity)) + 
  geom_smooth(method="loess", se=F) + xlim(c(0, 0.1)) + ylim(c(0, 500000)) + 
  labs(title="Area Vs Population", y="Population", x="Area", caption="Source: midwest")

# grafik sa tekstom i oznakama
gg + geom_text(aes(label=county), size=2, data=midwest_sub) + labs(subtitle="With ggplot2::geom_text") + theme(legend.position = "None")   # tekst

gg + geom_label(aes(label=county), size=2, data=midwest_sub, alpha=0.25) + labs(subtitle="With ggplot2::geom_label") + theme(legend.position = "None")  # oznake

# dodavanje teksta i oznaka na malo lepsi nacin (van tacaka) (koristeci `ggrepel` paket)
library(ggrepel)
gg + geom_text_repel(aes(label=county), size=2, data=midwest_sub) + labs(subtitle="With ggrepel::geom_text_repel") + theme(legend.position = "None")   # tekst

gg + geom_label_repel(aes(label=county), size=2, data=midwest_sub) + labs(subtitle="With ggrepel::geom_label_repel") + theme(legend.position = "None")   # labela

Pošto se oznake pozajmljuju iz druge baze, potrebno je da postavimo argument data koji ukazuje na nju.

Dodavanje napomena unutar grafika

Hajde sada da vidimo kako da dodamo napomene bilo gde na grafiku. To se može uraditi sa annotation_custom()- funkcijom koja uzima grob kao argument. Dakle, hajde da napravimo grob koji sadrži tekst koji želimo da prikažemo pomoću grid paketa.

gg = ggplot(midwest, aes(x=area, y=poptotal)) + 
  geom_point(aes(col=state, size=popdensity)) + 
  geom_smooth(method="loess", se=F) + xlim(c(0, 0.1)) + ylim(c(0, 500000)) + 
  labs(title="Area Vs Population", y="Population", x="Area", caption="Source: midwest")

# konstruisemo i dodajemo napomenu
library(grid)
my_text = "Ovaj tekst je na x=0.7 i y=0.8!"
my_grob = grid.text(my_text, x=0.7,  y=0.8, gp=gpar(col="firebrick", fontsize=14, fontface="bold"))

gg + annotation_custom(my_grob)

Zamena i okretanje x i y ose

Zamena osa

Samo dodajemo coord_flip().

gg = ggplot(midwest, aes(x=area, y=poptotal)) + 
  geom_point(aes(col=state, size=popdensity)) + 
  geom_smooth(method="loess", se=F) + xlim(c(0, 0.1)) + ylim(c(0, 500000)) + 
  labs(title="Area Vs Population", y="Population", x="Area", caption="Source: midwest", subtitle="X and Y axis Flipped") + theme(legend.position = "None")

# Zamenjujemo ose
gg + coord_flip()

Okretanje skale na osi

Ovo je prilično jednostavno. Koristimo scale_x_reverse() za x osu i scale_y_reverse() za y osu.

gg = ggplot(midwest, aes(x=area, y=poptotal)) + 
  geom_point(aes(col=state, size=popdensity)) + 
  geom_smooth(method="loess", se=F) + xlim(c(0, 0.1)) + ylim(c(0, 500000)) + 
  labs(title="Area Vs Population", y="Population", x="Area", caption="Source: midwest", subtitle="Axis Scales Reversed") + theme(legend.position = "None")

# "Izvrcemo" x i y ose
gg + scale_x_reverse() 
## Scale for 'x' is already present. Adding another scale for 'x', which
## will replace the existing scale.

gg + scale_y_reverse()
## Scale for 'y' is already present. Adding another scale for 'y', which
## will replace the existing scale.

gg + scale_x_reverse() + scale_y_reverse()
## Scale for 'x' is already present. Adding another scale for 'x', which
## will replace the existing scale.
## Scale for 'y' is already present. Adding another scale for 'y', which
## will replace the existing scale.

Fasete: Crtanje više grafika po kategorijama

Prikazaćemo kako se to radi na bazi mpg (ona je dostupna u ggplot2 paketu).

data(mpg, package="ggplot2")

g = ggplot(mpg, aes(x=displ, y=hwy)) + 
      geom_point() + 
      labs(title="hwy vs displ", caption = "Source: mpg") +
      geom_smooth(method="lm", se=FALSE) + 
      theme_bw()  # primenjujemo bw temu
g

Imamo jednostavan grafik kilometraže autoputa (hwy) u odnosu na broj obrtaja motora (discpl) za ceo skup podataka. Ali šta ako želimo da vidimo kako ovaj odnos varira za različite vrste vozila?

Facet Wrap

Funkcija facet_wrap() se koristi za razbijanje velikog grafika u više malih za pojedinačne kategorije. On uzima formulu kao glavni argument. Stavke levo od ~ predtsavljaju redove, dok su desno kolone.

Podrazumevano, svi grafici imaju istu skalu na x i y osi. Možemo ih promeniti postavljanjem scales = 'free', ali na ovaj način je teže uporediti grupe.

g = ggplot(mpg, aes(x=displ, y=hwy)) + 
      geom_point() + 
      geom_smooth(method="lm", se=FALSE) + 
      theme_bw()  

# Facet wrap sa istim skalama
g + facet_wrap( ~ class, nrow=3) + labs(title="hwy vs displ", caption = "Source: mpg", subtitle="Ggplot2 - Faceting - Multiple plots in one figure")

# Facet wrap sa slobodnim skalama
g + facet_wrap( ~ class, scales = "free") + labs(title="hwy vs displ", caption = "Source: mpg", subtitle="Ggplot2 - Faceting - Multiple plots in one figure with free scales") 

Dakle, šta možemo zakljuciti iz ovoga? Kao prvo, većina automobila sa dva sedišta ima veći broj obrtaja motora, dok su kombi (minivan) i kompaktna vozila sa manjim brojem. To je očigledno iz mesta gde su tačke postavljene na x osi.

Takođe, kilometraža na autoputu pada kod svih klasa kako se povećava broj obrtaja motora. Ovaj pad se čini više najizraženijim kod kompaktnih i subkompaktnih vozila.

Facet Grid

Naslovi i oznake na osama zauzimaju značajan prostor - facet_grid() se oslobađa toga i daje veći prostor gafikonima. Glavna razlika je što nije moguće odabrati broj redova i kolona u mreži.

Napravimo mrežu da vidimo kako se ona razlikuje po proizvodjačima:

g = ggplot(mpg, aes(x=displ, y=hwy)) + 
      geom_point() + 
      labs(title="hwy vs displ", caption = "Source: mpg", subtitle="Ggplot2 - Faceting - Multiple plots in one figure") +
      geom_smooth(method="lm", se=FALSE) + 
      theme_bw()  

# Dodajemo fasetnu mrezu
g1 = g + facet_grid(manufacturer ~ class)  # proizvodjaci po redovima i vrste po kolonama
plot(g1)

Napravimo još jednu varijantu - po cilindru:

g = ggplot(mpg, aes(x=displ, y=hwy)) + 
      geom_point() + 
      geom_smooth(method="lm", se=FALSE) + 
      labs(title="hwy vs displ", caption = "Source: mpg", subtitle="Ggplot2 - Facet Grid - Multiple plots in one figure") +
      theme_bw() 

g2 = g + facet_grid(cyl ~ class)  # cyl u redovima i class u kolonama
plot(g2)

Moguće je i oba grafikona staviti u jedno polje. Za to možemo koristiti paket gridExtra().

# Crtamo vise grafika u jedno polje
library(gridExtra)
## 
## Attaching package: 'gridExtra'
## The following object is masked from 'package:dplyr':
## 
##     combine
gridExtra::grid.arrange(g1, g2, ncol=2)

Modifikovanje pozadine grafika, glavne i manjih osi

Promena pozadine grafika

g = ggplot(mpg, aes(x=displ, y=hwy)) + 
      geom_point() + 
      geom_smooth(method="lm", se=FALSE) + 
      theme_bw()  

# menjamo pozadinske elemente grafika
g + theme(panel.background = element_rect(fill = 'khaki'),
          panel.grid.major = element_line(colour = "burlywood", size=1.5),
          panel.grid.minor = element_line(colour = "tomato", 
                                          size=0.25, 
                                          linetype = "dashed"),
          panel.border = element_blank(),
          axis.line.x = element_line(colour = "darkorange", 
                                     size=1.5, 
                                     lineend = "butt"),
          axis.line.y = element_line(colour = "darkorange", 
                                     size=1.5)) +
    labs(title="Modified Background", 
         subtitle="How to Change Major and Minor grid, Axis Lines, No Border")

# menjamo margine grafika
g + theme(plot.background=element_rect(fill="salmon"), 
          plot.margin = unit(c(2, 2, 1, 1), "cm")) +  # gore, desno, dole, levo
    labs(title="Modified Background", subtitle="How to Change Plot Margin")

Uklanjanje velike i male mreže, promena granica, naslova osa, oznaka, podeoka

g = ggplot(mpg, aes(x=displ, y=hwy)) + 
      geom_point() + 
      geom_smooth(method="lm", se=FALSE) + 
      theme_bw()  

g + theme(panel.grid.major = element_blank(), 
          panel.grid.minor = element_blank(), 
          panel.border = element_blank(),
          axis.title = element_blank(), 
          axis.text = element_blank(),
          axis.ticks = element_blank()) +
  labs(title="Modified Background", subtitle="How to remove major and minor axis grid, border, axis title, text and ticks") 

Dodavanje slike u pozadinu

library(grid)
library(png)

img = png::readPNG("C:\\Users\\WIN7\\Desktop\\MATF\\SS4\\GGPLOT\\RLogo.png")
g_pic = rasterGrob(img, interpolate=TRUE)

g = ggplot(mpg, aes(x=displ, y=hwy)) + 
      geom_point() + 
      geom_smooth(method="lm", se=FALSE) + 
      theme_bw()  

g + theme(panel.grid.major = element_blank(), 
          panel.grid.minor = element_blank(), 
          plot.title = element_text(size = rel(1.5), face = "bold"),
          axis.ticks = element_blank()) + 
  annotation_custom(g_pic, xmin=5, xmax=7, ymin=30, ymax=45)