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:
element_text()
: Budući da su naslov, podnaslov i natpisi tekstualni elementi, element_text()
funkcija se koristi za njihovo podešavanje.
element_line()
: Slično, element_line()
koristi za modifikovanje linijskih komponenti kao sto su linije osa, linije mreže, itd.
element_rect()
: Modifikuje komponente kao što su pozadina grafika i panela.
element_blank()
: Isključuje prikazivanje komponente teme.
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, 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.
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.
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
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"))
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))
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'))
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")
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.
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)
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()
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.
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?
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.
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)
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")
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")
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)