Kuvan labelointi data.frame:lla R:n ggplot2:ssa

Luokat: data

Tehdäänpä tiivis tekninen bloggaus lähinnä vinkkinä itselleni tulevaisuuteen. Eli kun seuraavan kerran googlaan lauseella ggplot label with dataframe data.frame niin löydän tänne.

ggplot2 on suosittu R-kielen paketti staattisen grafiikan tekemiseen. Paketin funktiot geom_label ja geom_text (kuin myös geom_sf_text, geom_sf_label ja ggrepel-paketin geom_text_repel ja geom_label_repel) ovat näppäriä tekstin lisäämiseen kuviin. Tavanomainen käyttötarkoitus on esim. nimetä viivakuvion viiva suoraan kuvaan, laittaa tolpan nokkaan sarjan arvo tai karttaan pitäjän nimi ja väkiluku.

Menneellä viikolla minulle tuli tarve saada karttaan jokaisen alueen kohdalle pieni taulukko, jossa kolme saraketta ja kolme riviä. Yleensä käytän tällaisiin leaflet-pakettia ja teen vuorovaikutteisen kartan Eduskuntavaalit 2019: Helsingin äänestysalueiden top 3. Saavutettavuuden aikakaudella olen palannut staattisiin karttoihin, joille on helppo antaa alt-teksti ja tein saman sitten ggplot2:lla. Tässä on esimerkkikoodi, jossa haetaan kuntatason data se aggregoidaan vaalipiiritasolle. Vaalipiireittäin haluan sitten näyttää vaalipiirin nimen, kuntien määrän ja vaalipiirin pinta-alan.

library(dplyr)
library(glue)
library(ggplot2)
library(tidyr)
library(readr)
library(geofi)
library(sf)

muni <- get_municipalities()
vaalipiiri <- muni %>% 
  group_by(vaalipiiri_name_fi) %>% 
  summarise(n_muni = n())
vaalipiiri$area <- as.integer(round(sf::st_area(vaalipiiri)/1000000))

print(vaalipiiri)
## Simple feature collection with 13 features and 3 fields
## geometry type:  GEOMETRY
## dimension:      XY
## bbox:           xmin: 83747.59 ymin: 6637032 xmax: 732907.7 ymax: 7776431
## projected CRS:  ETRS89 / TM35FIN(E,N)
## # A tibble: 13 x 4
##    vaalipiiri_name_fi     n_muni                                      geom  area
##  * <chr>                   <int>                            <GEOMETRY [m]> <int>
##  1 Ahvenanmaan maakunnan…     16 MULTIPOLYGON (((90854.78 6694278, 89955.…  1525
##  2 Hämeen vaalipiiri          21 POLYGON ((290386.6 6750853, 290311.6 675… 12682
##  3 Helsingin vaalipiiri        1 MULTIPOLYGON (((402737.7 6680700, 402069…   264
##  4 Kaakkois-Suomen vaali…     27 MULTIPOLYGON (((470374.8 6722711, 464319… 28966
##  5 Keski-Suomen vaalipii…     22 POLYGON ((434977 6839711, 430753.7 68430… 18926
##  6 Lapin vaalipiiri           21 POLYGON ((337502.3 7581690, 332585.3 758… 98930
##  7 Oulun vaalipiiri           38 MULTIPOLYGON (((334215.3 7125046, 334345… 61918
##  8 Pirkanmaan vaalipiiri      23 POLYGON ((262460.4 6807729, 263748.3 681… 15513
##  9 Satakunnan vaalipiiri      16 MULTIPOLYGON (((195782.2 6798446, 196072…  8354
## 10 Savo-Karjalan vaalipi…     32 POLYGON ((451260.4 6978835, 455573.9 698… 43900
## 11 Uudenmaan vaalipiiri       25 MULTIPOLYGON (((280618.9 6639331, 277760…  9335
## 12 Vaasan vaalipiiri          40 MULTIPOLYGON (((189333.9 7001075, 190233… 27208
## 13 Varsinais-Suomen vaal…     27 MULTIPOLYGON (((180938.5 6714890, 181988… 10444

Seuraavaksi tarvitsemme kullekin vaalipiirille sen oman pienen datan. Tavoitteena siis tämän tyyppinen label:

Vaasan vaalipiiri

vpiiri  Vaasan
n_muni      40
area     27208
pad_same_length_plus_2 <- function(x,
                                   padchar=" ",
                                   padside= "right", 
                                   padplus = 2){
  stringr::str_pad(x, max(nchar(x))+padplus, side=padside, pad=padchar)
                                   } 
vaalipiiri_df <- st_drop_geometry(vaalipiiri) %>% 
  setNames(c("vpiiri","n_muni","area"))

vpt <- unique(vaalipiiri_df$vpiiri)
vplista <- list()
for (i in seq_along(vpt)){
  tmpdat <- tibble(vaalipiiri = vpt[i],
                   label = vaalipiiri_df %>%
                     filter(vpiiri == vpt[i]) %>%
                     mutate_all(as.character) %>%
                     mutate(vpiiri = gsub(" vaalipiiri| maakunnan", "", vpiiri)) %>% 
                     pivot_longer(1:3) %>% 
                     mutate(name = pad_same_length_plus_2(name, padplus = 0),
                            value = pad_same_length_plus_2(value, padside = "left", padplus = 0))  %>%
                     setNames(c(" "," ")) %>% 
                     format_tsv() %>%  
                     sub("\n$", "", .)) %>%
    mutate(label = paste0(vaalipiiri,"\n",label))
  vplista[[vpt[i]]] <-  tmpdat
}
label_data <- do.call(bind_rows, vplista)
mapdata2 <- left_join(vaalipiiri,label_data, by = c("vaalipiiri_name_fi" = "vaalipiiri"))
ggplot(mapdata2, aes(fill = area,
                    label = label)) +
  labs(title = "Vaalipiirit vertailussa",
       fill = "Vaalipiirin pinta-ala") +
  geom_sf() +
  ggrepel::geom_label_repel(data = mapdata2 %>%
                             sf::st_set_geometry(NULL) %>%
                             bind_cols(mapdata2 %>% 
                                         sf::st_centroid() %>% 
                                         sf::st_coordinates() %>% as_tibble()),
                           aes(label = label,
                               x = X,
                               y = Y#,
                               ),
                           fill = alpha("white", 2/3),
                           color = "black",
                           family = "Space Mono",
                           size = 3.5,
                           max.overlaps = 35) +
  scale_fill_viridis_c()

Käännökset

Katso myös