R:n Visualisointipakettien vertailua

Olen aina ollut hyvin visuaalinen persoona. Piirtäminen, maalaaminen ym. taiteilu oli pitkään hyvinkin aktiivinen osa elämää. Sitten kävi silleen vanhanaikaisesti, että työt ja perhe ns. poistivat vaapaa-ajan ongelmat; valitettavasti aika vähän tulee piirreltyä mitään analogisilla visualisointivälineillä. Vaikka näkökin on tasaisesti heikentynyt, ei visuaalinen silmä ole kuitenkaan vallan ummistunut. Kun vielä istuin työaikana yliopistolla, saatoin kuluttaa päiväkausia julkaisugrafiikoiden/presentaatioiden hiomiseen.

Aluksi käytin grafiikan tuottamiseen ihan spesifejä visualisointiohjelmia, mutta jossain vaiheessa tajusin ettei hommassa ollut mitään järkeä. Sen sijaan että muuttaisin jotain viivan paksuuksia kymmenennen kerran käsin, hoituisivat muutokset paljon näppärämmin jos graafikan muodostus tapahtuisi koodilla. Tuohon aikaan työskentelin enimmäkseen Matlabilla, mutta myös R:llä alkoi pikkuhiljaa syntyä siedettävää kuvamateriaalia. Niin sanotun base-R grafiikasta olen hyvin pitkälti jo luopunut, sillä modernit visualisointikirjastot tarjoavat paljon tyydyttävämpää jälkeä, ennen kaikkea vähemmällä vaivalla.

Nykyään laajasti käytetyistä high-level grafiikkakirjastoista helppokäyttöisin on ggplot2, jota myös itse olen käyttänyt selvästi eniten. ggplot:illa kuvien tuottaminen muistuttaa kuvankäsittelyä, siten että kuvaobjektiin voi käytännössä loputtomasti lisätä uusia, kuvan ominaisuuksia muuttavia kerroksia. Base-R grafiikan tapaan ggplot2 kuvat ovat staattisia, joskin molempiin on saatavissa reaktiivisuutta shiny paketin avulla. Yhtenä oikotienä voi myös käyttää
ggviz -pakettia, joka piilottaa käyttäjältä suuren osan shiny-toiminnallisuuden vaatimasta koodista.

Puhtaasti R:lle kirjoitettujen grafiikkapakettien lisäksi on myös olemassa JavaScript:llä toteutettuja, vahvasti interaktiivisia visualisointityökaluja, joihin on olemassa R-API. Tähän kategoriaan kuuluvat esim. highcharter, plotly ja dygraphs. Näillä paketeilla saa aikaan mahtavaa jälkeä, kunhan ensin opettelee miten syntaksi toimii. Lisääntynyt toiminnallisuus tuo väkisinkin mukanaan oppimishaasteen, eikä ongelmiin löydy vielä apuja välttämättä kovin helposti. Tämä ongelma voi toki hyvinkin korjaantua ajan kanssa, mutta se riippuu pitkälti käyttäjien aktiivisuudesta ja halusta ottaa näitä työkaluja haltuun.

Katsotaan seuraavaksi miten saman kuvan tuottaminen (ainakin osapuilleen) onnistuu eri kirjastoilla. Käytän esimerkkinä R:n datasets -paketista löytyvää UKLungDeaths aikasarja-aineistoa, jossa on tilastoituna Iso-Britannian keuhkotautikuolemat kuukausittain vuosina 1974–1979, erikseen kummallekin sukupuolelle. Osa paketeista toimii hienosti aikasarjaobjektien kanssa, mutta esim. ggplot2 käyttää data.frame formaatissa olevaa dataa:

require(zoo)
lungDeaths = cbind(mdeaths, fdeaths)
df = data.frame(time = zoo::as.Date(as.yearmon(time(lungDeaths))),
                Male = lungDeaths[,'mdeaths'],
                Female = lungDeaths[,'fdeaths'])

 

ggplot2

Aloitetaan itselleni helpoimmasta eli ggplot2:sta, jossa (kuten muissakin tässä käsiteltävissä paketeissa) kuvaan voi lisätä elementtejä joko päivittämällä kuvaobjektia tai ketjuttamalla komentoja. Muista paketeista poiketen (jotka noudattavat magrittr -paketin ketjutusoperaattori-konventiota %>%), ggplot2:ssa elementtejä yhdistellään + -operaattorilla. Laitan kuvaan miesten kuolemat viivalla ja pisteillä sekä naisten kuolemat porrasviivana, siten että viivan alle jäävä alue on väritetty:

require(ggplot2)
require(ggalt)

ggplot(df,aes(time,Male)) + 
  # Male series:
  geom_line(col = bilot_palette[3]) +
  geom_point(shape = 22,
             fill = 'white',
             col = bilot_palette[3]) +
  # Female series:
  geom_ribbon(aes(ymin = 0, ymax = Female),
              stat="stepribbon",
              fill = bilot_palette[1],
              alpha = 0.2) +
  geom_step(aes(time,Female),
            col = bilot_palette[1]) +
  # Decoration:
  theme_classic() +
  xlab('') + 
  ylab('Number of deaths') +
  ggtitle("Deaths from Lung Disease (UK)")

 

Yksinkertaista ja tyylikästä. Kuvan muotoilua voi helposti säätää theme_x() määrittelyllä (tässä käytin theme_classic teemaa) ja lisää valmiiksi koodattuja teemoja löytyy esim. ggthemr, ggthemes ja ggtech -paketeista. Vaikka interaktiivisuus puuttuu, on kuvan tyylin muokkaaminen mielestäni helppoa ja intuitiivista. Lisäksi, ggplot2:lla tehdyn kuvan saa todella näppärästi muutettua (ainakin osittain) interaktiiviseksi plotly paketin avulla, syöttämällä ggplot -kuvaobjekti ggplotly() -funktiolle.

 

plotly

Plotly ei itse asiassa ole pelkkä visualisointityökalu, vaan laajempi tuote joka mahdollistaa myös web-applikaatioiden tekemisen. Plotly:n dashboard-toiminnallisuus on kuitenkin toteutettu Python:illa. R:ssä plotly -kuvien teko tapahtuu hyvin samalla tavalla kuin ggplot:issa; ensin luodaan kuvaobjekti plot_ly() -funktiolla, antamalla data yhtenä argumenttina. Kuvan muotoilua voi säätää joustavasti, mutta vaikka dokumentaatio on pääsääntöisesti oikein hyvää, eri kuvaelementtien ominaisuuksien hienosäätö saattaa vaatia kärsivällistä selvittelyä.

require(plotly)

plot_ly(df) %>%
  # Male series:
  add_trace(x = ~time,y = ~Male,
            type = 'scatter',
            mode = "markers+lines",
            color = I(bilot_palette[3]),
            marker = list(color = 'white',
                          symbol = 'square',
                          line = list(
                            color = bilot_palette[3],
                            width = 1)
                          ),
            name = 'Male') %>%
  # Female series:
  add_ribbons(x = ~time,ymin = 0,ymax = ~Female,
              color = I(bilot_palette[1]),
              opacity = 0.5,
              line = list(shape = "hvh"),
              name = 'Female') %>%
  # Decoration:
  layout(title = "Deaths from Lung Disease (UK)",
         xaxis = list(title=''), 
         yaxis = list(title = 'Number of deaths'))

 

 

Lopputuloksena saadaan vähällä vaivalla interaktiivinen kuva, joka näyttää kursoria kuvan päällä liikuteltaessa haluttua dataa halutulla tavalla. Kuvaa voi myös zoomata tai filtteröidä valintatyökaluilla.

 

highcharter

highcharter -paketti on R-käyttöliittymä Highcharts JavaScript kirjastolle. Vaikka Highcharts on todella monipuolinen, sen käyttö R:ssä ei kuitenkaan ole kovin helppoa, varsinkin kun kunnollinen dokumentaatio puuttuu. Olen itse myös aika noviisi tämän paketin käytössä, joten sain aikaiseksi vain osittain vertailukelpoisen kuvan.

require(highcharter)

highchart() %>%
  # Male series:
  hc_add_series_ts(mdeaths, 
                   name = "Male",
                   color = bilot_palette[3]) %>%
  # Female series:
  hc_add_series_ts(fdeaths, 
                   name = "Female",
                   color = bilot_palette[1]) %>%  
  # Decoration:
  hc_tooltip(crosshairs = TRUE, 
                      borderColor = bilot_palette[4],
                      shared = TRUE, 
                      borderWidth = 2) %>%
  hc_plotOptions(series = 
                   list(step = 'center')) %>%
  hc_title(text = "Monthly Deaths from Lung Diseases in the UK") %>%  
  hc_yAxis(title = list(text='Number of deaths')) %>%
  hc_add_theme(hc_theme_elementary())

 

Myönnettäköön että highcharter ei varsinaisesti pääse näyttämään parhaita puoliaan tässä esimerkissä. Muista paketeista poiketen se nimittäin mahdollistaa ns. porautumisen graafissa datajoukon sisään, mikä tosin vaatii datan strukturointia etukäteen.

 

dygraphs

Viimeisenä listalla on spesifisti aikasarjojen visualisointiin tarkoitettu dygraphs -paketti, joka on todella hyvin dokumentoitu. Syntaksi toimii pääpiirteissään samalla logiikalla kuin muissakin ym. paketeissa. Aikasarjojen tyylin muotoilu on tehty todella helpoksi ja aikajanan zoomaus on toteutettu näyttävästi.

require(dygraphs)

dygraph(lungDeaths, 
        main = "Deaths from Lung Disease (UK)",
        ylab = 'Number of deaths') %>%
  # Male series:
  dySeries("mdeaths", 
           label='Males',
           drawPoints = TRUE, 
           pointShape = "square", 
           pointSize = 5,
           color = bilot_palette[3]) %>%
  # Female series:
  dySeries("fdeaths", 
           label='Females',           
           stepPlot = TRUE, 
           fillGraph = TRUE, 
           strokeWidth = 2,
           color = bilot_palette[1]) %>%
  # Decoration:
  dyOptions(pointSize = 2, 
            drawGrid = F) %>%
  dyCrosshair(direction = 'vertical') %>%
  dyHighlight(highlightCircleSize = 5,
              highlightSeriesOpts = 
                list(strokeWidth = 1)) %>%
  dyRangeSelector(height = 30, 
                  strokeColor = "")

 

Johtopäätös

Ainakin omasta mielestäni R on erinomainen visualisointityökalu. Mahdollisuudet ovat käytännössä rajattomat, ainakin jos taitoa löytyy. Mitä tulee eri pakettien paremmuuteen, olen mieltä. Mitään yleispätevää suositusta en pysty antamaan; sopivin paketti riippuu pitkälti tilanteesta ja tarpeesta. Harvemmin yhden paketin/kirjaston hallinta riittää kattamaan kaikki skenaariot. Pikaiseen kokeiluun ja staattiseen visualisointiin ggplot2 on ehkä paras vaihtoehto. Voin sanoa että dygraphs on ehdottomasti oma valinta aikasarjojen visualisointiin ja interaktiivisiin kuviin käyttäisin varmaan ensisijaisesti plotly:ä.