diff --git a/CITATION.cff b/CITATION.cff index a3017e0..9adad4c 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -1,15 +1,20 @@ -# ----------------------------------------------------------- -# CITATION file created with {cffr} R package, v0.5.0 +# -------------------------------------------- +# CITATION file created with {cffr} R package # See also: https://docs.ropensci.org/cffr/ -# ----------------------------------------------------------- +# -------------------------------------------- cff-version: 1.2.0 message: 'To cite package "sorvi" in publications use:' type: software license: BSD-2-Clause title: 'sorvi: Functions for Finnish Open Data' -version: 0.8.21 +version: 0.9.01 doi: 10.5281/zenodo.598121 +identifiers: +- type: doi + value: 10.32614/CRAN.package.sorvi +- type: url + value: https://ropengov.github.io/sorvi/ abstract: Misc support functions for rOpenGov and open data downloads. authors: - family-names: Lahti @@ -46,12 +51,12 @@ preferred-citation: orcid: https://orcid.org/0000-0003-2853-2765 doi: 10.5281/zenodo.598121 url: https://github.com/rOpenGov/sorvi - year: '2023' - notes: R package version 0.8.21 + year: '2025' + notes: R package version 0.9.01 repository: https://CRAN.R-project.org/package=sorvi repository-code: https://github.com/ropengov/sorvi url: https://CRAN.R-project.org/package=sorvi -date-released: '2023-08-21' +date-released: '2025-08-21' contact: - family-names: Lahti given-names: Leo @@ -64,12 +69,11 @@ references: url: https://www.R-project.org/ authors: - name: R Core Team - location: - name: Vienna, Austria - year: '2023' institution: name: R Foundation for Statistical Computing - version: '>= 3.5.0' + address: Vienna, Austria + year: '2025' + version: '>= 4.1.0' - type: software title: dlstats abstract: 'dlstats: Download Stats of R Packages' @@ -80,7 +84,8 @@ references: - family-names: Yu given-names: Guangchuang email: guangchuangyu@gmail.com - year: '2023' + year: '2025' + doi: 10.32614/CRAN.package.dlstats - type: software title: dplyr abstract: 'dplyr: A Grammar of Data Manipulation' @@ -104,7 +109,8 @@ references: given-names: Davis email: davis@posit.co orcid: https://orcid.org/0000-0003-4777-038X - year: '2023' + year: '2025' + doi: 10.32614/CRAN.package.dplyr - type: software title: ggplot2 abstract: 'ggplot2: Create Elegant Data Visualisations Using the Grammar of Graphics' @@ -139,7 +145,12 @@ references: - family-names: Dunnington given-names: Dewey orcid: https://orcid.org/0000-0002-9415-4582 - year: '2023' + - family-names: Brand + given-names: Teun + name-particle: van den + orcid: https://orcid.org/0000-0002-9335-7468 + year: '2025' + doi: 10.32614/CRAN.package.ggplot2 - type: software title: gh abstract: 'gh: ''GitHub'' ''API''' @@ -151,7 +162,8 @@ references: given-names: Jennifer - family-names: Wickham given-names: Hadley - year: '2023' + year: '2025' + doi: 10.32614/CRAN.package.gh - type: software title: tidyr abstract: 'tidyr: Tidy Messy Data' @@ -167,7 +179,8 @@ references: email: davis@posit.co - family-names: Girlich given-names: Maximilian - year: '2023' + year: '2025' + doi: 10.32614/CRAN.package.tidyr - type: software title: purrr abstract: 'purrr: Functional Programming Tools' @@ -177,12 +190,13 @@ references: authors: - family-names: Wickham given-names: Hadley - email: hadley@rstudio.com + email: hadley@posit.co orcid: https://orcid.org/0000-0003-4757-117X - family-names: Henry given-names: Lionel - email: lionel@rstudio.com - year: '2023' + email: lionel@posit.co + year: '2025' + doi: 10.32614/CRAN.package.purrr - type: software title: rlang abstract: 'rlang: Functions for Base Types and Core R and ''Tidyverse'' Features' @@ -196,18 +210,8 @@ references: - family-names: Wickham given-names: Hadley email: hadley@posit.co - year: '2023' -- type: software - title: utils - abstract: 'R: A Language and Environment for Statistical Computing' - notes: Imports - authors: - - name: R Core Team - location: - name: Vienna, Austria - year: '2023' - institution: - name: R Foundation for Statistical Computing + year: '2025' + doi: 10.32614/CRAN.package.rlang - type: software title: rvest abstract: 'rvest: Easily Harvest (Scrape) Web Pages' @@ -217,23 +221,25 @@ references: authors: - family-names: Wickham given-names: Hadley - email: hadley@rstudio.com - year: '2023' + email: hadley@posit.co + year: '2025' + doi: 10.32614/CRAN.package.rvest - type: software title: xml2 abstract: 'xml2: Parse XML' notes: Imports - url: https://xml2.r-lib.org/ + url: https://xml2.r-lib.org repository: https://CRAN.R-project.org/package=xml2 authors: - family-names: Wickham given-names: Hadley - email: hadley@rstudio.com - family-names: Hester given-names: Jim - family-names: Ooms given-names: Jeroen - year: '2023' + email: jeroenooms@gmail.com + year: '2025' + doi: 10.32614/CRAN.package.xml2 - type: software title: lubridate abstract: 'lubridate: Make Dealing with Dates a Little Easier' @@ -248,7 +254,8 @@ references: given-names: Garrett - family-names: Wickham given-names: Hadley - year: '2023' + year: '2025' + doi: 10.32614/CRAN.package.lubridate - type: software title: checkmate abstract: 'checkmate: Fast and Versatile Argument Checks' @@ -260,7 +267,8 @@ references: given-names: Michel email: michellang@gmail.com orcid: https://orcid.org/0000-0001-9754-0393 - year: '2023' + year: '2025' + doi: 10.32614/CRAN.package.checkmate - type: software title: magrittr abstract: 'magrittr: A Forward-Pipe Operator for R' @@ -274,7 +282,8 @@ references: - family-names: Wickham given-names: Hadley email: hadley@rstudio.com - year: '2023' + year: '2025' + doi: 10.32614/CRAN.package.magrittr - type: software title: sf abstract: 'sf: Simple Features for R' @@ -286,7 +295,36 @@ references: given-names: Edzer email: edzer.pebesma@uni-muenster.de orcid: https://orcid.org/0000-0001-8049-7069 - year: '2023' + year: '2025' + doi: 10.32614/CRAN.package.sf +- type: software + title: httr2 + abstract: 'httr2: Perform HTTP Requests and Process the Responses' + notes: Imports + url: https://httr2.r-lib.org + repository: https://CRAN.R-project.org/package=httr2 + authors: + - family-names: Wickham + given-names: Hadley + email: hadley@posit.co + year: '2025' + doi: 10.32614/CRAN.package.httr2 +- type: software + title: tibble + abstract: 'tibble: Simple Data Frames' + notes: Imports + url: https://tibble.tidyverse.org/ + repository: https://CRAN.R-project.org/package=tibble + authors: + - family-names: Müller + given-names: Kirill + email: kirill@cynkra.com + orcid: https://orcid.org/0000-0002-1416-3412 + - family-names: Wickham + given-names: Hadley + email: hadley@rstudio.com + year: '2025' + doi: 10.32614/CRAN.package.tibble - type: software title: gridExtra abstract: 'gridExtra: Miscellaneous Functions for "Grid" Graphics' @@ -296,7 +334,8 @@ references: - family-names: Auguie given-names: Baptiste email: baptiste.auguie@gmail.com - year: '2023' + year: '2025' + doi: 10.32614/CRAN.package.gridExtra - type: software title: RColorBrewer abstract: 'RColorBrewer: ColorBrewer Palettes' @@ -306,7 +345,8 @@ references: - family-names: Neuwirth given-names: Erich email: erich.neuwirth@univie.ac.at - year: '2023' + year: '2025' + doi: 10.32614/CRAN.package.RColorBrewer - type: software title: knitr abstract: 'knitr: A General-Purpose Package for Dynamic Report Generation in R' @@ -318,7 +358,8 @@ references: given-names: Yihui email: xie@yihui.name orcid: https://orcid.org/0000-0003-0645-5666 - year: '2023' + year: '2025' + doi: 10.32614/CRAN.package.knitr - type: software title: rmarkdown abstract: 'rmarkdown: Dynamic Documents for R' @@ -361,7 +402,8 @@ references: given-names: Richard email: rich@posit.co orcid: https://orcid.org/0000-0003-3925-190X - year: '2023' + year: '2025' + doi: 10.32614/CRAN.package.rmarkdown - type: software title: Cairo abstract: 'Cairo: R Graphics Device using Cairo Graphics Library for Creating High-Quality @@ -377,7 +419,6 @@ references: - family-names: Horner given-names: Jeffrey email: jeff.horner@vanderbilt.edu - year: '2023' -identifiers: -- type: url - value: https://ropengov.github.io/sorvi/ + year: '2025' + doi: 10.32614/CRAN.package.Cairo + diff --git a/DESCRIPTION b/DESCRIPTION index bb82e2f..ea6e782 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,8 +1,8 @@ Package: sorvi Type: Package Title: Functions for Finnish Open Data -Version: 0.8.21 -Date: 2023-10-20 +Version: 0.9.1 +Date: 2025-09-14 Authors@R: c( person("Leo", "Lahti", , "leo.lahti@iki.fi", role = c("aut", "cre"), comment = c(ORCID = "0000-0001-5537-637X")), @@ -20,7 +20,7 @@ URL: https://github.com/ropengov/sorvi, https://CRAN.R-project.org/package=sorvi, https://ropengov.github.io/sorvi/ Depends: - R (>= 3.6.0) + R (>= 4.1.0) Imports: dlstats, dplyr, @@ -29,13 +29,16 @@ Imports: tidyr, purrr, rlang, - utils, rvest, xml2, lubridate, checkmate, magrittr, - sf + sf, + httr2, + tibble, + R6, + utils Suggests: gridExtra, RColorBrewer, @@ -43,5 +46,5 @@ Suggests: rmarkdown, Cairo Encoding: UTF-8 -RoxygenNote: 7.2.3 +RoxygenNote: 7.3.2 LazyData: true diff --git a/NAMESPACE b/NAMESPACE index 1f25832..5460cee 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,9 +1,14 @@ # Generated by roxygen2: do not edit by hand +export(TurkuWFS) +export(WFSClient) export(cran_downloads) +export(get_classification_df) +export(get_feature_turku) export(get_ifpi_charts) export(get_municipalities) export(gh_issue_stats) +export(list_features_turku) export(load_sorvi_data) importFrom(checkmate,assert_choice) importFrom(checkmate,assert_integer) @@ -16,6 +21,7 @@ importFrom(dplyr,desc) importFrom(dplyr,filter) importFrom(dplyr,group_by) importFrom(dplyr,left_join) +importFrom(dplyr,rename) importFrom(dplyr,select) importFrom(dplyr,summarise) importFrom(dplyr,tibble) @@ -28,10 +34,16 @@ importFrom(ggplot2,ggplot) importFrom(ggplot2,theme) importFrom(ggplot2,theme_set) importFrom(gh,gh) +importFrom(httr2,req_perform) +importFrom(httr2,req_url_query) +importFrom(httr2,request) +importFrom(httr2,resp_body_json) importFrom(lubridate,isoyear) importFrom(magrittr,"%>%") +importFrom(purrr,keep) importFrom(purrr,map) importFrom(purrr,map_chr) +importFrom(purrr,map_dfr) importFrom(purrr,map_int) importFrom(rlang,.data) importFrom(rvest,html_elements) @@ -39,7 +51,14 @@ importFrom(rvest,html_text) importFrom(sf,st_as_sf) importFrom(sf,st_drop_geometry) importFrom(sf,st_is_empty) +importFrom(sf,st_read) +importFrom(tibble,tibble) +importFrom(tidyr,pivot_wider) importFrom(tidyr,tibble) -importFrom(utils,read.csv) +importFrom(utils,URLencode) importFrom(xml2,as_list) importFrom(xml2,read_html) +importFrom(xml2,read_xml) +importFrom(xml2,xml_find_all) +importFrom(xml2,xml_ns) +importFrom(xml2,xml_text) diff --git a/NEWS.md b/NEWS.md index c78d6d3..94f3c59 100755 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,15 @@ +# sorvi 0.9.01 (2025-09-14) + +### NEW FEATURES + +- Added function `get_classification_df()` for downloading classifications from Statistics Finland Classification API +- Added R6 Class `WFSClient` for using basic methods related to WFS APIs. Added subclass `TurkuWFS` that inherits `WFSClient` and has the relevant WFS API URL ready in the constructor. +- Added wrapper functions `list_features_turku()` and `get_feature_turku()` as a more familiar interface for most users. + +### OTHER CHANGES + +- Made `load_sorvi_data()` use classification info downloaded from the API with `get_classification_df()` instead of using datasets included with the package. + # sorvi 0.8.22 (2023-10-20) ### BUG FIXES diff --git a/R/firstlib.R b/R/firstlib.R index 5458a72..7602781 100755 --- a/R/firstlib.R +++ b/R/firstlib.R @@ -1,12 +1,15 @@ # When one has weighed the sun in the balance, and measured the # steps of the moon, and mapped out the seven heavens star by star, # there still remains oneself. Who can calculate the orbit of his own -# soul? - Oscar Wilde +# soul? - Oscar Wilde .onAttach <- function(lib, pkg) { - packageStartupMessage("sorvi - Tools for Finnish Open Data.\nCopyright (C) 2010-2023 Leo Lahti, Juuso Parkkinen, Joona Lehtomaki and Pyry Kantanen \n\nhttp://github.com/ropengov/sorvi \n\n Hard sciences are successful because they deal with soft problems; \n soft sciences are struggling because they deal with hard problems.\n- Von Foerster\n") + packageStartupMessage("sorvi - Tools for Finnish Open Data.\nCopyright (C) 2010-2025 Leo Lahti, Juuso Parkkinen, Joona Lehtomaki and Pyry Kantanen \n\nhttp://github.com/ropengov/sorvi \n\n Hard sciences are successful because they deal with soft problems; \n soft sciences are struggling because they deal with hard problems.\n- Von Foerster\n") + + # dummy to suppress "All declared Imports should be used" NOTE + class <- R6::R6Class() } diff --git a/R/get_statfi_classifications.R b/R/get_statfi_classifications.R new file mode 100644 index 0000000..24cea1e --- /dev/null +++ b/R/get_statfi_classifications.R @@ -0,0 +1,73 @@ +#' @title Get classifications from Statistics Finland API +#' @description Downloads classifications from Statistics Finland +#' @details +#' Concatenated together the name and date parameters form the localId of the +#' classification item. If only localId is used as a parameter, it supersedes the separate +#' date and name parameters. +#' +#' Available classifications and their localId's can be viewed in +#' \url{https://data.stat.fi/api/classifications/v2/classifications?content=url} +#' or +#' \url{https://data.stat.fi/api/classifications/v2/classifications?content=data&lang=fi}. +#' @param name name of the classification, often in format "NAME_1" +#' @param date date of the classification, in format `"1999-01-01"` (year, month, day) +#' @param localId localId of the object. This field supersedes the name and date fields, if not null +#' @param lang either "fi" (default), "en", "sv" or "all" +#' @param content can only be "data" (default) +#' @param meta can be either "min" or "max" (default) +#' @importFrom httr2 request req_url_query req_perform resp_body_json +#' @importFrom purrr map_dfr keep +#' @importFrom tibble tibble +#' @examples +#' \donttest{ +#' maakunta <- get_classification_df("maakunta_1", "20200101", lang = "fi") +#' maakunta_all <- get_classification_df("maakunta_1", "20200101", lang = "all") +#' } +#' +#' @export +get_classification_df <- function(name = NULL, date = NULL, localId = NULL, lang = "fi", content = "data", meta = "max") { + # Only "data" supported for now + if (!is.null(localId)) { + name <- sub("_(\\d{8})$", "", localId) # remove the date part + date <- sub("^.*_(\\d{8})$", "\\1", localId) # keep only the date part + } + + stopifnot(content == "data", !is.null(name), !is.null(date)) + + # Determine which languages to fetch + langs <- if (lang == "all") c("fi", "sv", "en") else lang + + # Helper to fetch one language + fetch_lang <- function(l) { + url <- sprintf("https://data.stat.fi/api/classifications/v2/classifications/%s_%s/classificationItems", + name, date) + + resp <- httr2::request(url) |> + httr2::req_url_query(content = content, meta = meta, lang = l) |> + httr2::req_perform() |> + httr2::resp_body_json() + + items <- resp # list of classification items + + # Flatten items + purrr::map_dfr(items, function(item) { + nm <- purrr::keep(item$classificationItemNames, ~ .x$lang == l) + tibble::tibble( + localId = item$localId, + code = item$code, + level = item$level, + order = item$order, + modified = item$modifiedDate, + parentId = item$parentItemLocalId, + parentCode = item$parentCode, + lang = l, + name = if (length(nm) > 0) nm[[1]]$name else NA + ) + }) + } + + # Fetch all requested languages and combine + df <- purrr::map_dfr(langs, fetch_lang) + + return(df) +} diff --git a/R/load_sorvi_data.R b/R/load_sorvi_data.R index b90a5ea..28c8b5d 100755 --- a/R/load_sorvi_data.R +++ b/R/load_sorvi_data.R @@ -1,39 +1,41 @@ #' @title Supporting Data #' @description Load custom data sets. #' @param data.id data ID to download (see details) -#' @param verbose verbose +#' @details +#' This function is a thin wrapper to `get_classification_df()`. The only +#' value data.id parameter will accept as argument is `translation_provinces`, +#' which will return a data.frame object containing the English and Finnish +#' names of Finnish provinces from 2025 classification. #' -#' @return Data set. The format depends on the data. -#' @details The following data sets are available: -#' \itemize{ -#' \item{translation_provinces}{Translation of Finnish province (maakunta) names (Finnish, English).} -#' } +#' @return a data.frame #' @examples translations <- load_sorvi_data("translation_provinces") -#' @importFrom utils read.csv -#' @export #' @references #' See citation("sorvi") -#' @author Leo Lahti \email{leo.lahti@iki.fi} +#' @author Leo Lahti \email{leo.lahti@@iki.fi} #' @keywords utilities -load_sorvi_data <- function(data.id, verbose = TRUE) { +#' @importFrom tidyr pivot_wider +#' @importFrom dplyr rename select +#' @importFrom rlang .data +#' @export +load_sorvi_data <- function(data.id = "translation_provinces") { + + allow_list <- c("translation_provinces") - # Useful code for retrieving data from other github repos - #url <- ropengov_storage_path("louhos") - #filepath <- paste0(url, data.id, ".rda") - # While trying to be URL agnostic, figure out if storage path is - # pointing to GitHub. If yes, add an extra extension to the url - #if (grepl("github.com", filepath)) { - # filepath <- paste0(filepath, "?raw=true") - #} - #if (verbose) { message(paste("Loading ", filepath, sep = "")) } - #load(url(filepath)) + stopifnot(data.id %in% allow_list) + d <- NULL if ( data.id == "translation_provinces" ) { - f <- system.file("/extdata/translation_provinces.csv", package = "sorvi") - d <- read.csv(f) + maakunta_all <- get_classification_df("maakunta_1", "20250101", lang = "all") + + maakunta_wide <- maakunta_all |> + tidyr::pivot_wider(names_from = .data$lang, values_from = .data$name, names_prefix = "name_") |> + dplyr::rename(Finnish = "name_fi", English = "name_en", Swedish = "name_sv") |> + dplyr::select("English", "Finnish") + + d <- maakunta_wide + d <- as.data.frame(d) } d } - diff --git a/R/sorvi-package.R b/R/sorvi-package.R index 9192e2e..ea5fc84 100755 --- a/R/sorvi-package.R +++ b/R/sorvi-package.R @@ -1,12 +1,11 @@ -#' The sorvi package hosts various functions that are mainly helpful in rOpenGov -#' package maintenance, package authoring and drawing graphs for presentations. +#' The sorvi package hosts various functions that are mainly helpful in rOpenGov +#' package maintenance, package authoring and drawing graphs for presentations. #' Additionally it has some functions that do not (yet) have their own package #' but are useful in some contexts. #' #' @name sorvi-package #' @aliases sorvi -#' @docType package -#' @title Algorithmic Tools for Open Data in Finland +#' @title Algorithmic Tools for Open Data in Finland #' #' @author Leo Lahti, Juuso Parkkinen, Jussi Paananen, Joona Lehtomaki, Einari Happonen, Juuso Haapanen, and Pyry Kantanen \email{louhos@@googlegroups.com} #' @references @@ -14,4 +13,4 @@ #' \url{https://github.com/rOpenGov/sorvi} #' @examples library(sorvi) #' @keywords package -NULL +"_PACKAGE" diff --git a/R/wfs.R b/R/wfs.R new file mode 100644 index 0000000..82f4ea1 --- /dev/null +++ b/R/wfs.R @@ -0,0 +1,135 @@ +#' @title Generic WFS client +#' @description +#' An R6 class for interacting with OGC Web Feature Service (WFS) endpoints. +#' Provides methods to list available feature layers (from GetCapabilities) +#' and to fetch individual layers as \code{sf} objects. +#' +#' @field base_url Base URL of the WFS API, default is NULL +#' @field version Version of the WFS API, default is "1.1.0" +#' +#' @examples +#' \dontrun{ +#' client <- WFSClient$new("https://turku.asiointi.fi/teklaogcweb/wfs.ashx") +#' client$list_features() +#' sf_obj <- client$get_feature("GIS:Aanestysalueet", crs = "EPSG:3067") +#' } +#' @importFrom utils URLencode +#' @importFrom sf st_read +#' @importFrom xml2 read_xml xml_find_all xml_text xml_ns +#' @importFrom tibble tibble +#' +#' @export +WFSClient <- R6::R6Class("WFSClient", + public = list( + base_url = NULL, + version = "1.1.0", + + #' @description Create a new WFS client + #' @param base_url Character. The base URL of the WFS service. + #' @param version Character. WFS version (default: \code{"1.0.0"}). + initialize = function(base_url, version = "1.1.0") { + self$base_url <- base_url + self$version <- version + }, + + #' @description List available feature layers with names, titles, and abstracts. + #' @return A tibble with columns \code{name}, \code{title}, \code{abstract}. + list_features = function() { + url <- sprintf( + "%s?service=WFS&version=%s&request=GetCapabilities", + self$base_url, self$version + ) + caps <- xml2::read_xml(url) + ns <- xml2::xml_ns(caps) + + names <- xml2::xml_find_all(caps, ".//d1:FeatureType/d1:Name", ns) |> xml2::xml_text() + titles <- xml2::xml_find_all(caps, ".//d1:FeatureType/d1:Title", ns) |> xml2::xml_text() + abstracts <- xml2::xml_find_all(caps, ".//d1:FeatureType/d1:Abstract", ns) |> xml2::xml_text() + + tibble::tibble( + name = names, + title = titles, + abstract = ifelse(abstracts == "", NA, abstracts) + ) + }, + + #' @description Fetch a feature collection as an \code{sf} object. + #' @param layer Character. The layer (feature type) name. + #' @param crs Character. Target coordinate reference system (e.g., \code{"EPSG:3067"}). + #' @return An \code{sf} object. + get_feature = function(layer, crs = "EPSG:4326") { + url <- sprintf( + "%s?SERVICE=WFS&VERSION=%s&REQUEST=GetFeature&typeName=%s&srsName=%s", + self$base_url, self$version, + utils::URLencode(layer, reserved = TRUE), + crs + ) + sf::st_read(url, quiet = TRUE) + } + ) +) + +#' @title Turku-specific WFS client +#' @description +#' A specialized subclass of \code{WFSClient} that defaults to the City of Turku’s +#' geoservice WFS endpoint. +#' +#' @examples +#' \dontrun{ +#' turku <- TurkuWFS$new() +#' layers <- turku$list_features() +#' sf_obj <- turku$get_feature("GIS:Aanestysalueet", crs = "EPSG:3067") +#' } +#' +#' @export +TurkuWFS <- R6::R6Class("TurkuWFS", + inherit = WFSClient, + public = list( + #' @description Create a new Turku WFS client + initialize = function() { + super$initialize("https://turku.asiointi.fi/teklaogcweb/wfs.ashx") + } + ) +) + +#' List available WFS feature layers from Turku's geoservice +#' +#' Queries the WFS `GetCapabilities` endpoint of the City of Turku +#' and returns a tibble of available layers, including the machine-readable +#' name, human-readable title, and optional abstract. +#' +#' @return A tibble with columns: \code{name}, \code{title}, \code{abstract}. +#' @examples +#' \dontrun{ +#' turku_features() +#' } +#' @export +list_features_turku <- function() { + client <- TurkuWFS$new() + client$list_features() +} + +#' Download a WFS feature layer from Turku's geoservice +#' +#' Retrieves a feature collection as an \code{sf} object from the City of Turku +#' WFS server, using the specified layer name and coordinate reference system. +#' +#' @param layer Character. The feature type (layer name), e.g. \code{"GIS:Aanestysalueet"}. +#' A full list of layers can be obtained with \code{turku_features()}. +#' @param crs Character. The target coordinate reference system (default: \code{"EPSG:3067"}). +#' +#' @return An \code{sf} object with the requested geometries and attributes. +#' @examples +#' \dontrun{ +#' # List layers +#' turku_features() +#' +#' # Download voting districts in EPSG:3067 +#' aanestysalueet <- turku_get("GIS:Aanestysalueet", crs = "EPSG:3067") +#' plot(sf::st_geometry(aanestysalueet)) +#' } +#' @export +get_feature_turku <- function(layer, crs = "EPSG:3067") { + client <- TurkuWFS$new() + client$get_feature(layer, crs) +} diff --git a/README.Rmd b/README.Rmd index 859dd3b..d85f6b6 100644 --- a/README.Rmd +++ b/README.Rmd @@ -90,7 +90,10 @@ For more examples, check the [package vignette](https://ropengov.github.io/sorvi **Kindly cite this work** as follows: -[Leo Lahti](https://github.com/antagomir/), Juuso Parkkinen, Joona Lehtomaki and Pyry Kantanen (2023). sorvi: Finnish open data toolkit for R. R package version 0.8.21. URL: https://github.com/rOpenGov/sorvi +```{r, comment = "", highlight=FALSE} +citation("sorvi") + +``` We are grateful to Jussi Paananen, Einari Happonen, Juuso Haapanen, and all other [contributors](https://github.com/rOpenGov/sorvi/graphs/contributors)! This project is part of [rOpenGov](https://ropengov.org). diff --git a/README.md b/README.md index 532cf46..b94fb44 100755 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ + [![rOG-badge](https://ropengov.github.io/rogtemplate/reference/figures/ropengov-badge.svg)](https://ropengov.org/) @@ -73,11 +74,11 @@ df #> # Groups: year [5] #> year package n #> -#> 1 2018 eurostat 18932 -#> 2 2019 eurostat 28454 -#> 3 2020 eurostat 31298 -#> 4 2021 eurostat 30307 -#> 5 2022 eurostat 27656 +#> 1 2020 eurostat 31298 +#> 2 2021 eurostat 30307 +#> 3 2022 eurostat 27656 +#> 4 2023 eurostat 41685 +#> 5 2024 eurostat 55423 ``` Get download statistics of various rOpenGov packages over time and draw @@ -110,9 +111,31 @@ vignette](https://ropengov.github.io/sorvi/articles/sorvi_tutorial.html). **Kindly cite this work** as follows: -[Leo Lahti](https://github.com/antagomir/), Juuso Parkkinen, Joona -Lehtomaki and Pyry Kantanen (2023). sorvi: Finnish open data toolkit for -R. R package version 0.8.21. URL: +``` text +citation("sorvi") +Kindly cite the sorvi R package as follows: + +To cite 'sorvi' in publications use: + + Lahti L, Parkkinen J, Lehtomaki J, Haapanen J, Happonen E, Paananen + J, Kantanen P (2025). _sorvi: Functions for Finnish Open Data_. + doi:10.32614/CRAN.package.sorvi + , R package version + 0.9.1, . + +A BibTeX entry for LaTeX users is + + @Manual{R-sorvi, + title = {{sorvi: Functions for Finnish Open Data}}, + doi = {10.32614/CRAN.package.sorvi}, + author = {Leo Lahti and Juuso Parkkinen and Joona Lehtomaki and Juuso Haapanen and Einari Happonen and Jussi Paananen and Pyry Kantanen}, + url = {https://github.com/rOpenGov/sorvi}, + year = {2025}, + note = {R package version 0.9.1}, + } + +Many thanks for all contributors! +``` We are grateful to Jussi Paananen, Einari Happonen, Juuso Haapanen, and all other diff --git a/inst/CITATION b/inst/CITATION index b8caf3d..c89ce4b 100755 --- a/inst/CITATION +++ b/inst/CITATION @@ -1,11 +1,16 @@ -citHeader("Kindly cite the sorvi R package as follows:") +year <- sub("-.*", "", meta$Date) +version_note <- paste("R package version", meta$Version) +pkg <- meta$Package +title <- gsub("'", "", meta$Title) +doi <- paste0("10.32614/CRAN.package.", pkg) -year <- sub(".*(2[[:digit:]]{3})-.*", "\\1", meta$Date, perl = TRUE) -vers <- paste("R package version", meta$Version) +citHeader("Kindly cite the sorvi R package as follows:") -bibentry(bibtype="misc", - title = "sorvi: Finnish open government data toolkit for R", - author = c( +bibentry(bibtype = "Manual", + header = sprintf("To cite '%s' in publications use:", pkg), + title = sprintf("{%s: %s}", pkg, title), + doi = doi, + author = c( person(given ="Leo", family="Lahti", email = "leo.lahti@iki.fi"), person(given ="Juuso", family="Parkkinen"), person(given ="Joona", family="Lehtomaki"), @@ -13,18 +18,11 @@ bibentry(bibtype="misc", person(given ="Einari", family="Happonen"), person(given ="Jussi", family="Paananen"), person(given = "Pyry", family="Kantanen") - ), - doi = "10.5281/zenodo.598121", + ), url = "https://github.com/rOpenGov/sorvi", - journal = "", year = year, - note = vers, - textVersion = - paste("Leo Lahti, Juuso Parkkinen, Joona Lehtomaki, Juuso Haapanen, Einari Happonen, Jussi Paananen and Pyry Kantanen (",year,"). ", - "sorvi: Finnish open data toolkit for R. ", - vers, - " URL: https://github.com/rOpenGov/sorvi", - sep="") - ) + note = version_note, + key = paste0("R-", pkg) + ) citFooter("\nMany thanks for all contributors!") diff --git a/man/TurkuWFS.Rd b/man/TurkuWFS.Rd new file mode 100644 index 0000000..0720ae7 --- /dev/null +++ b/man/TurkuWFS.Rd @@ -0,0 +1,63 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/wfs.R +\name{TurkuWFS} +\alias{TurkuWFS} +\title{Turku-specific WFS client} +\description{ +A specialized subclass of \code{WFSClient} that defaults to the City of Turku’s +geoservice WFS endpoint. +} +\examples{ +\dontrun{ + turku <- TurkuWFS$new() + layers <- turku$list_features() + sf_obj <- turku$get_feature("GIS:Aanestysalueet", crs = "EPSG:3067") +} + +} +\section{Super class}{ +\code{\link[sorvi:WFSClient]{sorvi::WFSClient}} -> \code{TurkuWFS} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-TurkuWFS-new}{\code{TurkuWFS$new()}} +\item \href{#method-TurkuWFS-clone}{\code{TurkuWFS$clone()}} +} +} +\if{html}{\out{ +
Inherited methods + +
+}} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TurkuWFS-new}{}}} +\subsection{Method \code{new()}}{ +Create a new Turku WFS client +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{TurkuWFS$new()}\if{html}{\out{
}} +} + +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-TurkuWFS-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{TurkuWFS$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/WFSClient.Rd b/man/WFSClient.Rd new file mode 100644 index 0000000..e886689 --- /dev/null +++ b/man/WFSClient.Rd @@ -0,0 +1,107 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/wfs.R +\name{WFSClient} +\alias{WFSClient} +\title{Generic WFS client} +\description{ +An R6 class for interacting with OGC Web Feature Service (WFS) endpoints. +Provides methods to list available feature layers (from GetCapabilities) +and to fetch individual layers as \code{sf} objects. +} +\examples{ +\dontrun{ + client <- WFSClient$new("https://turku.asiointi.fi/teklaogcweb/wfs.ashx") + client$list_features() + sf_obj <- client$get_feature("GIS:Aanestysalueet", crs = "EPSG:3067") +} +} +\section{Public fields}{ +\if{html}{\out{
}} +\describe{ +\item{\code{base_url}}{Base URL of the WFS API, default is NULL} + +\item{\code{version}}{Version of the WFS API, default is "1.1.0"} +} +\if{html}{\out{
}} +} +\section{Methods}{ +\subsection{Public methods}{ +\itemize{ +\item \href{#method-WFSClient-new}{\code{WFSClient$new()}} +\item \href{#method-WFSClient-list_features}{\code{WFSClient$list_features()}} +\item \href{#method-WFSClient-get_feature}{\code{WFSClient$get_feature()}} +\item \href{#method-WFSClient-clone}{\code{WFSClient$clone()}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-WFSClient-new}{}}} +\subsection{Method \code{new()}}{ +Create a new WFS client +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{WFSClient$new(base_url, version = "1.1.0")}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{base_url}}{Character. The base URL of the WFS service.} + +\item{\code{version}}{Character. WFS version (default: \code{"1.0.0"}).} +} +\if{html}{\out{
}} +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-WFSClient-list_features}{}}} +\subsection{Method \code{list_features()}}{ +List available feature layers with names, titles, and abstracts. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{WFSClient$list_features()}\if{html}{\out{
}} +} + +\subsection{Returns}{ +A tibble with columns \code{name}, \code{title}, \code{abstract}. +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-WFSClient-get_feature}{}}} +\subsection{Method \code{get_feature()}}{ +Fetch a feature collection as an \code{sf} object. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{WFSClient$get_feature(layer, crs = "EPSG:4326")}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{layer}}{Character. The layer (feature type) name.} + +\item{\code{crs}}{Character. Target coordinate reference system (e.g., \code{"EPSG:3067"}).} +} +\if{html}{\out{
}} +} +\subsection{Returns}{ +An \code{sf} object. +} +} +\if{html}{\out{
}} +\if{html}{\out{}} +\if{latex}{\out{\hypertarget{method-WFSClient-clone}{}}} +\subsection{Method \code{clone()}}{ +The objects of this class are cloneable with this method. +\subsection{Usage}{ +\if{html}{\out{
}}\preformatted{WFSClient$clone(deep = FALSE)}\if{html}{\out{
}} +} + +\subsection{Arguments}{ +\if{html}{\out{
}} +\describe{ +\item{\code{deep}}{Whether to make a deep clone.} +} +\if{html}{\out{
}} +} +} +} diff --git a/man/figures/README-example_visualize-1.png b/man/figures/README-example_visualize-1.png index cf11e1c..2a7451c 100644 Binary files a/man/figures/README-example_visualize-1.png and b/man/figures/README-example_visualize-1.png differ diff --git a/man/get_classification_df.Rd b/man/get_classification_df.Rd new file mode 100644 index 0000000..417af8e --- /dev/null +++ b/man/get_classification_df.Rd @@ -0,0 +1,48 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/get_statfi_classifications.R +\name{get_classification_df} +\alias{get_classification_df} +\title{Get classifications from Statistics Finland API} +\usage{ +get_classification_df( + name = NULL, + date = NULL, + localId = NULL, + lang = "fi", + content = "data", + meta = "max" +) +} +\arguments{ +\item{name}{name of the classification, often in format "NAME_1"} + +\item{date}{date of the classification, in format `"1999-01-01"` (year, month, day)} + +\item{localId}{localId of the object. This field supersedes the name and date fields, if not null} + +\item{lang}{either "fi" (default), "en", "sv" or "all"} + +\item{content}{can only be "data" (default)} + +\item{meta}{can be either "min" or "max" (default)} +} +\description{ +Downloads classifications from Statistics Finland +} +\details{ +Concatenated together the name and date parameters form the localId of the +classification item. If only localId is used as a parameter, it supersedes the separate +date and name parameters. + +Available classifications and their localId's can be viewed in +\url{https://data.stat.fi/api/classifications/v2/classifications?content=url} +or +\url{https://data.stat.fi/api/classifications/v2/classifications?content=data&lang=fi}. +} +\examples{ +\donttest{ +maakunta <- get_classification_df("maakunta_1", "20200101", lang = "fi") +maakunta_all <- get_classification_df("maakunta_1", "20200101", lang = "all") +} + +} diff --git a/man/get_feature_turku.Rd b/man/get_feature_turku.Rd new file mode 100644 index 0000000..45c0010 --- /dev/null +++ b/man/get_feature_turku.Rd @@ -0,0 +1,31 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/wfs.R +\name{get_feature_turku} +\alias{get_feature_turku} +\title{Download a WFS feature layer from Turku's geoservice} +\usage{ +get_feature_turku(layer, crs = "EPSG:3067") +} +\arguments{ +\item{layer}{Character. The feature type (layer name), e.g. \code{"GIS:Aanestysalueet"}. +A full list of layers can be obtained with \code{turku_features()}.} + +\item{crs}{Character. The target coordinate reference system (default: \code{"EPSG:3067"}).} +} +\value{ +An \code{sf} object with the requested geometries and attributes. +} +\description{ +Retrieves a feature collection as an \code{sf} object from the City of Turku +WFS server, using the specified layer name and coordinate reference system. +} +\examples{ +\dontrun{ + # List layers + turku_features() + + # Download voting districts in EPSG:3067 + aanestysalueet <- turku_get("GIS:Aanestysalueet", crs = "EPSG:3067") + plot(sf::st_geometry(aanestysalueet)) +} +} diff --git a/man/list_features_turku.Rd b/man/list_features_turku.Rd new file mode 100644 index 0000000..41ee22d --- /dev/null +++ b/man/list_features_turku.Rd @@ -0,0 +1,21 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/wfs.R +\name{list_features_turku} +\alias{list_features_turku} +\title{List available WFS feature layers from Turku's geoservice} +\usage{ +list_features_turku() +} +\value{ +A tibble with columns: \code{name}, \code{title}, \code{abstract}. +} +\description{ +Queries the WFS `GetCapabilities` endpoint of the City of Turku +and returns a tibble of available layers, including the machine-readable +name, human-readable title, and optional abstract. +} +\examples{ +\dontrun{ + turku_features() +} +} diff --git a/man/load_sorvi_data.Rd b/man/load_sorvi_data.Rd index 999a67f..8c5d19a 100644 --- a/man/load_sorvi_data.Rd +++ b/man/load_sorvi_data.Rd @@ -4,24 +4,22 @@ \alias{load_sorvi_data} \title{Supporting Data} \usage{ -load_sorvi_data(data.id, verbose = TRUE) +load_sorvi_data(data.id = "translation_provinces") } \arguments{ \item{data.id}{data ID to download (see details)} - -\item{verbose}{verbose} } \value{ -Data set. The format depends on the data. +a data.frame } \description{ Load custom data sets. } \details{ -The following data sets are available: - \itemize{ - \item{translation_provinces}{Translation of Finnish province (maakunta) names (Finnish, English).} - } +This function is a thin wrapper to `get_classification_df()`. The only +value data.id parameter will accept as argument is `translation_provinces`, +which will return a data.frame object containing the English and Finnish +names of Finnish provinces from 2025 classification. } \examples{ translations <- load_sorvi_data("translation_provinces") diff --git a/man/sorvi-package.Rd b/man/sorvi-package.Rd index cca7379..e1ce5ab 100644 --- a/man/sorvi-package.Rd +++ b/man/sorvi-package.Rd @@ -6,8 +6,8 @@ \alias{sorvi} \title{Algorithmic Tools for Open Data in Finland} \description{ -The sorvi package hosts various functions that are mainly helpful in rOpenGov -package maintenance, package authoring and drawing graphs for presentations. +The sorvi package hosts various functions that are mainly helpful in rOpenGov +package maintenance, package authoring and drawing graphs for presentations. Additionally it has some functions that do not (yet) have their own package but are useful in some contexts. } @@ -17,6 +17,16 @@ library(sorvi) \references{ See citation("sorvi") \url{https://github.com/rOpenGov/sorvi} +} +\seealso{ +Useful links: +\itemize{ + \item \url{https://github.com/ropengov/sorvi} + \item \url{https://CRAN.R-project.org/package=sorvi} + \item \url{https://ropengov.github.io/sorvi/} + \item Report bugs at \url{https://github.com/ropengov/sorvi/issues} +} + } \author{ Leo Lahti, Juuso Parkkinen, Jussi Paananen, Joona Lehtomaki, Einari Happonen, Juuso Haapanen, and Pyry Kantanen \email{louhos@googlegroups.com} diff --git a/vignettes/sorvi_tutorial.Rmd b/vignettes/sorvi_tutorial.Rmd index 2d028d9..23cda43 100755 --- a/vignettes/sorvi_tutorial.Rmd +++ b/vignettes/sorvi_tutorial.Rmd @@ -81,6 +81,18 @@ ggplot(map1931) + geom_sf() See sorvi article [Finnish historical maps with sorvi R package](https://ropengov.github.io/sorvi/articles/finnish-historical-maps.html) for more information and examples. +## Data from Statistics Finland Classification API + +Basic usage example: + +```{r} +maakunta <- get_classification_df("maakunta_1", "20200101", lang = "fi") +head(maakunta) +suuruusluokka <- get_classification_df("suuruusluokka_1", "20180101", lang = "all") + +``` + + ## Licensing and Citations This work can be freely used, modified and distributed under the