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

data
Author

Markus Kainu

Published

April 30, 2021

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
Bounding box:  xmin: 83747.59 ymin: 6637032 xmax: 732907.7 ymax: 7776431
Projected CRS: ETRS89 / TM35FIN(E,N)
# A tibble: 13 × 4
   vaalipiiri_name_fi               n_muni                            geom  area
 * <chr>                             <int>                  <GEOMETRY [m]> <int>
 1 Ahvenanmaan maakunnan vaalipiiri     16 MULTIPOLYGON (((113645.7 66811…  1525
 2 Hämeen vaalipiiri                    21 POLYGON ((399519.5 6739515, 39… 12682
 3 Helsingin vaalipiiri                  1 MULTIPOLYGON (((402737.7 66807…   264
 4 Kaakkois-Suomen vaalipiiri           27 MULTIPOLYGON (((508037.2 66841… 28966
 5 Keski-Suomen vaalipiiri              22 POLYGON ((416178.3 6847939, 41… 18926
 6 Lapin vaalipiiri                     21 POLYGON ((388163.1 7285002, 38… 98930
 7 Oulun vaalipiiri                     38 MULTIPOLYGON (((382095.7 70603… 61918
 8 Pirkanmaan vaalipiiri                23 POLYGON ((329878.3 6763699, 32… 15513
 9 Satakunnan vaalipiiri                16 MULTIPOLYGON (((237353.5 67582…  8354
10 Savo-Karjalan vaalipiiri             32 POLYGON ((549385.7 6881072, 54… 43900
11 Uudenmaan vaalipiiri                 25 MULTIPOLYGON (((300620.8 66443…  9335
12 Vaasan vaalipiiri                    40 MULTIPOLYGON (((225346.6 68870… 27208
13 Varsinais-Suomen vaalipiiri          27 MULTIPOLYGON (((194643.4 66445… 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()

Reuse

CC BY 4.0

Citation

BibTeX citation:
@online{kainu2021,
  author = {Markus Kainu},
  editor = {},
  title = {Kuvan Labelointi Data.frame:lla {R:n} Ggplot2:ssa},
  date = {2021-04-30},
  url = {https://markuskainu.fi/posts/2021-04-30-ggplot-label},
  langid = {en}
}
For attribution, please cite this work as:
Markus Kainu. 2021. “Kuvan Labelointi Data.frame:lla R:n Ggplot2:ssa .” April 30, 2021. https://markuskainu.fi/posts/2021-04-30-ggplot-label.