2.2 Plotly

Plotly je drugi paket koji ćemo posmatrati. Početna inspiracija za ovaj paket je bila podrška plotly.js tipova grafika koje ggplot2 ne podržava. Plotly ima bogate karakteristike, kao i dosta pristupačnih grafika. Poseduje web-based toolbox koristan za vizualizaciju. I takođe ima sposobnost da ggplot2 grafike učini interaktivnim.


2.2.1 Scatterplot

Scatterplot je koristan za vizualizaciju povezanosti dve kvantitativne promenljive, problem se javlja ako dođe do preklapanja, i to možemo rešiti na par načina.

#Posmatramo na x-osi gradsku miljažu, dok na y-osi posmatramo miljažu auto-puta
 library(plotly)
## 
## Attaching package: 'plotly'
## The following object is masked from 'package:ggplot2':
## 
##     last_plot
## The following object is masked from 'package:stats':
## 
##     filter
## The following object is masked from 'package:graphics':
## 
##     layout
 subplot(
   plot_ly(mpg, x = ~cty, y = ~hwy, name = "default"), #po default-u
   plot_ly(mpg, x = ~cty, y = ~hwy) %>% 
     add_markers(alpha = 0.2, name = "alpha"), #alfa transparentnost
   plot_ly(mpg, x = ~cty, y = ~hwy) %>% 
     add_markers(symbol = I(1), name = "hollow") #uzimamo jedan simbol, i stavićemo da bude šupalj
 )
## No trace type specified:
##   Based on info supplied, a 'scatter' trace seems appropriate.
##   Read more about this trace type -> https://plot.ly/r/reference/#scatter
## No scatter mode specifed:
##   Setting the mode to markers
##   Read more about this attribute -> https://plot.ly/r/reference/#scatter-mode
#Sada ćemo da vidimo na koji način možemo da koristimo simbole
  subplot(
   plot_ly(x = 1:6, y = 1:6, symbol = I(1:6), name = "pch"),
   plot_ly(mpg, x = ~cty, y = ~hwy,  symbol = ~cyl,
           symbols = 1:3,name = "cyl")) #ponovo posmatramo na x-osi gradsku miljažu, dok na y-osi posmatramo miljažu auto-puta, i uzimamo različite simbole u odnosu na broj cilindara
## No trace type specified:
##   Based on info supplied, a 'scatter' trace seems appropriate.
##   Read more about this trace type -> https://plot.ly/r/reference/#scatter
## No scatter mode specifed:
##   Setting the mode to markers
##   Read more about this attribute -> https://plot.ly/r/reference/#scatter-mode
## No trace type specified:
##   Based on info supplied, a 'scatter' trace seems appropriate.
##   Read more about this trace type -> https://plot.ly/r/reference/#scatter
## No scatter mode specifed:
##   Setting the mode to markers
##   Read more about this attribute -> https://plot.ly/r/reference/#scatter-mode
#Kada mapiramo numeričku promenljivu u simbol, napravi se samo jedan trag, pa se ne generiše legenda. Međutim ako želimo jedan trag po simbolu, moramo da se postaramo da je promenljiva koju mapiramo faktor, kao u narednom primeru:
 

 p <- plot_ly(mpg, x = ~cty, y = ~hwy, alpha = 0.3) 
 subplot(
   add_markers(p, symbol = ~cyl, name = "A single trace"),
   add_markers(p, symbol = ~factor(cyl), color = I("black"))
 )  
#Argument color ima slične osobine kao simbol, odnosno, ako je numerička vrednost u pitanju, color ima jedan trag, ali se generiše kao colorbar kako bi se razlikovale vrednosti promenljivih. Viridis je po default-u namešten colorbar. Takođe, ako je u pitanju faktor, onda color za svaku vrednost napravi trag.
 
 p <- plot_ly(mpg, x = ~cty, y = ~hwy, alpha = 0.5)
 subplot(
   add_markers(p, color = ~cyl, showlegend = FALSE) %>% 
     colorbar(title = "Viridis"),
   add_markers(p, color = ~factor(cyl))
 )
 #Postoji više načina kako da promenimo boje koje su nameštene po default-u
 
 col1 <- c("#132B43", "#56B1F7")
 col2 <- viridisLite::inferno(10)
 col3 <- colorRamp(c("red", "white", "blue"))
 subplot(
   add_markers(p, color = ~cyl, colors = col1) %>%
     colorbar(title = "ggplot2 default"),
   add_markers(p, color = ~cyl, colors = col2) %>% 
     colorbar(title = "Inferno"),
   add_markers(p, color = ~cyl, colors = col3) %>% 
     colorbar(title = "colorRamp")
 ) %>% hide_legend()
#Argument size kontroliše maksimum i minimum veličine kružića (u pikselima)

  subplot(
   add_markers(p, size = ~cyl, name = "default"),
   add_markers(p, size = ~cyl, sizes = c(1, 200), name = "custom")
 )
## Warning: `line.width` does not currently support multiple values.

## Warning: `line.width` does not currently support multiple values.

Sada ćemo proći kroz još neke tipove geometrijskih objekata kojim se prikazuju podaci.


2.2.2 Histogram i Bar plot

Glavna razlika ove dve funkcije je što bar plot zahteva i visinu (odnosno i x i y-osu), dok za histogram treba samo jedna promenljiva. U primeru ispod poredimo algoritam naslaganja po default-u u plotly.js sa nekoliko različitih algoritama dostupnih u R-u preko hist() funkcije.

#Hist() funkcija nam pruža priliku da spomenemo tri poznata algoritma po nazivu (Sturges 1926); (Freedman and Diaconis 1981); (Scott 1979).
#Price_hist() služi da zadrži rezultate naslaganja, kao i njihovo mapiranje pomoću funkcije add_bars().
#Posmatramo bazu podataka Diamonds iz paketa plotly i histogramom predstavljamo cenu dijamanata.


  p1 <- plot_ly(diamonds, x = ~price) %>% add_histogram(name = "plotly.js")
  
  price_hist <- function(method) {
    h <- hist(diamonds$price, breaks = method, plot = FALSE)
    plot_ly(x = h$mids, y = h$counts) %>% add_bars(name = method)
  }
  
  subplot(
    p1, price_hist("FD"), price_hist("Sturges"),  price_hist("Scott"),
    nrows = 4, shareX = TRUE )  #stavljamo grafike jedne ispod drugih, kako b delili x-osu
#U sledećem primeru gledamo dva načina kreiranja osnovnog bar plota, vizuelno su rezultati isti, ali pokazaćemo razliku u implementiranju.
#add_histogram() funkcija šalje sve posmatrane vrednosti browser-u i dozvoljava plotly.js-u da obavlja naslaganje. Što se tiče drugog načina, potrebno je više ljudskog truda da se to izvede, ali je prednost što se šalje manje podataka i zahteva manje računanja od strane web browser-a.
  
#Pravimo bar plotove u odnosu na kvalitet po rezu
  
  p1 <- plot_ly(diamonds, x = ~cut) %>% add_histogram()
  
  p2 <- diamonds %>%
    dplyr::count(cut) %>% #prebrojava sve vrednosti u zavisnosti od reza
    plot_ly(x = ~cut, y = ~n) %>% 
    add_bars()
  
  subplot(p1, p2) %>% hide_legend()

2.2.3 Box plot

Kao što smo već rekli, box plot predstavlja grafički prikaz 5 sumarnih statistika. Add_boxplot() funkcija zahteva jednu promenljivu i garantuje da box plotovi budu korektno orijentisani, bez obzira na to da li je promenljiva pozicionirana na x ili y-osi.

#U sledećem primeru posmatramo sveukupne cene i cene po rezu. Stavićemo sve vrednosti na isti grafik, deleći njihovu y-osu.
  
  p <- plot_ly(diamonds, y = ~price, color = I("black"), 
               alpha = 0.1, boxpoints = "suspectedoutliers")
  p1 <- p %>% add_boxplot(x = "Overall")
  p2 <- p %>% add_boxplot(x = ~cut)
  subplot(
    p1, p2, shareY = TRUE,
    widths = c(0.2, 0.8), margin = 0
  ) %>% hide_legend()
#Ako želimo da koristimo više promenljivih, preporučuje se mapiranje njihove interakcije na diskretnu osu i bojenje grupisanih vrednosti. 
#U narednom primeru smo to uradili sa cenama dijamanata po rezu i bistrini.
  
  plot_ly(diamonds, x = ~price, y = ~interaction(clarity, cut)) %>%
    add_boxplot(color = ~clarity) %>%
    layout(yaxis = list(title = ""))

2.2.4 Pravougaono naslaganje

Postoje dve funkcije za predstavljanje pravougaonog naslaganja: add_heatmap() i add_histogram2d(). Add_heatmap() funkcija je 2D analogna funkciji add_bars(), a funkcija add_histogram2d() je 2D analogna funkciji add_histogram().

#U ovom primeru posmatramo odnos cena i broja karata i poredimo tri različite funkcije add_histogram2d():
##1. Naslaganje po default-u
##2. Naslaganje po default-u sa funkcijom zsmooth koja služi za efektivni rast broja pravougaoničića.
##3. Određivanje broja pravougaonika

  p <- plot_ly(diamonds, x = ~log(carat), y = ~log(price))
  subplot(
    add_histogram2d(p) %>%
      colorbar(title = "default") %>%
      layout(xaxis = list(title = "default")),
    add_histogram2d(p, zsmooth = "best") %>%
      colorbar(title = "zsmooth") %>%
      layout(xaxis = list(title = "zsmooth")),
    add_histogram2d(p, nbinsx = 60, nbinsy = 60) %>%
      colorbar(title = "nbins") %>%
      layout(xaxis = list(title = "nbins")),
    shareY = TRUE, titleX = TRUE
  )

##Animacije

options(warn=-1)
#Pokazaćemo evoluciju odnosa između bruto društvenog proizvoda i očekivanog životnog veka od 1952 do 2007 godine. 

  data(gapminder, package = "gapminder")
  
  gg <- ggplot(gapminder, aes(gdpPercap, lifeExp, color = continent)) +
    geom_point(aes(size = pop, frame = year, ids = country)) +
    #za frame stavljamo year jer su podaci zabeleženi na godišnjoj bazi, dok je za ids postavljeno country, što omogućava glatki prelaz iz godine u godinu
    
    scale_x_log10()
  ggplotly(gg)
  #sve dok postoji frame, animacija se realizuje sa play/pause dugmićima i slider komponentom za kontrolisanje animacije.
 #Ove komponente se mogu ukloniti ili preurediti funkcijama animation_button() i animation_slider().
 #Razne animacione opcije, kao što je vreme između kadrova, trajanje prelaza i olakšanje prelaza menjaju se preko funkcije animation_opts().
  
 # U sledećem primeru prikazani su isti podaci, ali je udvostručena količina vremena između kadrova, stavlja animacionu dugmad bliže slideru, modifikuje default currentvalue.prefix podešavanja slidera.
  
  base <- gapminder %>%
    plot_ly(x = ~gdpPercap, y = ~lifeExp, size = ~pop, 
            text = ~country, hoverinfo = "text") %>% #lebdeći tekst, da se prikazuju države kod kružića
    layout(xaxis = list(type = "log"))
  
  base %>%
    add_markers(color = ~continent, frame = ~year, ids = ~country) %>%
    animation_opts(1000, easing = "elastic") %>%
    animation_button(
      x = 1, xanchor = "right", y = 0, yanchor = "bottom"
    ) %>%
    animation_slider(
      currentvalue = list(prefix = "YEAR ", font = list(color="red"))
    )
# I frame i ids služe da animiraju određene delove grafika. Može da se obezbedi pozadina koja prikazuje svaki mogući okvir (koji nije animiran) i preklapa animirane kadrove na tu pozadinu. Na narednoj slici prikazane su iste informacije kao na prethodnoj, ali slojevi animiranih okvira se pojavljuju na pozadini svih okvira.
  
  base %>%
    add_markers(color = ~continent, alpha = 0.2, showlegend = F) %>%
    add_markers(color = ~continent, frame = ~year, ids = ~country) %>%
    animation_opts(1000, redraw = FALSE)
options(warn=0)