diff --git a/.Rbuildignore b/.Rbuildignore index f616b607..5b261fd3 100755 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -1,24 +1,19 @@ +^renv$ +^renv\.lock$ +^CRAN-RELEASE$ # Extra material related but not to be included in the package inst/extras README.Rmd +README.html index.* # pkgdown docs + # Vignette -./vignettes/2015-RJournal -./vignettes/2017_RJournal_manuscript/* -./vignettes/cheatsheet/ -./vignettes/cheatsheet.Rmd -./vignettes/blogposts.Rmd -./vignettes/publications.Rmd -./vignettes/NUTS_2010_60M_SH/* -./vignettes/NUTS_2010_60M_SH.zip -./vignettes/NUTS_2010.xls -./vignettes/zipfile -./vignettes/figure -./vignettes/fig -./vignettes/cheatsheet +./vignettes/*.Rmd +#./vignettes/fig +#./vignettes/fig/ ./figure$ ./cache$ # Git related @@ -32,7 +27,6 @@ docs ^\.Rproj\.user$ ^packrat/ ^\.Rprofile$ -^NEWS.md$ ^cran-comments\.md$ ^data-raw$ ^revdep$ @@ -41,3 +35,11 @@ docs ^appveyor\.yml$ ^_pkgdown\.yml$ ^docs$ +^doc$ +^Meta$ +^\.github$ +^codecov\.yml$ +^pkgdown$ +^\._pkgdown\.yml$ +^vignettes/articles$ +^CRAN-SUBMISSION$ diff --git a/.Rinstignore b/.Rinstignore new file mode 100755 index 00000000..39b10844 --- /dev/null +++ b/.Rinstignore @@ -0,0 +1,2 @@ +inst/doc/fig + diff --git a/.github/.gitignore b/.github/.gitignore new file mode 100755 index 00000000..00fdd192 --- /dev/null +++ b/.github/.gitignore @@ -0,0 +1,3 @@ +*.html +R-version +*.Rds diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..3de2551d --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + - package-ecosystem: "github-actions" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "weekly" + diff --git a/.github/workflows/check-full.yaml b/.github/workflows/check-full.yaml new file mode 100644 index 00000000..7a47123a --- /dev/null +++ b/.github/workflows/check-full.yaml @@ -0,0 +1,47 @@ +# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples +# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help +on: + workflow_dispatch: + schedule: + - cron: '0 0 * * 0' + +name: R-CMD-check (full) +jobs: + R-CMD-check: + runs-on: ${{ matrix.config.os }} + + name: ${{ matrix.config.os }} (${{ matrix.config.r }}) + + strategy: + fail-fast: false + matrix: + config: + - {os: macos-latest, r: 'release'} + - {os: windows-latest, r: 'release'} + - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} + - {os: ubuntu-latest, r: 'release'} + - {os: ubuntu-latest, r: 'oldrel-1'} + + env: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + R_KEEP_PKG_SOURCE: yes + + steps: + - uses: actions/checkout@v5 + + - uses: r-lib/actions/setup-pandoc@v2 + + - uses: r-lib/actions/setup-r@v2 + with: + r-version: ${{ matrix.config.r }} + http-user-agent: ${{ matrix.config.http-user-agent }} + use-public-rspm: true + + - uses: r-lib/actions/setup-r-dependencies@v2 + with: + extra-packages: any::rcmdcheck + needs: check + + - uses: r-lib/actions/check-r-package@v2 + with: + upload-snapshots: true \ No newline at end of file diff --git a/.github/workflows/check-standard.yaml b/.github/workflows/check-standard.yaml new file mode 100644 index 00000000..b60da2fb --- /dev/null +++ b/.github/workflows/check-standard.yaml @@ -0,0 +1,29 @@ +# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples +# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help +on: + push: + branches: [main, master] + pull_request: + branches: [main, master] + +name: R-CMD-check (standard) + +jobs: + R-CMD-check: + runs-on: ubuntu-latest + env: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + R_KEEP_PKG_SOURCE: yes + steps: + - uses: actions/checkout@v5 + + - uses: r-lib/actions/setup-r@v2 + with: + use-public-rspm: true + + - uses: r-lib/actions/setup-r-dependencies@v2 + with: + extra-packages: any::rcmdcheck + needs: check + + - uses: r-lib/actions/check-r-package@v2 \ No newline at end of file diff --git a/.github/workflows/rogtemplate-gh-pages.yaml b/.github/workflows/rogtemplate-gh-pages.yaml new file mode 100644 index 00000000..027815f9 --- /dev/null +++ b/.github/workflows/rogtemplate-gh-pages.yaml @@ -0,0 +1,58 @@ +# Workflow derived from https://github.com/r-lib/actions/tree/master/examples +# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help +# Workflow triggering derived from: https://stevenmortimer.com/running-github-actions-sequentially/ +on: + push: + branches: [main, master] + tags: ['*'] + paths-ignore: + - 'README.Rmd' + repository_dispatch: + types: [trigger-pkgdown-workflow] + workflow_dispatch: + +name: rogtemplate-gh-pages + +jobs: + rogtemplate-gh-pages: + runs-on: ubuntu-latest + env: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v5 + + - uses: r-lib/actions/setup-pandoc@v2 + + - uses: r-lib/actions/setup-r@v2 + with: + use-public-rspm: true + + - uses: r-lib/actions/setup-r-dependencies@v2 + with: + needs: website + extra-packages: + local::. + any::pkgdown + ropengov/rogtemplate + any::rcmdcheck + + - name: Build logo if not present and prepare template + run: | + # Check that logo is not present + if (isFALSE(file.exists(file.path("man", "figures", "logo.png")) || + file.exists(file.path("man", "figures", "logo.png")))) { + rogtemplate::rog_logo() + } else { + + message("The package already has a logo") + } + + rogtemplate::rog_add_template_pkgdown() + + shell: Rscript {0} + + - name: Deploy package + run: | + git config --local user.name "github-actions[bot]" + git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com" + Rscript -e 'pkgdown::deploy_to_branch(new_process = FALSE)' diff --git a/.github/workflows/test-coverage.yaml b/.github/workflows/test-coverage.yaml new file mode 100644 index 00000000..6aa95277 --- /dev/null +++ b/.github/workflows/test-coverage.yaml @@ -0,0 +1,32 @@ +# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples +# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help +on: + push: + branches: [main, master] + pull_request: + branches: [main, master] + +name: test-coverage + +jobs: + test-coverage: + runs-on: ubuntu-latest + env: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + + steps: + - uses: actions/checkout@v5 + + - uses: r-lib/actions/setup-r@v2 + with: + use-public-rspm: true + + - uses: r-lib/actions/setup-r-dependencies@v2 + with: + extra-packages: any::covr + needs: coverage + + - name: Test coverage + run: covr::codecov(token = Sys.getenv("CODECOV_TOKEN"), quiet = FALSE) + shell: Rscript {0} \ No newline at end of file diff --git a/.github/workflows/tidy_code.yaml b/.github/workflows/tidy_code.yaml new file mode 100644 index 00000000..48cb262a --- /dev/null +++ b/.github/workflows/tidy_code.yaml @@ -0,0 +1,63 @@ +# Workflow derived from https://github.com/r-lib/actions/blob/master/.github/workflows/render-readme.yaml +# and https://fromthebottomoftheheap.net/2020/04/30/rendering-your-readme-with-github-actions/ +# Workflow triggering derived from: https://stevenmortimer.com/running-github-actions-sequentially/ +on: + workflow_dispatch: + +# This is triggered manually + + +name: Tidy code + +jobs: + tidy: + name: Tidy code + runs-on: macOS-latest + env: + GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} + steps: + - uses: actions/checkout@v5 + + - uses: r-lib/actions/setup-pandoc@v2 + + - uses: r-lib/actions/setup-r@v2 + with: + use-public-rspm: true + + - uses: r-lib/actions/setup-r-dependencies@v2 + with: + extra-packages: | + local::. + any::usethis + any::styler + any::urlchecker + any::devtools + any::roxygen2 + ropengov/rogtemplate + needs: website + - name: Tidy code + run: | + usethis::use_tidy_description() + tools::resaveRdaFiles("data") + tools::resaveRdaFiles("R") + styler::style_pkg(filetype = c("R", "Rmd")) + urlchecker::url_update() + devtools::build_readme() + roxygen2::roxygenise() + shell: Rscript {0} + + + - name: Commit results + run: | + git config --local user.name "github-actions[bot]" + git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com" + git add -A + git commit -m 'Tidy code' || echo "No changes to commit" + git push origin || echo "No changes to commit" + + - name: Trigger pkgdown workflow + if: success() + run: | + git config --local user.name "github-actions[bot]" + git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com" + Rscript -e 'pkgdown::deploy_to_branch(new_process = FALSE)' \ No newline at end of file diff --git a/.gitignore b/.gitignore index e9fa3acc..20546d8a 100755 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,15 @@ -_pkgdown.yml -docs/docsearch.js -docs/articles/2015-RJournal/response.txt +.Rproj.user +.Rhistory +.RData +.Ruserdata +.Rdata +.httr-oauth +.DS_Store +inst/doc *Rcheck* -inst/extras +inst/extras/* +application/* +!inst/extras/cheatsheet/ inst/extras/..Rcheck *~ */~ @@ -12,7 +19,6 @@ vignettes/*_tutorial.html vignettes/*~ vignettes/tmp* vignettes/fig/*.pdf -.Rproj.user eurostat.Rproj vignettes/NUTS_2010.xls vignettes/NUTS_2010_60M_SH* @@ -20,6 +26,9 @@ vignettes/zipfile NUTS_2010.xls zipfile packrat/lib*/ -.Rhistory - /revdep/.cache.rds +doc +Meta +/doc/ +/Meta/ +docs diff --git a/.travis.yml b/.travis.yml deleted file mode 100755 index a8766783..00000000 --- a/.travis.yml +++ /dev/null @@ -1,173 +0,0 @@ -language: r -sudo: required -cache: packages -dist: trusty - -warnings_are_errors: false - -notifications: - email: - - leo.lahti@iki.fi - - -r_packages: - - broom - - Cairo - - classInt - - curl - - devtools - - ggplot2 - - httr - - jsonlite - - knitr - - lubridate - - gdalUtils - - geojson - - geojsonio - - geojsonlint - - jqr - - mapview - - mapproj - - plotrix - - protolite - - rgdal - - RColorBrewer - - readr - - rmarkdown - - rmapshaper - - roxygen2 - - rsdmx - - rvest - - sf - - sp - - tmap - - tmaptools - - testthat - - V8 - -r_github_packages: - - jimhester/covr - - r-dbi/DBI - - r-dbi/RPostgres - - -addons: - postgresql: "9.6" - apt: - sources: - - sourceline: 'ppa:opencpu/jq' - - sourceline: 'ppa:ubuntugis/ubuntugis-unstable' - - sourceline: 'deb http://apt.postgresql.org/pub/repos/apt/ trusty-pgdg main' - key_url: 'https://www.postgresql.org/media/keys/ACCC4CF8.asc' - packages: - - libprotobuf-dev - - protobuf-compiler - - libv8-3.14-dev - - libjq-dev - - libudunits2-dev - - libproj-dev - - libgeos-dev - - libspatialite-dev - - libgdal-dev - - libjson-c-dev - - postgresql-server-dev-9.6 - -env: - global: - - WARNINGS_ARE_ERRORS=1 - - GITHUB_REPO: ropengov/eurostat - -r_build_args: "--no-resave-data --no-build-vignettes" -r_check_args: "--as-cran --no-build-vignettes" - -apt_packages: - - libudunits2-dev - - udunits2 - - libv8-dev - - libprotobuf-dev - - libprotoc-dev - - libcairo2-dev - - protobuf-compiler - - valgrind - - libgdal20 - - libspatialite-dev - - libproj-dev - - libgeos-dev - - libgdal1-dev - - libgdal-dev - - libgeos-c1v5 - - libjq-dev - - netcdf-bin - -before_install: - - pip install --user codecov - - sudo apt-get -qq update - - sudo apt-get install -y libxml2-dev - - sudo apt-get install -y libprotobuf-dev protobuf-compiler - - sudo apt-get install libssl-dev - - sudo apt-get install libcairo2-dev - - sudo add-apt-repository ppa:ubuntugis/ubuntugis-unstable --yes - - sudo add-apt-repository -y ppa:opencpu/jq - - sudo apt-get --yes --force-yes update -qq - - sudo apt-get --yes install npm - - # install postgis from source: - - wget http://download.osgeo.org/postgis/source/postgis-2.3.2.tar.gz - - (mv postgis* /tmp; cd /tmp; tar xzf postgis-2.3.2.tar.gz) - - (cd /tmp/postgis-2.3.2 ; ./configure; make; sudo make install) - - # activate liblwgeom by: - - sudo ldconfig - # create postgis databases: - - sudo service postgresql restart - - createdb postgis - - psql -d postgis -c "CREATE EXTENSION postgis;" - - psql -d postgis -c "GRANT CREATE ON DATABASE postgis TO travis" - - psql -d postgis -c "GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO travis" - - createdb empty - - psql -d empty -c "CREATE EXTENSION postgis;" - # - R -q -e 'install.packages("devtools"); devtools::install_github("ropenscilabs/tic"); tic::prepare_all_stages()' - - - - Rscript -e 'install.packages("broom",repos="http://cran.us.r-project.org")' - - Rscript -e 'install.packages("classInt")' - - Rscript -e 'install.packages("jsonlite")' - - Rscript -e 'install.packages("curl")' - - Rscript -e 'install.packages("httr")' - - Rscript -e 'install.packages("RColorBrewer")' - - Rscript -e 'install.packages("sp")' - - Rscript -e 'install.packages("readr")' - - Rscript -e 'install.packages("Cairo")' - - Rscript -e 'install.packages("ggplot2")' - - Rscript -e 'install.packages("lubridate")' - - Rscript -e 'install.packages("mapproj")' - - Rscript -e 'install.packages("plotrix")' - - Rscript -e 'install.packages("rmarkdown")' - - Rscript -e 'install.packages("roxygen2")' - - Rscript -e 'install.packages("rsdmx")' - - Rscript -e 'install.packages("rvest")' - - Rscript -e 'install.packages("testthat")' - - Rscript -e 'install.packages("knitr")' - - Rscript -e 'install.packages("tmap", repos="http://cran.us.r-project.org")' - - Rscript -e 'install.packages("sf", repos="http://cran.us.r-project.org")' - - -install: - - . $HOME/.nvm/nvm.sh - - nvm install stable - - nvm use stable - - npm install -g mapshaper - - npm install -g geojson - -r: -- release -- devel - -after_success: - #- Rscript -e 'covr::codecov()' - - dropdb postgis - - createdb postgis - - psql -d postgis -c "CREATE EXTENSION postgis;" - - psql -d postgis -c "GRANT CREATE ON DATABASE postgis TO travis" - - R -q -e 'covr::codecov(quiet = FALSE)' - diff --git a/DESCRIPTION b/DESCRIPTION index 9083550c..ea2c8b76 100755 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,58 +1,76 @@ -Package: eurostat Type: Package +Package: eurostat Title: Tools for Eurostat Open Data -Date: 2018-10-16 -Version: 3.2.93 -Encoding: UTF-8 +Version: 4.0.0 +Date: 2023-12-19 Authors@R: c( - person("Leo", "Lahti", email = "leo.lahti@iki.fi", role = c("aut", "cre")), - person("Janne", "Huovari", role = "aut"), - person("Markus", "Kainu", role = "aut"), - person("Przemyslaw" , "Biecek", role = "aut"), - person("Joona", "Lehtomaki", role = "ctb"), - person("Francois", "Briatte", role = "ctb"), - person("Oliver", "Reiter", role = "ctb")) -Maintainer: Leo Lahti -MailingList: rOpenGov + person("Leo", "Lahti", , "leo.lahti@iki.fi", role = c("aut", "cre"), + comment = c(ORCID = "0000-0001-5537-637X")), + person("Janne", "Huovari", role = "aut"), + person("Markus", "Kainu", role = "aut"), + person("Przemyslaw", "Biecek", role = "aut"), + person("Daniel", "Antal", role = "ctb"), + person("Diego", "Hernangomez", role = "ctb", + comment = c(ORCID = "0000-0001-8457-4658")), + person("Joona", "Lehtomaki", role = "ctb"), + person("Francois", "Briatte", role = "ctb"), + person("Reto", "Stauffer", role = "ctb"), + person("Paul", "Rougieux", role = "ctb"), + person("Anna", "Vasylytsya", role = "ctb"), + person("Oliver", "Reiter", role = "ctb"), + person("Pyry", "Kantanen", role = "ctb", + comment = c(ORCID = "0000-0003-2853-2765")), + person("Enrico", "Spinielli", , "enrico.spinielli@gmail.com", role = "ctb", + comment = c(ORCID = "0000-0001-8584-9131")) + ) Description: Tools to download data from the Eurostat database - together with search and - manipulation utilities. + together with search and manipulation + utilities. License: BSD_2_clause + file LICENSE +URL: https://ropengov.github.io/eurostat/, + https://github.com/rOpenGov/eurostat +BugReports: https://github.com/rOpenGov/eurostat/issues Depends: - methods, - R (>= 3.4.0) + R (>= 3.6.0) Imports: - broom, classInt, - dplyr, - httr, + countrycode, + curl, + digest, + dplyr, + httr2 (>= 0.2.3), + ISOweek, jsonlite, - RColorBrewer, - readr, - sf, - sp, + lubridate, + rappdirs, + readr, + RefManageR, + regions, + rlang, stringi, stringr, tibble, - tidyr, - countrycode + tidyr (>= 1.0.0), + xml2, + data.table (>= 1.14.8) Suggests: - Cairo, - ggplot2, - knitr, - lubridate, - mapproj, - plotrix, + giscoR, + knitr, rmarkdown, - roxygen2, - rsdmx, - rvest, - testthat, - tmap + sf, + testthat (>= 3.0.0) +VignetteBuilder: + knitr +Config/Needs/website: ggplot2, tmap, styler, sessioninfo, + ropengov/rogtemplate, ragg +Config/testthat/edition: 3 +Config/testthat/parallel: false +Encoding: UTF-8 LazyData: true -URL: https://ropengov.github.io/eurostat -BugReports: https://github.com/ropengov/eurostat/issues -VignetteBuilder: knitr +MailingList: rOpenGov NeedsCompilation: no Repository: CRAN -RoxygenNote: 6.1.0 +Roxygen: list(markdown = TRUE) +RoxygenNote: 7.2.3 +X-schema.org-isPartOf: http://ropengov.org/ +X-schema.org-keywords: ropengov diff --git a/LICENSE b/LICENSE index 684e34df..1de69c39 100755 --- a/LICENSE +++ b/LICENSE @@ -1,2 +1,2 @@ -YEAR: 2014-2018 -COPYRIGHT HOLDER: Leo Lahti, Janne Huovari, Markus Kainu, Przemyslaw Biecek +YEAR: 2014-2022 +COPYRIGHT HOLDER: Leo Lahti, Janne Huovari, Markus Kainu, Przemyslaw Biecek \ No newline at end of file diff --git a/NAMESPACE b/NAMESPACE index ccc68cf6..2ecf819b 100755 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,48 +1,96 @@ # Generated by roxygen2: do not edit by hand +export(add_nuts_level) +export(check_access_to_data) export(clean_eurostat_cache) export(cut_to_classes) export(dic_order) export(eurotime2date) export(eurotime2num) +export(get_bibentry) export(get_eurostat) export(get_eurostat_dic) +export(get_eurostat_folder) export(get_eurostat_geospatial) +export(get_eurostat_interactive) export(get_eurostat_json) export(get_eurostat_toc) export(grepEurostatTOC) export(harmonize_country_code) +export(harmonize_geo_code) export(label_eurostat) export(label_eurostat_tables) export(label_eurostat_vars) +export(list_eurostat_cache_items) +export(recode_nuts) +export(recode_to_nuts_2013) +export(recode_to_nuts_2016) export(search_eurostat) -import(methods) -importFrom(RColorBrewer,brewer.pal) -importFrom(broom,tidy) +export(set_eurostat_cache_dir) +export(validate_geo_code) +export(validate_nuts_regions) +importFrom(ISOweek,ISOweek2date) +importFrom(RefManageR,BibEntry) +importFrom(RefManageR,toBiblatex) importFrom(classInt,classIntervals) +importFrom(countrycode,countrycode) +importFrom(curl,curl_download) +importFrom(data.table,":=") +importFrom(data.table,.SD) +importFrom(data.table,fread) +importFrom(data.table,melt) +importFrom(data.table,setDT) +importFrom(digest,digest) importFrom(dplyr,"%>%") +importFrom(dplyr,case_when) +importFrom(dplyr,coalesce) importFrom(dplyr,filter) -importFrom(dplyr,left_join) +importFrom(dplyr,inner_join) importFrom(dplyr,mutate) -importFrom(dplyr,select) -importFrom(httr,GET) -importFrom(httr,build_url) -importFrom(httr,content) -importFrom(httr,status_code) +importFrom(httr2,"%>%") +importFrom(httr2,req_error) +importFrom(httr2,req_perform) +importFrom(httr2,req_proxy) +importFrom(httr2,req_retry) +importFrom(httr2,req_user_agent) +importFrom(httr2,request) +importFrom(httr2,resp_body_json) +importFrom(httr2,resp_content_type) +importFrom(httr2,resp_is_error) +importFrom(httr2,url_build) +importFrom(httr2,url_parse) importFrom(jsonlite,fromJSON) -importFrom(methods,as) +importFrom(jsonlite,toJSON) +importFrom(lubridate,day) +importFrom(lubridate,dmy) +importFrom(lubridate,month) +importFrom(lubridate,year) +importFrom(lubridate,ymd) importFrom(readr,col_character) +importFrom(readr,cols) importFrom(readr,read_tsv) -importFrom(sf,as_Spatial) -importFrom(sf,st_as_sf) -importFrom(sf,st_read) -importFrom(sp,merge) -importFrom(stringi,stri_match_first_regex) +importFrom(regions,recode_nuts) +importFrom(regions,validate_geo_code) +importFrom(regions,validate_nuts_regions) +importFrom(rlang,"!!") +importFrom(rlang,sym) +importFrom(stats,na.omit) +importFrom(stringi,stri_extract_first_regex) +importFrom(stringi,stri_replace_all_fixed) +importFrom(stringi,stri_replace_all_regex) +importFrom(stringr,str_extract) +importFrom(stringr,str_glue) importFrom(stringr,str_replace_all) -importFrom(tibble,as_data_frame) -importFrom(tibble,data_frame) +importFrom(tibble,as_tibble) importFrom(tibble,is_tibble) -importFrom(tidyr,gather_) +importFrom(tidyr,pivot_longer) importFrom(tidyr,separate) -importFrom(utils,data) +importFrom(utils,capture.output) importFrom(utils,download.file) +importFrom(utils,hasName) +importFrom(utils,menu) +importFrom(utils,person) +importFrom(utils,toBibtex) +importFrom(xml2,read_xml) +importFrom(xml2,xml_find_all) +importFrom(xml2,xml_text) diff --git a/NEWS.md b/NEWS.md old mode 100755 new mode 100644 index 1993dc18..22c8436a --- a/NEWS.md +++ b/NEWS.md @@ -1,8 +1,163 @@ -# eurostat next +# eurostat 4.0.0 -* The `label_eurostat()` has new countrycode and countrycode_nomatch arguments to - label with countrycode package and custom_dic argument to add custom dictionary. +## Major updates + +* Add data.table to package Imports and make using data.table functions optional with `get_eurostat()` `use.data.table` argument. This is especially useful with big datasets that would otherwise take a long time to go through the different data cleaning functions or crash R with their large memory footprint. (issue #277, PR #278) +* switch from `httr` package to `httr2` (issue #273, PR #276) +* Rewritten caching functionalities, making it possible to cache filtered queries and rely on local caches if the user attempt to filter a complete dataset that has already been cached. A list of queries and cached item hashes is stored in a cache_list.json file in cache folder. This can be viewed with a new function: `list_eurostat_cache_items()`. (Affects issues mentioned in #144, #257, #258, fixed in PR #267) +* Column names in `.eurostatTOC` object (returned by `get_eurostat_toc()`) now use dots instead of spaces in the style of `base::make.names()`, e.g. turning `last update of data` to `last.update.of.data` (PR #271) +* `.eurostatTOC` object includes a new hierarchy column that represents the position of each folder, dataset and table in the folder structure. +* `search_eurostat()` includes the option to search Table of Content items by dataset codes in addition to titles. This makes it possible to make further queries from similar datasets (e.g. "nama_10_gdp", "nama_10r_2gdp", "nama_10r_3popgdp") that might have different titles. +* `label_eurostat_tables()` has been rewritten to use the new SDMX API instead of `table_dic.dic` file in Eurostat Bulk Download Listing (PR #271) +* Remove legacy code related to downloading data from old bulk download facilities and temporary functions added in package version 3.7.14. +* `get_eurostat_geospatial()` now leverages on `giscoR::gisco_get_nuts()` for +downloading geospatial data (PR #264, thanks to @dieghernan): + * `"spdf"` output class soft-deprecated, it would return a `sf` object with a message. + * `make_valid` parameter soft-deprecated. + * Added `...` to the function so additional parametes can be passed to `giscoR::gisco_get_nuts()`. + * Dataset `eurostat_geodata_60_2016` updated. +* `get_eurostat_geospatial()` now requires sf package to work at all (PR #280, thanks to @dieghernan) + +## Minor updates + +* Added suppressWarnings() to some of the tests that use TOC's directly or indirectly as the tests are not directly related to TOC files. +* Use more parameter inheritance in package function documentation to reduce discrepancies between different functions (DRY-principle) (PR #270) +* Documentation more explicitly explains how to use filter parameters in `get_eurostat()` and `get_eurostat_json()` functions. The documentation now warns users about potential problems caused by `time` / `TIME_PERIOD` parameters when used to query datasets that contain quarterly data (issue #260) +* As continuation of the update done in 3.7.14, started to use the new URL also for dictionary files in `get_eurostat_dic()` and `label_eurostat()` functions. +* `get_bibentry()` now outputs "Accessed YYYY-MM-DD" and "dataset last updated YYYY-MM-DD" in note field as otherwise it would be sporadically printed or not at all printed from `urldate` field. +* Print more informative API error messages. (issue #261, PR #262, thanks to @ake123) +* Removed `sp`, `methods` and `broom` packages from dependencies. +* Added `giscoR` to Suggests. (PR #264) + +## New features + +* Added new function: `get_eurostat_interactive()` for interactively searching and downloading data from Eurostat SDMX API. The function aims to make good data citation practices more prominently visible and also make it easier to explore what different arguments in `get_eurostat()` function do. +* There is also a new internal function `eurostat:::fixity_checksum()` to easily calculate a fixity checksum for datasets downloaded from Eurostat. The fixity checksum can, for example, be saved in research notes and reported in as part of data appendices. Printing the fixity checksum is encouraged by including an option to print it in every `get_eurostat_interactive()` query. +* Added a new internal function `clean_eurostat_toc()` for easy removal of TOC objects from .EurostatEnv environment. (PR #278) +* New internal function `check_lang()` (PR #270) +* `get_eurostat()` function now explicity accepts a 'lang' argument, for passing onwards to `get_eurostat_json()` and `label_eurostat()` (PR #270) +* New user facing function: `get_eurostat_folder()` for downloading all datasets in a folder. The function is limited to downloading folders that contain at maximum 20 datasets. This function relies on new internal helper functions: `toc_count_whitespace()`, `toc_determine_hierarchy()`, `toc_count_children()` and `toc_list_children()`. (PR #270) +* EXPERIMENTAL: `get_eurostat_toc()` and `set_eurostat_toc()` now have experimental features that support downloading TOCs in French and German as well. This support, in turn, is leveraged in `get_bibentry()` which now has a language parameter: `lang` (PR #270) +* Related to updates to `get_eurostat_toc()`, `search_eurostat()` now supports searching from French and German TOC-files as well (PR #270) + +## Deprecated and defunct + +* `grepEurostatTOC()` is completely marked as defunct and is enroute to being removed from the package as `search_eurostat()` is now the only way to fetch Eurostat TOC items and search (grep) them (PR #270) +* During the development of the 4.0.0 version there was a temporary function called `label_eurostat_vars2` that has been removed in the final version, as promised earlier: "The old function will be completely removed after October 2023 when Eurostat Bulk Download Listing website is retired and `label_eurostat_vars2` will be renamed to `label_eurostat_vars()`". The new `label_eurostat_vars()` function uses the new SDMX API to retrieve names for dataset columns. Function evolution is subject to ongoing Eurostat API developments. (PR #270) + +## Bug fixes + +* Added a more informatic warning message in situations where TOC datasets downloaded from Eurostat might not have proper titles. For some reason this was isolated to German and French language versions of TOC while English language TOC had proper titles for all items. (PR #278) +* `get_bibentry()` returns correct codes for titles and warns the user if some / all of the requested codes were not found in the TOC (PR #270) +* `get_bibentry()` uses the date field with the internal BibEntry format that can be easily translated to other formats: bibtex, bibentry (PR #270) +* `get_bibentry()` now outputs dataset codes in titles correctly so that `bibtex` and `biblatex` entries can be copypasted into bibliographies without adding escape characters manually (PR #270) +* Fix issue related to downloading quarterly data (issue #260, PR #271) +* Reduce RAM usage in `eurotime2date()` when handling big datasets containing weekly data and tens of millions of rows (dataset used for testing mentioned in issue #200). + +# eurostat 3.8.3 (2023-03-07) + +## Bug fixes + +* Fix date handling bug in the `get_eurostat_json()` and `eurotime2date()` functions (issue #251, reported by @lz1nwm). The `get_eurostat_json()` function uses the temporary `eurotime2date()` function for date handling until the old bulk download API is deprecated. + +# eurostat 3.8.2 (2023-03-06) + +## Minor updates + +* use `curl::curl_download` on Windows platforms instead of `utils::download.file` as the latter causes the following error: "error reading from the connection [...] invalid or incomplete compressed data". This affects only files downloaded from the new API. + +# eurostat 3.7.14 (2023-02-22) + +## Major updates + +* Updated `get_eurostat()` and its assorted functions to download data from the new dissemination API (related to issues #251, #243). See Eurostat web page Transition - from Eurostat Bulk Download to API for a list of differences between old and new data sources: https://wikis.ec.europa.eu/display/EUROSTATHELP/Transition+-+from+Eurostat+Bulk+Download+to+API +* Added new temporary functions for downloading and handling data from the new dissemination API: `get_eurostat_raw2`, `tidy_eurostat2`, `convert_time_col2`, `eurotime2date2`, `eurotime2num2` and `label_eurostat2`. When the old bulk download facilities are decommissioned, these functions will replace the old functions with old naming schemes (without the 2s at the end). +* `tidy_eurostat2` function is now able to handle multiple time frequencies in one call: For example, you can download annual, quarterly, and monthly data simply by using a vector c("A", "Q", "M") in select_time instead of using these singular frequencies in separate calls. The function will also return multiple time series in one dataset if select_time is NULL (as it is by default). If the dataset contains multiple time series and these are explicitly downloaded / no select_time parameter is given, a message will be printed. +* `eurotime2num` can now handle monthly and weekly data as well. +* Added a new parameter to `get_eurostat()` function: legacy_bulk_download (default = TRUE). By setting this parameter to FALSE the user can download data from the new dissemination API. If you want to test the new API before it becomes the only way to download the data (and we very much encourage you to do so), set this parameter to FALSE. + +## Minor updates + +* Removed render-rmarkdown.yaml workflow used for rendering README.md file. README.md must be generated locally from now on. + +# eurostat 3.7.13 (2023-02-01) + +* Updated `get_eurostat_json()` to migrate from JSON web service to API Statistics (addressed in issues #243, #251). Please note that the output from JSON API is now slightly different than before: the datasets now contain a freq column to indicate the frequency with which data has been collected, for example annually "A", monthly "M" or quarterly "Q". See Eurostat - Data browser online help website for more information: https://wikis.ec.europa.eu/display/EUROSTATHELP/API+Statistics+-+migrating+from+JSON+web+service+to+API+Statistics +* Minor fixes in `get_bibentry()` and `get_eurostat_geospatial()` + +# eurostat 3.7.12 (2022-06-28) + +* Updated included dataset `eurostat_geodata_60_2016` to fix the issue of old-style crs object (#237) +* Added information about different variables in `eurostat_geodata_60_2016` so that the dataset is more understandable and usable for testing purposes. Added the same information to `get_eurostat_geospatial()` documentation as well. +* Added the GISCO copyright disclaimer to `eurostat_geodata_60_2016` and `get_eurostat_geospatial()` documentation. +* Get rid of unnecessary "No encoding supplied: defaulting to UTF-8." messages in `get_eurostat_geospatial()` by setting content encoding to UTF-8 when `httr::content()` function is called +* dplyr and tidyr namespaces are no longer imported completely, only selected few functions with importFrom + +# eurostat 3.7.10 (2022-02-09) + +* Fixed URL issues in tests and examples + +# eurostat 3.7.9 (2020-10-01) + +* Function documentation migrated from old `\code{}`, `\link{}` syntax to markdown (issue #230, PR #231 by @dieghernan) + +# eurostat 3.7.8 (2020-09-30) + +* Package cache management updated: `options()` command is no longer needed and the cache dir can be modified persistently with a custom function (issue #223, PR #228 by @dieghernan) + +# eurostat 3.7.7 (2020-06-24) +* Maps vignette fixed + +# eurostat 3.7.6 (2021-05-20) + +* Deprecated `add_nuts_level()`, `harmonize_geo_code()`, `recode_to_nuts_2016()` and `recode_to_nuts_2013()`; these functions were moved to the new package regions. The problem of sub-national geo codes is explained in the new vignette "Mapping Regional Data, Mapping Metadata Problems", which replaces the "Regional data examples for the eurostat R package" vignette. This is a shared vignette, but the new regions package has more articles on how to work with sub-national data. (issues #218 and #219, PR #220 by @antaldaniel) + +# eurostat 3.7.5 (2020-05-12) + +* Moved sf from Imports to Suggests and made `get_eurostat_geospatial()` return a message if sf is not installed. This is to increase compatibility of eurostat-package on systems that have trouble installing sf (issue #213) +* Wrapped some problem causing examples to `\dontrun{}` for a quick CRAN release + +# eurostat 3.7.3 + +* Removed outdated dependencies (mapproj, plotrix, rsdmx) + +# eurostat 3.7.2 + +* Non-intersecting sf-geometries in get_eurostat_geospatial (PR #202 by @retostauffer) + +# eurostat 3.6.4 (2020-05-12) + +* Fixed stringsAsFactors for R-4.0.0 and moved default to FALSE + +# eurostat 3.6.3 (2020-04-21) + +* Stabilized http requests (PR by @annnvv) + +# eurostat 3.5.3 + +* get_eurostat switched to v2.1 + +# eurostat 3.5.2 + +* internet and proxy setting fixes +* bibentry fix + +# eurostat 3.4.1 + +* Fixed vignette +* Added automated error messages to URL download failures + +# eurostat 3.3.3 + +* Countries and Country Codes data.frames get label column for country names in the Eurostat database. +* Fixed vignette duplicate entry issue and smaller issues +* Added get_bibentry + +# eurostat 3.3.1 + +* The `label_eurostat()` has new countrycode and countrycode_nomatch arguments to label with countrycode package and custom_dic argument to add custom dictionary. +* Vignette updated # eurostat 3.2.3 @@ -21,8 +176,7 @@ ## Minor features -* data/ generation script in data-raw/ updated to make all data reproducible - +* ./data/ generation script in ./data-raw/ updated to make all data reproducible ## Bug fixes @@ -32,19 +186,13 @@ ## Minor features -* Added new example data set to reduce repeated downloads from - eurostat service - -* Now `label_eurostat()` gives always an error by default, if labelling - introduces duplicated labels. A new `fix_duplicated` argument is add to fix - duplicated labels automatically. (#79, #90) - +* Added new example data set to reduce repeated downloads from eurostat service +* Now `label_eurostat()` gives always an error by default, if labelling introduces duplicated labels. A new `fix_duplicated` argument is add to fix duplicated labels automatically. (#79, #90) * Shrinked the package tarball size ## Bug fixes * Modified tutorial to accommodate the CRAN error - * Fixed cut_to_classes to generate unique breaks # eurostat 3.1.1 @@ -65,14 +213,10 @@ ## Bug fixes -* `search_eurostat()` accepts new argument `fixed`: if `TRUE` -(default), `pattern` provided will used as is; if `FALSE`, -`pattern` will be interpreted as a true regex pattern. -* Augmented the list of Suggested packages in the DESCRIPTION file, - including the Cairo package (#70) +* `search_eurostat()` accepts new argument `fixed`: if `TRUE` (default), `pattern` provided will used as is; if `FALSE`, `pattern` will be interpreted as a true regex pattern. +* Augmented the list of Suggested packages in the DESCRIPTION file, including the Cairo package (#70) * Updated the journal manuscript based on reviewer feedback - # eurostat 2.2.20001 * Development version opened @@ -107,30 +251,17 @@ # eurostat 1.2.21 -* The `get_eurostat()` can now get data also from the Eurostat JSON API via - `get_eurostat_json()`. It also have a new argument `type` to select labels - for variable values instead of codes. +* The `get_eurostat()` can now get data also from the Eurostat JSON API via `get_eurostat_json()`. It also have a new argument `type` to select labels for variable values instead of codes. * Fix an error after update to `tidyr 0.4.0` (#47). - # eurostat 1.2.13 -* New `select_time` argument for `get_eurostat()` to select a time frequency - in case of multi-frequency datasets. Now the `get_eurostat()` also gives an - error if you try to get multi-frequency with other time formats - than `time_format = "raw"`. (#30) `time` column is also now in ascending - order. -* `get_eurostat()` gets a new argument `compress_file` to control compression - of the cache file. Also cache filenames includes now all relevant arguments. (#28) +* New `select_time` argument for `get_eurostat()` to select a time frequency in case of multi-frequency datasets. Now the `get_eurostat()` also gives an error if you try to get multi-frequency with other time formats than `time_format = "raw"`. (#30) `time` column is also now in ascending order. +* `get_eurostat()` gets a new argument `compress_file` to control compression of the cache file. Also cache filenames includes now all relevant arguments. (#28) * For `search_eurostat()` a new type option `type = "all"` to search all types. -* For `label_eurostat()` new arguments. A `code` to retain also codes - for spesified colums. A `eu_order` to order factor levels in Eurostat order, - which uses the new function `dic_order()`. -* Now `label_eurostat_vars(x)` gives labels for names, if x is other than - a character or a factor and `label_eurostat_tables(x)` does not accept other - than a character or a factor. -* For `get_eurostat()` a new argument `stringsAsFactors` to control the - factor conversion of variables. +* For `label_eurostat()` new arguments. A `code` to retain also codes for specified columns. A `eu_order` to order factor levels in Eurostat order, which uses the new function `dic_order()`. +* Now `label_eurostat_vars(x)` gives labels for names, if x is other than a character or a factor and `label_eurostat_tables(x)` does not accept other than a character or a factor. +* For `get_eurostat()` a new argument `stringsAsFactors` to control the factor conversion of variables. * `eurotime2date` (and `get_eurostat`) convers now also daily data. # eurostat 1.0.16 @@ -146,4 +277,3 @@ # eurostat 0.9.1 (2014-04-24) * Package collected from statfi and smarterpoland - diff --git a/R/check_access_to_data.R b/R/check_access_to_data.R new file mode 100755 index 00000000..f5e26776 --- /dev/null +++ b/R/check_access_to_data.R @@ -0,0 +1,43 @@ +#' @title Check access to ec.europe.eu +#' @description Check if R has access to resources at http://ec.europa.eu +#' @author Markus Kainu +#' @return a logical. +#' @examples +#' \donttest{ +#' check_access_to_data() +#' } +#' +#' @importFrom curl curl_download +#' @importFrom utils download.file +#' +#' @export + +check_access_to_data <- function() { + temp <- tempfile() + http_url <- "https://ec.europa.eu/eurostat/cache/GISCO/distribution/v2/nuts/geojson/NUTS_RG_60M_2006_4326_LEVL_0.geojson" + # If unix use curl::curl_download to test connection + # If windows use download.file with default method 'wininet' + if (.Platform$OS.type == "unix") { + suppressWarnings( + try( + curl::curl_download(http_url, temp, quiet = TRUE, ), + silent = TRUE + ) + ) + } else { + suppressWarnings( + try( + utils::download.file(http_url, + temp, + quiet = TRUE + ), + silent = TRUE + ) + ) + } + if (is.na(file.info(temp)$size)) { + FALSE + } else { + TRUE + } +} diff --git a/R/clean_eurostat_cache.R b/R/clean_eurostat_cache.R index 7e05b433..66ecb3cc 100755 --- a/R/clean_eurostat_cache.R +++ b/R/clean_eurostat_cache.R @@ -1,27 +1,59 @@ -#' @title Clean Eurostat Cache -#' @description Delete all .rds files from the eurostat cache directory. -#' See \code{\link{get_eurostat}} for more on cache. -#' @param cache_dir A path to cache directory. If \code{NULL} (default) -#' tries to clean default temporary cache directory. +#' @title +#' Clean Eurostat Cache +#' @description +#' Delete all .rds files from the eurostat cache directory. +#' See [get_eurostat()] for more on cache. +#' @param cache_dir +#' A path to cache directory. If `NULL` (default) +#' tries to clean default temporary cache directory. +#' @param config +#' Logical `TRUE/FALSE`. Should the cached path be deleted? +#' @family cache utilities +#' @author +#' Przemyslaw Biecek, Leo Lahti, Janne Huovari, Markus Kainu and +#' Diego Hernangómez +#' @examples +#' \dontrun{ +#' clean_eurostat_cache() +#' } #' @export -#' @author Przemyslaw Biecek, Leo Lahti, Janne Huovari and Markus Kainu \email{ropengov-forum@@googlegroups.com} \url{http://github.com/ropengov/eurostat} -#' @examples clean_eurostat_cache() -clean_eurostat_cache <- function(cache_dir = NULL){ - if (is.null(cache_dir)){ - cache_dir <- getOption("eurostat_cache_dir", file.path(tempdir(), "eurostat")) - if (!file.exists(cache_dir)) { - message("The cache does not exist") - return(invisible(TRUE)) - } +clean_eurostat_cache <- function(cache_dir = NULL, config = FALSE) { + + # Config + # nocov start + if (config) { + config_dir <- rappdirs::user_config_dir("eurostat", "R") + + if (dir.exists(config_dir)) { + unlink(config_dir, recursive = TRUE, force = TRUE) + message("eurostat cache config deleted") + } + + set_eurostat_cache_dir(file.path(tempdir(), "eurostat")) } - if (!file.exists(cache_dir)) stop("The cache folder ", cache_dir, " does not exist") - - files <- list.files(cache_dir, pattern = "rds", full.names = TRUE) + # nocov end + + cache_dir <- eur_helper_cachedir(cache_dir) + + if (!file.exists(cache_dir)) { + # nocov start + stop( + "The cache folder ", cache_dir, + " does not exist" + ) + # nocov end + } + + files <- list.files( + cache_dir, + pattern = "rds|RData|cache_list.json", + full.names = TRUE + ) if (length(files) == 0) { message("The cache folder ", cache_dir, " is empty.") } else { unlink(files) - message("Deleted .rds files from ", cache_dir) + message("Deleted .rds/.RData files and cache_list.json from ", cache_dir) } invisible(TRUE) } diff --git a/R/cut_to_classes.R b/R/cut_to_classes.R index 658fb3a8..50c38ca1 100755 --- a/R/cut_to_classes.R +++ b/R/cut_to_classes.R @@ -1,92 +1,106 @@ #' @title Cuts the Values Column into Classes and Polishes the Labels -#' @description Categorises a numeric vector into automatic or manually defined categories. -#' and polishes the labels ready for used in mapping with \code{merge_with_geodata} function and ggplot2. -#' @param x A numeric vector, eg. \code{values} variable in data returned by \code{get_eurostat} +#' @description Categorises a numeric vector into automatic or manually defined +#' categories and polishes the labels ready for used in mapping with `ggplot2`. +#' @param x A numeric vector, eg. `values` variable in data returned by +#' [get_eurostat()]. #' @param n A numeric. number of classes/categories -#' @param style Chosen style: one of "fixed", "sd", "equal", "pretty", "quantile", "kmeans", "hclust", -#' "bclust", "fisher", or "jenks" #' @param manual Logical. If manual breaks are being used #' @param manual_breaks Numeric vector with manual threshold values #' @param decimals Number of decimals to include with labels #' @param nodata_label String. Text label for NA category. -#' @export +#' @inheritParams classInt::classIntervals #' @author Markus Kainu #' @return a factor. -#' @examples -#' \dontrun{ -#' lp <- get_eurostat("nama_aux_lp") -#' lp$class <- cut_to_classes(lp$values, n=5, style="equal", decimals=1) -#' } -cut_to_classes <- function(x, n=5, style="equal", manual=FALSE, - manual_breaks = NULL, decimals=0, - nodata_label="No data") { - - manual_breaks_orig <- manual_breaks - if (!is.null(manual_breaks) && (length(unique(manual_breaks)) == length(manual_breaks))) { - warning("manual_breaks in cut_to_classes are not unique. Using unique breaks only.") +#' @examplesIf check_access_to_data() +#' \donttest{ +#' # lp <- get_eurostat("nama_aux_lp") +#' lp <- get_eurostat("nama_10_lp_ulc") +#' lp$class <- cut_to_classes(lp$values, n = 5, style = "equal", decimals = 1) +#' } +#' +#' @importFrom classInt classIntervals +#' @importFrom stringr str_replace_all +#' @seealso [classInt::classIntervals()] +#' @family helpers +#' @export +cut_to_classes <- function(x, n = 5, style = "equal", manual = FALSE, + manual_breaks = NULL, decimals = 0, + nodata_label = "No data") { + # manual_breaks_orig <- manual_breaks + if (!is.null(manual_breaks) && + (length(unique(manual_breaks)) == length(manual_breaks))) { + warning(paste("manual_breaks in cut_to_classes are not unique.", + "Using unique breaks only.")) manual_breaks <- unique(manual_breaks) - } if (manual) { - levs <- as.data.frame(levels(cut(x, - breaks=manual_breaks, - include.lowest=T, - dig.lab=5))) + levs <- as.data.frame( + levels( + cut( + x, + breaks = manual_breaks, + include.lowest = TRUE, + dig.lab = 5 + ) + ) + ) } else { - - brs <- data.frame(classInt::classIntervals(x,n=n,style=style)[2])[,1] + brs <- data.frame(classInt::classIntervals(x, n = n, style = style)[2])[, 1] # Ensure that the breaks are unique brs <- unique(brs) - cutting <- cut(x, breaks=brs, include.lowest=T, dig.lab=5) + cutting <- cut(x, breaks = brs, include.lowest = TRUE, dig.lab = 5) levs <- levels(cutting) levs <- as.data.frame(levs) - } names(levs) <- "orig" - levs$mod <- str_replace_all(levs$orig, "\\[", "") - levs$mod <- str_replace_all(levs$mod, "\\]", "") - levs$mod <- str_replace_all(levs$mod, "\\(", "") - levs$lower <- gsub(",.*$","", levs$mod) - levs$upper <- gsub(".*,","", levs$mod) - + levs$mod <- stringr::str_replace_all(levs$orig, "\\[", "") + levs$mod <- stringr::str_replace_all(levs$mod, "\\]", "") + levs$mod <- stringr::str_replace_all(levs$mod, "\\(", "") + levs$lower <- gsub(",.*$", "", levs$mod) + levs$upper <- gsub(".*,", "", levs$mod) + levs$lower <- factor(levs$lower) - levs$lower <- round(as.numeric(levels(levs$lower))[levs$lower],decimals) - levs$lower <- prettyNum(levs$lower, big.mark=" ") - + levs$lower <- round(as.numeric(levels(levs$lower))[levs$lower], decimals) + levs$lower <- prettyNum(levs$lower, big.mark = " ") + levs$upper <- factor(levs$upper) - levs$upper <- round(as.numeric(levels(levs$upper))[levs$upper],decimals) - levs$upper <- prettyNum(levs$upper, big.mark=" ") - - levs$labs <- paste(levs$lower,levs$upper, sep=" ~< ") + levs$upper <- round(as.numeric(levels(levs$upper))[levs$upper], decimals) + levs$upper <- prettyNum(levs$upper, big.mark = " ") + + levs$labs <- paste(levs$lower, levs$upper, sep = " ~< ") labs <- as.character(c(levs$labs)) if (manual) { - y <- cut(x, breaks = manual_breaks, - include.lowest=T, - dig.lab=5, labels = labs) + y <- cut(x, + breaks = manual_breaks, + include.lowest = TRUE, + dig.lab = 5, labels = labs + ) rm(manual_breaks) } else { - brs2 <- data.frame(classIntervals(x,n = n, style = style)[2])[,1] + brs2 <- data.frame(classIntervals(x, n = n, style = style)[2])[, 1] # Ensure the breaks are unique brs2 <- unique(brs2) - y <- cut(x, breaks = brs2, - include.lowest=T, - dig.lab=5, labels = labs) + y <- cut(x, + breaks = brs2, + include.lowest = TRUE, + dig.lab = 5, labels = labs + ) } y <- as.character(y) - + y[is.na(y)] <- nodata_label - - y <- factor(y, levels=c(nodata_label,labs[1:n])) - + + y <- factor(y, levels = c(nodata_label, labs[1:n])) + y -} \ No newline at end of file +} diff --git a/R/data.R b/R/data.R index 1c10eb17..c9b88754 100755 --- a/R/data.R +++ b/R/data.R @@ -1,7 +1,10 @@ #' @title Auxiliary Data #' @description Auxiliary Data Sets -#' @details Retrieved with: \code{tgs00026 <- get_eurostat("tgs00026", time_format = "raw") } +#' @family datasets +#' @details +#' Disposable income of private households by NUTS 2 regions +#' Retrieved with: `tgs00026 <- get_eurostat("tgs00026", time_format = "raw") ` +#' Data retrieval date: 2022-06-27 #' @format data_frame #' @rdname tgs00026 -"tgs00026" - +"tgs00026" diff --git a/R/data_countries.R b/R/data_countries.R index 61044622..7d09d677 100755 --- a/R/data_countries.R +++ b/R/data_countries.R @@ -1,17 +1,18 @@ -#' @title Countries and Country Codes +#' @title Countries and Country Codes #' @description Countries and country codes in EU, #' Euro area, EFTA and EU candidate countries. #' @format A data_frame: -#' \describe{ -#' \item{code}{Country code in the Eurostat database} -#' \item{name}{Country name in English} -#' } -#' @source \url{http://ec.europa.eu/eurostat/statistics-explained/index.php/Tutorial:Country_codes_and_protocol_order}, -#' \url{http://ec.europa.eu/eurostat/statistics-explained/index.php/Glossary:Euro_area} -"eu_countries" +#' * **code**: Country code in the Eurostat database. +#' * **name**: Country name in English. +#' * **label**: Country name in the Eurostat database. +#' +#' @family datasets +#' @source , +#' +"eu_countries" #' @rdname eu_countries -"ea_countries" +"ea_countries" #' @rdname eu_countries "efta_countries" diff --git a/R/data_spatial.R b/R/data_spatial.R index c38d9c19..a1aacf8a 100755 --- a/R/data_spatial.R +++ b/R/data_spatial.R @@ -1,69 +1,128 @@ -#' @title Geospatial data of Europe from Gisco in 1:60 million scale from year 2016 -#' @description Geospatial data of Europe from Gisco in 1:60 million scale from year 2016 -#' @format sf -#' \describe{ -#' \item{id}{Country code in the Eurostat database} -#' \item{CNTRY_CODE}{Country code} -#' \item{NUTS_NAME}{NUTS name in local language} -#' \item{LEVL_CODE}{NUTS code} -#' \item{FID}{Country code} -#' \item{NUTS_ID}{NUTS code} -#' \item{geometry}{geospatial information} -#' \item{geo}{NUTS code} +#' Geospatial data of Europe from GISCO in 1:60 million scale from +#' year 2016 +#' +#' @description Geospatial data of Europe from GISCO in 1:60 million scale +#' from year 2016 +#' +#' @family datasets +#' @family geospatial +#' @format sf object +#' @docType data +#' @name eurostat_geodata_60_2016 +#' +#' @details +#' The dataset contains 2016 observations (rows) and 12 variables (columns). +#' +#' The object contains the following columns: +#' * **id**: JSON id code, the same as **NUTS_ID**. See **NUTS_ID** below for +#' further clarification. +#' * **LEVL_CODE**: NUTS level code: 0 (national level), 1 (major +#' socio-economic regions), 2 (basic regions for the application of regional +#' policies) or 3 (small regions). +#' * **NUTS_ID**: NUTS ID code, consisting of country code and numbers (1 for +#' NUTS 1, 2 for NUTS 2 and 3 for NUTS 3) +#' * **CNTR_CODE**: Country code: two-letter ISO code (ISO 3166 alpha-2), except +#' in the case of Greece (EL). +#' * **NAME_LATN**: NUTS name in local language, transliterated to Latin script +#' * **NUTS_NAME**: NUTS name in local language, in local script. +#' * **MOUNT_TYPE**: Mountain typology for NUTS 3 regions. +#' * 1: "where more than 50 % of the surface is covered by topographic +#' mountain areas" +#' * 2: "in which more than 50 % of the regional population lives in +#' topographic mountain areas" +#' * 3: "where more than 50 % of the surface is covered by topographic +#' mountain areas and where more than 50 % of the regional population lives +#' in these mountain areas" +#' * 4: non-mountain region / other region +#' * 0: no classification provided (e.g. in the case of NUTS 1 and NUTS 2 and +#' non-EU countries) +#' * **URBN_TYPE**: Urban-rural typology for NUTS 3 regions. +#' * 1: predominantly urban region +#' * 2: intermediate region +#' * 3: predominantly rural region +#' * 0: no classification provided (e.g. in the case of NUTS 1 and NUTS 2 +#' regions) +#' * **COAST_TYPE**: Coastal typology for NUTS 3 regions. +#' * 1: coastal (on coast) +#' * 2: coastal (>= 50% of population living within 50km of the coastline) +#' * 3: non-coastal region +#' * 0: no classification provided (e.g. in the case of NUTS 1 and NUTS 2 +#' regions) +#' * **FID**: Same as NUTS_ID. +#' * **geo**: Same as NUTS_ID, added for for easier joins with dplyr. However, +#' it is recommended to use other identical fields for this purpose. +#' * **geometry**: geospatial information. +#' +#' Dataset updated: 2023-06-29. For a more recent version, please use +#' [giscoR::gisco_get_nuts()] function. +#' +#' @source +#' Data source: Eurostat via [giscoR::gisco_get_nuts()]. +#' +#' © EuroGeographics for the administrative boundaries +#' +#' Data downloaded from: +#' +#' +#' @references +#' The following copyright notice is provided for end user convenience. +#' Please check up-to-date copyright information from the eurostat website: +#' [GISCO: Geographical information and maps - Administrative units/statistical units](https://ec.europa.eu/eurostat/web/gisco/geodata/reference-data/administrative-units-statistical-units) +#' +#' "In addition to the +#' [general copyright and licence policy](https://ec.europa.eu/eurostat/web/main/about/policies/copyright) +#' applicable to the whole Eurostat website, the following +#' specific provisions apply to the datasets you are downloading. The download +#' and usage of these data is subject to the acceptance of the following +#' clauses: +#' +#' 1. The Commission agrees to grant the non-exclusive and not transferable +#' right to use and process the Eurostat/GISCO geographical data downloaded +#' from this page (the "data"). +#' +#' 1. The permission to use the data is granted on condition that: +#' 1. the data will not be used for commercial purposes; +#' 2. the source will be acknowledged. A copyright notice, as specified +#' below, will have to be visible on any printed or electronic publication +#' using the data downloaded from this page. +#' +#' ## Copyright notice +#' +#' When data downloaded from this page is used in any printed or electronic +#' publication, in addition to any other provisions applicable to the whole +#' Eurostat website, data source will have to be acknowledged in the legend of +#' the map and in the introductory page of the publication with the following +#' copyright notice: +#' +#' EN: © EuroGeographics for the administrative boundaries +#' +#' FR: © EuroGeographics pour les limites administratives +#' +#' DE: © EuroGeographics bezüglich der Verwaltungsgrenzen +#' +#' For publications in languages other than English, French or German, the +#' translation of the copyright notice in the language of the publication shall +#' be used. +#' +#' If you intend to use the data commercially, please contact EuroGeographics +#' for information regarding their licence agreements." +#' +#' @seealso [giscoR::gisco_get_nuts()] and +#' [Eurostat. (2019). Methodological manual on territorial typologies -- 2018 edition. Manuals and guidelines.](https://ec.europa.eu/eurostat/web/products-manuals-and-guidelines/-/ks-gq-18-008) +#' +#' +#' @examples +#' +#' eurostat_geodata_60_2016 <- eurostat::eurostat_geodata_60_2016 +#' +#' # Manipulate and plot +#' if (require(sf)) { +#' library(sf) +#' # Filter NUTS3 from select countries like in a regular data frame +#' example_nuts <- subset(eurostat_geodata_60_2016, LEVL_CODE == 3 & +#' CNTR_CODE %in% c("DK", "DE", "PL")) +#' +#' plot(example_nuts["CNTR_CODE"]) #' } -#' @source \url{http://ec.europa.eu/eurostat/web/gisco/geodata/reference-data/administrative-units-statistical-units} -"eurostat_geodata_60_2016" - - -## -- 2016 -# library(sf) -# library(httr) -# -# resp <- GET("http://ec.europa.eu/eurostat/cache/GISCO/distribution/v2/nuts/geojson/NUTS_RG_03M_2016_4258_LEVL_0.geojson") -# n0 <- st_read(content(resp, as="text"), stringsAsFactors = FALSE, quiet = TRUE) -# resp <- GET("http://ec.europa.eu/eurostat/cache/GISCO/distribution/v2/nuts/geojson/NUTS_RG_03M_2016_4258_LEVL_1.geojson") -# n1 <- st_read(content(resp, as="text"), stringsAsFactors = FALSE, quiet = TRUE) -# resp <- GET("http://ec.europa.eu/eurostat/cache/GISCO/distribution/v2/nuts/geojson/NUTS_RG_03M_2016_4258_LEVL_2.geojson") -# n2 <- st_read(content(resp, as="text"), stringsAsFactors = FALSE, quiet = TRUE) -# resp <- GET("http://ec.europa.eu/eurostat/cache/GISCO/distribution/v2/nuts/geojson/NUTS_RG_03M_2016_4258_LEVL_3.geojson") -# n3 <- st_read(content(resp, as="text"), stringsAsFactors = FALSE, quiet = TRUE) -# eurostat_geodata_60_2016 <- rbind(n0,n1,n2,n3) -# eurostat_geodata_60_2016$geo <- eurostat_geodata_60_2016$NUTS_ID -# save(eurostat_geodata_60_2016, file = "./data/eurostat_geodata_60_2016.rda") - - -## -- 2013 -# resp <- GET("http://ec.europa.eu/eurostat/cache/GISCO/distribution/v1/geojson/NUTS_RG_60M_2013_4258_LEVL_0.geojson") -# n0 <- st_read(content(resp, as="text"), stringsAsFactors = FALSE, quiet = TRUE) -# resp <- GET("http://ec.europa.eu/eurostat/cache/GISCO/distribution/v1/geojson/NUTS_RG_60M_2013_4258_LEVL_1.geojson") -# n1 <- st_read(content(resp, as="text"), stringsAsFactors = FALSE, quiet = TRUE) -# resp <- GET("http://ec.europa.eu/eurostat/cache/GISCO/distribution/v1/geojson/NUTS_RG_60M_2013_4258_LEVL_2.geojson") -# n2 <- st_read(content(resp, as="text"), stringsAsFactors = FALSE, quiet = TRUE) -# resp <- GET("http://ec.europa.eu/eurostat/cache/GISCO/distribution/v1/geojson/NUTS_RG_60M_2013_4258_LEVL_3.geojson") -# n3 <- st_read(content(resp, as="text"), stringsAsFactors = FALSE, quiet = TRUE) -# eurostat_geodata_60_2013 <- rbind(n0,n1,n2,n3) -# save(eurostat_geodata_60_2013, file = "./data/eurostat_geodata_60_2013.rda") - -## --2010 -# resp <- GET("http://ec.europa.eu/eurostat/cache/GISCO/distribution/v1/geojson/NUTS_RG_60M_2010_4258_LEVL_0.geojson") -# n0 <- st_read(content(resp, as="text"), stringsAsFactors = FALSE, quiet = TRUE) -# resp <- GET("http://ec.europa.eu/eurostat/cache/GISCO/distribution/v1/geojson/NUTS_RG_60M_2010_4258_LEVL_1.geojson") -# n1 <- st_read(content(resp, as="text"), stringsAsFactors = FALSE, quiet = TRUE) -# resp <- GET("http://ec.europa.eu/eurostat/cache/GISCO/distribution/v1/geojson/NUTS_RG_60M_2010_4258_LEVL_2.geojson") -# n2 <- st_read(content(resp, as="text"), stringsAsFactors = FALSE, quiet = TRUE) -# resp <- GET("http://ec.europa.eu/eurostat/cache/GISCO/distribution/v1/geojson/NUTS_RG_60M_2010_4258_LEVL_3.geojson") -# n3 <- st_read(content(resp, as="text"), stringsAsFactors = FALSE, quiet = TRUE) -# eurostat_geodata_60_2010 <- rbind(n0,n1,n2,n3) -# save(eurostat_geodata_60_2010, file = "./data/eurostat_geodata_60_2010.rda") - -## --2006 -# resp <- GET("http://ec.europa.eu/eurostat/cache/GISCO/distribution/v1/geojson/NUTS_RG_60M_2006_4258_LEVL_0.geojson") -# n0 <- st_read(content(resp, as="text"), stringsAsFactors = FALSE, quiet = TRUE) -# resp <- GET("http://ec.europa.eu/eurostat/cache/GISCO/distribution/v1/geojson/NUTS_RG_60M_2006_4258_LEVL_1.geojson") -# n1 <- st_read(content(resp, as="text"), stringsAsFactors = FALSE, quiet = TRUE) -# resp <- GET("http://ec.europa.eu/eurostat/cache/GISCO/distribution/v1/geojson/NUTS_RG_60M_2006_4258_LEVL_2.geojson") -# n2 <- st_read(content(resp, as="text"), stringsAsFactors = FALSE, quiet = TRUE) -# resp <- GET("http://ec.europa.eu/eurostat/cache/GISCO/distribution/v1/geojson/NUTS_RG_60M_2006_4258_LEVL_3.geojson") -# n3 <- st_read(content(resp, as="text"), stringsAsFactors = FALSE, quiet = TRUE) -# eurostat_geodata_60_2006 <- rbind(n0,n1,n2,n3) -# save(eurostat_geodata_60_2006, file = "./data/eurostat_geodata_60_2006.rda") +#' +NULL diff --git a/R/deprecated_regions_functions.R b/R/deprecated_regions_functions.R new file mode 100755 index 00000000..533e00f7 --- /dev/null +++ b/R/deprecated_regions_functions.R @@ -0,0 +1,198 @@ +#' DEPRECATED FUNCTIONS FOR BACKWARD COMPATIBILITY +#' FUNCTIONS GIVE WARNING AND CALL APPROPRIATE regions FUNCTIONS + +#' @title Add the statistical aggregation level to data frame +#' @description Eurostat regional statistics contain country, and various +#' regional level information. In many cases, for example, when mapping, +#' it is useful to filter out national level data from NUTS2 level regional +#' data, for example. +#' +#' This function will be deprecated. Use the more comprehensive +#' `[regions::validate_nuts_regions()]` instead. +#' +#' @param dat A data frame or tibble returned by [get_eurostat()]. +#' @param geo_labels A geographical label, defaults to `geo`. +#' @author Daniel Antal +#' @return a new numeric variable nuts_level with the numeric value of +#' NUTS level 0 (country), 1 (greater region), +#' 2 (region), 3 (small region). +#' @keywords internal +#' @family regions functions +#' @seealso [regions::validate_nuts_regions()] +#' @examples +#' +#' dat <- data.frame( +#' geo = c("FR", "IE04", "DEB1C"), +#' values = c(1000, 23, 12) +#' ) +#' +#' add_nuts_level(dat) +#' @importFrom dplyr mutate case_when +#' +#' @export + +add_nuts_level <- function(dat, geo_labels = "geo") { + message("This function will be deprecated. Use regions::validate_nuts_regions() instead.") + + if (any(c("character", "factor") %in% class(dat))) { + input <- "label" + geo <- dat + dat <- data.frame( + geo = as.character(geo), + stringsAsFactors = FALSE + ) + } else { + input <- "not_label" + } + + + if ("data.frame" %in% class(dat)) { + if (!geo_labels %in% names(dat)) { + stop( + "Regional labelling variable '", + geo_labels, + "' is not found in the data frame." + ) + } + + dat <- regions::validate_nuts_regions(dat) + dat$nuts_level <- unlist(lapply(dat$typology, switch, + country = 0, + nuts_level_1 = 1, + nuts_level_2 = 2, + nuts_level_3 = 3 + )) + } + + if (input == "label") { + as.numeric(dat$nuts_level) + } else { + dat + } +} + +#' @title Harmonize NUTS region codes that changed with the `NUTS2016` +#' definition +#' @description Eurostat mixes `NUTS2013` and `NUTS2016` geographic +#' label codes in the `'geo'` column, which creates time-wise comparativity +#' issues. This deprecated function checked if you data is affected by this +#' problem and gives information on what to do. +#' +#' This function is deprecated, and a more general function was moved to +#' [regions::validate_nuts_regions()]. +#' +#' @param dat A Eurostat data frame downloaded with [get_eurostat()] +#' @author Daniel Antal +#' @return An augmented data frame that explains potential problems and +#' possible solutions. +#' @importFrom regions validate_nuts_regions +#' @examples +#' dat <- eurostat::tgs00026 +#' regions::validate_nuts_regions(dat) +#' @family regions functions +#' @keywords internal +#' @seealso [regions::validate_nuts_regions()] +#' @export + +harmonize_geo_code <- function(dat) { + warning("The 'harmonize_geo_code' function is deprecated. Use instead regions::validate_nuts_regions(dat, nuts_year = 2016)") + + regions::validate_nuts_regions(dat, nuts_year = 2016) +} + + +#' @title Recode geo labels and rename regions from NUTS2013 to NUTS2016 +#' @description Eurostat mixes NUTS2013 and NUTS2016 geographic label codes +#' in the `'geo'` column, which creates time-wise comparativity issues. +#' +#' This function is deprecated, and a more general function was moved to +#' `[regions::recode_nuts()]`. +#' +#' @param dat A Eurostat data frame downloaded with +#' [get_eurostat()]. +#' @author Daniel Antal +#' @return An augmented and potentially relabelled data frame which +#' contains all formerly `'NUTS2013'` definition geo labels in the +#' `'NUTS2016'` vocabulary when only the code changed, but the +#' boundary did not. It also contains some information on other geo labels +#' that cannot be brought to the current `'NUTS2016'` definition. +#' Furthermore, when the official name of the region changed, it will use +#' the new name (if the otherwise the region boundary did not change.) +#' If not called before, the function will use the helper function +#' [harmonize_geo_code()] +#' @examples +#' test_regional_codes <- data.frame( +#' geo = c("FRB", "FRE", "UKN02", "IE022", "FR243", "FRB03"), +#' time = c(rep(as.Date("2014-01-01"), 5), as.Date("2015-01-01")), +#' values = c(1:6), +#' control = c( +#' "Changed from NUTS2 to NUTS1", +#' "New region NUTS2016 only", +#' "Discontinued region NUTS2013", +#' "Boundary shift NUTS2013", +#' "Recoded in NUTS2013", +#' "Recoded in NUTS2016" +#' ) +#' ) +#' +#' recode_to_nuts_2016(test_regional_codes) +#' @importFrom regions recode_nuts +#' @family regions functions +#' @seealso [regions::recode_nuts()] +#' @keywords internal +#' @export + +recode_to_nuts_2016 <- function(dat) { + warning("The 'recode_to_nuts_2013' function is deprecated. Use instead regions::recode_nuts(dat, nuts_year = 2016)") + + regions::recode_nuts(dat, nuts_year = 2016) +} + + + +#' @title Recode geo labels and rename regions from NUTS2016 to NUTS2013 +#' @description Eurostat mixes NUTS2013 and NUTS2016 geographic label codes +#' in the `'geo'` column, which creates time-wise comparativity issues. +#' +#' This function is deprecated, and a more general function was moved to +#' `[regions::recode_nuts()]`. +#' +#' @param dat A Eurostat data frame downloaded with +#' [get_eurostat()]. +#' @author Daniel Antal +#' @return An augmented and potentially relabelled data frame which +#' contains all formerly `'NUTS2013'` definition geo labels in the +#' `'NUTS2016'` vocabulary when only the code changed, but the +#' boundary did not. It also contains some information on other geo labels +#' that cannot be brought to the current `'NUTS2013'` definition. +#' Furthermore, when the official name of the region changed, it will use +#' the new name (if the otherwise the region boundary did not change.) +#' If not called before, the function will use the helper function +#' [harmonize_geo_code()] +#' @examples +#' test_regional_codes <- data.frame( +#' geo = c("FRB", "FRE", "UKN02", "IE022", "FR243", "FRB03"), +#' time = c(rep(as.Date("2014-01-01"), 5), as.Date("2015-01-01")), +#' values = c(1:6), +#' control = c( +#' "Changed from NUTS2 to NUTS1", +#' "New region NUTS2016 only", +#' "Discontinued region NUTS2013", +#' "Boundary shift NUTS2013", +#' "Recoded in NUTS2013", +#' "Recoded in NUTS2016" +#' ) +#' ) +#' +#' recode_to_nuts_2013(test_regional_codes) +#' @importFrom regions recode_nuts +#' @family regions functions +#' @seealso [regions::recode_nuts()] +#' @keywords internal +#' @export + +recode_to_nuts_2013 <- function(dat) { + warning("The 'recode_to_nuts_2013' function is deprecated. Use instead regions::recode_nuts(dat, nuts_year = 2013)") + + recode_nuts(dat, nuts_year = 2013) +} diff --git a/R/dic_order.R b/R/dic_order.R index 0171478e..0acaea6c 100755 --- a/R/dic_order.R +++ b/R/dic_order.R @@ -1,22 +1,30 @@ #' @title Order of Variable Levels from Eurostat Dictionary. #' @description Orders the factor levels. -#' @details Some variables, like classifications, have logical or conventional ordering. Eurostat data tables are nor neccessary ordered in this order. The function \code{dic_order} get the ordering from Eurostat classifications dictionaries. The function \code{\link{label_eurostat}} can also order factor levels of labels with argument \code{eu_order = TRUE}. -#' +#' @details Some variables, like classifications, have logical or conventional +#' ordering. Eurostat data tables are nor necessary ordered in this order. +#' The function [dic_order()] get the ordering from Eurostat classifications +#' dictionaries. The function [label_eurostat()] can also order factor levels +#' of labels with argument `eu_order = TRUE`. +#' #' @param x a variable (code or labelled) to get order for. -#' @param dic a name of the dictionary. Correspond a variable name in the -#' data_frame from \code{\link{get_eurostat}}. Can be also data_frame from -#' \code{\link{get_eurostat_dic}}. -#' @param type a type of the x. Could be \code{code} or \code{label}. -#' @export -#' @author Przemyslaw Biecek, Leo Lahti, Janne Huovari and Markus Kainu \email{ropengov-forum@@googlegroups.com} \url{http://github.com/ropengov/eurostat} +#' @param dic a name of the dictionary. Correspond a variable name in the +#' data_frame from [get_eurostat()]. Can be also data_frame from +#' [get_eurostat_dic()]. +#' @param type a type of the x. Could be `code` or `label`. +#' @author Przemyslaw Biecek, Leo Lahti, Janne Huovari and Markus Kainu #' @return A numeric vector of orders. +#' +#' @importFrom tibble is_tibble +#' @family helpers +#' +#' @export dic_order <- function(x, dic, type) { - if (!is_tibble(dic)) dic <- get_eurostat_dic(dic) - + if (!tibble::is_tibble(dic)) dic <- get_eurostat_dic(dic) + # code or label n_type <- match(type, c("code", "label")) if (is.na(n_type)) stop("Invalid type.") - + # get order y <- order(match(x, dic[[n_type]])) if (any(is.na(y))) stop("All orders were not found.") diff --git a/R/eurostat-defunct.R b/R/eurostat-defunct.R new file mode 100644 index 00000000..9837831c --- /dev/null +++ b/R/eurostat-defunct.R @@ -0,0 +1,26 @@ +#' @title Defunct functions in eurostat +#' +#' @description +#' This list of defunct functions is maintained to document changes to eurostat functions in a +#' transparent manner. +#' +#' @param ... Generic representation of old arguments +#' +#' @name eurostat-defunct +#' @aliases eurostat-defunct +#' +#' @details +#' The following functions are defunct: +#' +#' \itemize{ +#' \item \code{\link{grepEurostatTOC}}: Use \code{search_eurostat} instead +#' } +#' +#' +NULL + +#' @rdname eurostat-defunct +#' @export +grepEurostatTOC <- function(...) { + .Defunct(new = "search_eurostat") +} \ No newline at end of file diff --git a/R/eurostat-package.R b/R/eurostat-package.R index 27c24013..7f231408 100755 --- a/R/eurostat-package.R +++ b/R/eurostat-package.R @@ -1,25 +1,342 @@ -#' Brief summary of the eurostat package -#' -#' \tabular{ll}{ -#' Package: \tab eurostat\cr -#' Type: \tab Package\cr -#' Version: \tab See sessionInfo() or DESCRIPTION file\cr -#' Date: \tab 2014-2017\cr -#' License: \tab BSD_2_clause + LICENSE\cr -#' LazyLoad: \tab yes\cr -#' } +#' @title R Tools for Eurostat open data +#' +#' @description +#' Tools to download data from the Eurostat database +#' together with search and manipulation +#' utilities. +#' +#' @details #' -#' R Tools for Eurostat Open Data +#' | | | +#' | :--- | :-- | +#' | **Package** | eurostat | +#' | **Type** | Package | +#' | **Version** | `r packageVersion("eurostat")` | +#' | **Date** | 2014-2023 | +#' | **License** | `r as.character(utils::packageDescription("eurostat")["License"])`| +#' | **LazyLoad** | yes | #' #' @name eurostat-package #' @aliases eurostat #' @docType package -#' @title R Tools for Eurostat open data #' -#' @author Leo Lahti, Janne Huovari, Markus Kainu, Przemyslaw Biecek \email{ropengov-forum@@googlegroups.com} \url{https://ropengov.github.io/eurostat} +#' @author Leo Lahti, Janne Huovari, Markus Kainu, Przemyslaw Biecek #' @references -#' See citation("eurostat") -#' \url{https://ropengov.github.io/eurostat} +#' See `citation("eurostat")`: +#' +#' ```{r, echo=FALSE, comment="" } +#' citation("eurostat") +#' ``` +#' +#' When citing data downloaded from Eurostat, see section "Citing Eurostat data" +#' in [get_eurostat()] documentation. +#' +#' @details +#' # Eurostat +#' Eurostat website: \url{https://ec.europa.eu/eurostat} +#' Eurostat database: \url{https://ec.europa.eu/eurostat/web/main/data/database} +#' +#' Information about the data update schedule from Eurostat: +#' "Eurostat datasets are updated twice a day at 11:00 and 23:00 CET, if newer +#' data is available or for structural changes, for example for the +#' dimensions in the dataset. +#' +#' The Eurostat database always contains the latest version of the datasets, +#' meaning that there is no versioning or documentation of past versions of +#' the data." +#' +#' # Data source: Eurostat SDMX 2.1 Dissemination API +#' +#' Data is downloaded from Eurostat SDMX 2.1 API endpoint +#' as compressed TSV files that are transformed into tabular format. +#' See Eurostat documentation for more information: +#' \url{https://wikis.ec.europa.eu/display/EUROSTATHELP/API+SDMX+2.1+-+data+query} +#' +#' The new dissemination API replaces the old bulk download facility that was +#' used by Eurostat before October 2023 and by the eurostat R package versions +#' before 4.0.0. +#' See Eurostat documentation about the transition from Bulk Download to API +#' for more information about the differences between the old bulk download +#' facility and the data provided by the new API connection: +#' \url{https://wikis.ec.europa.eu/display/EUROSTATHELP/Transition+-+from+Eurostat+Bulk+Download+to+API} +#' +#' See especially the document Migrating_to_API_TSV.pdf that describes the +#' changes in TSV file format in new applications. +#' +#' For more information about SDMX 2.1, see SDMX standards: Section 7: +#' Guidelines for the use of web services, Version 2.1: +#' \url{https://sdmx.org/wp-content/uploads/SDMX_2-1_SECTION_7_WebServicesGuidelines.pdf} +#' +#' # Disclaimer: Availability of filtering functionalities +#' +#' Currently it only possible to download filtered data through API Statistics +#' (JSON API) when using `eurostat` package, although technically filtering +#' datasets downloaded through the SDMX Dissemination API is also supported by +#' Eurostat. We may support this feature in the future. In the meantime, if you +#' are interested in filtering Dissemination API data queries manually, please +#' consult the following Eurostat documentation: +#' \url{https://wikis.ec.europa.eu/display/EUROSTATHELP/API+SDMX+2.1+-+data+filtering} +#' +#' # Data source: Eurostat API Statistics (JSON API) +#' +#' Data is downloaded from Eurostat API Statistics. See Eurostat documentation +#' for more information about data queries in API Statistics +#' \url{https://wikis.ec.europa.eu/display/EUROSTATHELP/API+Statistics+-+data+query} +#' +#' This replaces the old JSON Web Services that was used by Eurostat before +#' February 2023 and by the eurostat R package versions before 3.7.13. +#' See Eurostat documentation about the migration from JSON web service to API +#' Statistics for more information about the differences between the old and +#' the new service: +#' \url{https://wikis.ec.europa.eu/display/EUROSTATHELP/API+Statistics+-+migrating+from+JSON+web+service+to+API+Statistics} +#' +#' For easily viewing which filtering options are available - in addition to +#' the default ones, time and language - Eurostat Web services Query builder +#' tool may be useful: +#' \url{https://ec.europa.eu/eurostat/web/query-builder} +#' +#' # Filtering datasets +#' +#' When using Eurostat API Statistics (JSON API), datasets can be filtered +#' before they are downloaded and saved in local memory. The general format +#' for filter parameters is `=`. +#' +#' Filter parameters are optional but the used dimension codes must be present +#' in the data product that is being queried. Dimension codes can +#' vary between different data products so it may be useful to examine new +#' datasets in Eurostat data browser beforehand. However, most if not all +#' Eurostat datasets concern European countries and contain information that +#' was gathered at some point in time, so `geo` and `time` dimension codes +#' can usually be used. +#' +#' `` and `` are case-insensitive and they can be written +#' in lowercase or uppercase in the query. +#' +#' Parameters are passed onto the `eurostat` package functions [get_eurostat()] +#' and [get_eurostat_json()] as a list item. If an individual item contains +#' multiple items, as it often can be in the case of `geo` parameters and +#' other optional items, they must be in the form of a vector: `c("FI", "SE")`. +#' For examples on how to use these parameters, see function examples below. +#' +#' ## Time parameters +#' +#' `time` and `time_period` address the same `TIME_PERIOD` dimension in the +#' dataset and can be used interchangeably. In the Eurostat documentation +#' it is stated that "Using more than one Time parameter in the same query +#' is not accepted", but practice has shown that actually Eurostat API allows +#' multiple `time` parameters in the same query. This makes it possible to +#' use R colon operator when writing queries, so `time = c(2015:2018)` +#' translates to `&time=2015&time=2016&time=2017&time=2018`. +#' +#' The only exception +#' to this is when the queried dataset contains e.g. quarterly data and +#' `TIME_PERIOD` is saved as `2015-Q1`, `2015-Q2` etc. Then it is possible +#' to use `time=2015-Q1&time=2015-Q2` style in the query URL, but this makes it +#' unfeasible to use the colon operator and requires a lot of manual typing. +#' +#' Because of this, it is useful to know about other time parameters as well: +#' * `untilTimePeriod`: return dataset items from the oldest record up until the +#' set time, for example "all data until 2000": `untilTimePeriod = 2000` +#' * `sinceTimePeriod`: return dataset items starting from set time, for example +#' "all datastarting from 2008": `sinceTimePeriod = 2008` +#' * `lastTimePeriod`: starting from the most recent time period, how many +#' preceding time periods should be returned? For example 10 most +#' recent observations: `lastTimePeriod = 10` +#' +#' Using both `untilTimePeriod` and `sinceTimePeriod` parameters in the same +#' query is allowed, making the usage of the R colon operator unnecessary. +#' In the case of quarterly data, using `untilTimePeriod` and `sinceTimePeriod` +#' parameters also works, as opposed to the colon operator, so it is generally +#' safer to use them as well. +#' +#' ## Other dimensions +#' +#' In [get_eurostat_json()] examples `nama_10_gdp` dataset is filtered with +#' two additional filter parameters: +#' * `na_item = "B1GQ"` +#' * `unit = "CLV_I10"` +#' +#' Filters like these are most likely unique to the `nama_10_gdp` dataset +#' (or other datasets within the same domain) and should +#' not be used with others dataset without user discretion. +#' By using [label_eurostat()] we know that `"B1GQ"` stands for +#' "Gross domestic product at market prices" and +#' `"CLV_I10"` means "Chain linked volumes, index 2010=100". +#' +#' Different dimension codes can be translated to a natural language by using +#' the [get_eurostat_dic()] function, which returns labels for individual +#' dimension items such as `na_item` and `unit`, as opposed to +#' [label_eurostat()] which does it for whole datasets. For example, the +#' parameter `na_item` stands for "National accounts indicator (ESA 2010)" and +#' `unit` stands for "Unit of measure". +#' +#' ## Language +#' +#' All datasets have metadata available in English, French and German. If no +#' parameter is given, the labels are returned in English. +#' +#' Example: +#' * `lang = "fr"` +#' +#' ## More information +#' +#' For more information about data filtering see Eurostat documentation +#' on API Statistics: +#' \url{https://wikis.ec.europa.eu/display/EUROSTATHELP/API+Statistics+-+data+query#APIStatisticsdataquery-TheparametersdefinedintheRESTrequest} +#' +#' # Data source: Eurostat Table of Contents +#' +#' The Eurostat Table of Contents (TOC) is downloaded from +#' \url{https://ec.europa.eu/eurostat/api/dissemination/catalogue/toc/txt?lang=en} +#' (default) or from French or German language variants: +#' \url{https://ec.europa.eu/eurostat/api/dissemination/catalogue/toc/txt?lang=fr} +#' \url{https://ec.europa.eu/eurostat/api/dissemination/catalogue/toc/txt?lang=de} +#' +#' See Eurostat documentation on TOC items: +#' \url{https://wikis.ec.europa.eu/display/EUROSTATHELP/API+-+Detailed+guidelines+-+Catalogue+API+-+TOC} +#' +#' # Data source: GISCO - General Copyright +#' +#' "Eurostat's general copyright notice and licence policy is applicable and +#' can be consulted here: +#' +#' +#' Please also be aware of the European Commission's general conditions: +#' +#' +#' Moreover, there are specific provisions applicable to some of the following +#' datasets available for downloading. The download and usage of these data +#' is subject to their acceptance: +#' +#' * Administrative Units / Statistical Units +#' * Population distribution / Demography +#' * Transport Networks +#' * Land Cover +#' * Elevation (DEM)" +#' +#' Of the abovementioned datasets, Administrative Units / Statistical Units +#' is applicable if the user wants to draw maps with borders provided by +#' GISCO / EuroGeographics. +#' +#' # Data source: GISCO - Administrative Units / Statistical Units +#' +#' The following copyright notice is provided for end user convenience. +#' Please check up-to-date copyright information from the GISCO website: +#' [GISCO: Geographical information and maps - Administrative units/statistical units](https://ec.europa.eu/eurostat/web/gisco/geodata/reference-data/administrative-units-statistical-units) +#' +#' "In addition to the [general copyright and licence policy](https://ec.europa.eu/eurostat/web/main/about/policies/copyright) applicable to the whole Eurostat website, the following +#' specific provisions apply to the datasets you are downloading. The download +#' and usage of these data is subject to the acceptance of the following +#' clauses: +#' +#' 1. The Commission agrees to grant the non-exclusive and not transferable +#' right to use and process the Eurostat/GISCO geographical data downloaded +#' from this page (the "data"). +#' +#' 1. The permission to use the data is granted on condition that: +#' 1. the data will not be used for commercial purposes; +#' 2. the source will be acknowledged. A copyright notice, as specified +#' below, will have to be visible on any printed or electronic publication +#' using the data downloaded from this page." +#' +#' ## Copyright notice +#' +#' When data downloaded from this page is used in any printed or electronic +#' publication, in addition to any other provisions applicable to the whole +#' Eurostat website, data source will have to be acknowledged in the legend of +#' the map and in the introductory page of the publication with the following +#' copyright notice: +#' +#' EN: © EuroGeographics for the administrative boundaries +#' +#' FR: © EuroGeographics pour les limites administratives +#' +#' DE: © EuroGeographics bezüglich der Verwaltungsgrenzen +#' +#' For publications in languages other than English, French or German, the +#' translation of the copyright notice in the language of the publication shall +#' be used. +#' +#' If you intend to use the data commercially, please contact EuroGeographics +#' for information regarding their licence agreements." +#' +#' # Eurostat: Copyright notice and free re-use of data +#' +#' The following copyright notice is provided for end user convenience. +#' Please check up-to-date copyright information from the eurostat website: +#' +#' +#' "(c) European Union, 1995 - today +#' +#' Eurostat has a policy of encouraging free re-use of its data, both for +#' non-commercial and commercial purposes. All statistical data, metadata, +#' content of web pages or other dissemination tools, official publications +#' and other documents published on its website, with the exceptions listed +#' below, can be reused without any payment or written licence provided that: +#' +#' * the source is indicated as Eurostat; +#' * when re-use involves modifications to the data or text, this must be +#' stated clearly to the end user of the information." +#' +#' For exceptions to the abovementioned principles see +#' [Eurostat website](https://ec.europa.eu/eurostat/about-us/policies/copyright) +#' +#' # Citing Eurostat data +#' +#' For citing datasets, use [get_bibentry()] to build a bibliography that +#' is suitable for your reference manager of choice. +#' +#' When using Eurostat data in other contexts than academic publications that +#' in-text citations or footnotes/endnotes, the following guidelines may be +#' helpful: +#' +#' * The origin of the data should always be mentioned as "Source: Eurostat". +#' +#' * The online dataset codes(s) should also be provided in order to ensure +#' transparency and facilitate access to the Eurostat data and related +#' methodological information. For example: +#' "Source: Eurostat (online data code: namq_10_gdp)" +#' +#' * Online publications (e.g. web pages, PDF) should include a clickable +#' link to the dataset using the bookmark functionality available in the +#' Eurostat data browser. +#' +#' It should be avoided to associate different entities (e.g. Eurostat, +#' National Statistical Offices, other data providers) to the same dataset or +#' indicator without specifying the role of each of them in the treatment of +#' data. +#' +#' See also section "Eurostat: Copyright notice and free re-use of data" +#' in [get_eurostat()] documentation. +#' +#' # Strategies for handling large datasets more efficiently +#' +#' Most Eurostat datasets are relatively manageable, at least on a machine +#' with 16 GB of RAM. The largest dataset in Eurostat database, at the time +#' of writing this, had 148362539 (148 million) values, which results in an +#' object with 148 million rows in tidy data (long) format. The test machine +#' with 16 GB of RAM was able to handle the second largest dataset in the +#' database with 91 million values (rows). +#' +#' There are still some methods to make data fetching +#' functions perform faster: +#' +#' * turn caching off: `get_eurostat(cache = FALSE)` +#' * turn cache compression off (may result in rather large cache files!): +#' `get_eurostat(compress_file = FALSE)` +#' * if you want faster caching with manageable file sizes, use stringsAsFactors: +#' `get_eurostat(cache = TRUE, compress_file = TRUE, stringsAsFactors = TRUE)` +#' * Use faster data.table functions: `get_eurostat(use.data.table = TRUE)` +#' * Keep column processing to a minimum: +#' `get_eurostat(time_format = "raw", type = "code")` etc. +#' * Read `get_eurostat()` function documentation carefully so you understand +#' what different arguments do +#' * Filter the dataset so that you fetch only the parts you need! +#' #' @examples library(eurostat) +#' @section regions functions: +#' For working with sub-national statistics the basic functions of the +#' regions package are imported . #' @keywords package +#' @seealso `help("regions")`, NULL diff --git a/R/eurotime2date.R b/R/eurotime2date.R index 0d0efe87..a59a030e 100755 --- a/R/eurotime2date.R +++ b/R/eurotime2date.R @@ -1,77 +1,154 @@ -#' @title Date Conversion from Eurostat Time Format -#' @description Date conversion from Eurostat time format. A function to -#' convert Eurostat time values to objects of class \code{\link{Date}} +#' @title Date Conversion from New Eurostat Time Format +#' @description +#' Date conversion from Eurostat time format. A function to +#' convert Eurostat time values to objects of class [Date()] #' representing calendar dates. +#' @details +#' Available patterns are YYYY (year), YYYY-SN (semester), YYYY-QN (quarter), +#' YYYY-MM (month), YYYY-WNN (week) and YYYY-MM-DD (day). #' @param x a charter string with time information in Eurostat time format. -#' @param last a logical. If \code{FALsE} (default) the date is -#' the first date of the period (month, quarter or year). If \code{TRUE} +#' @param last a logical. If `FALSE` (default) the date is +#' the first date of the period (month, quarter or year). If `TRUE` #' the date is the last date of the period. +#' @references +#' See `citation("eurostat")`: +#' +#' ```{r, echo=FALSE, comment="#" } +#' citation("eurostat") +#' ``` +#' +#' @return an object of class [Date()]. +#' @author Janne Huovari +#' @family helpers +#' @seealso [lubridate::ymd()] +#' @examplesIf check_access_to_data() +#' \donttest{ +#' na_q <- get_eurostat("namq_10_pc", time_format = "raw") +#' na_q$TIME_PERIOD <- eurotime2date(x = na_q$TIME_PERIOD) +#' unique(na_q$TIME_PERIOD) +#' } +#' +#' \dontrun{ +#' # Test for weekly data +#' get_eurostat( +#' id = "lfsi_abs_w", +#' select_time = c("W"), +#' time_format = "date" +#' ) +#' } +#' +#' @importFrom lubridate ymd +#' @importFrom ISOweek ISOweek2date +#' @importFrom dplyr inner_join +#' #' @export -#' @return an object of class \code{\link{Date}}. -#' @author Janne Huovari \email{janne.huovari@@ptt.fi} -#' @examples \dontrun{ -#' na_q <- get_eurostat("namq_10_pc", time_format = "raw") -#' na_q$time <- eurotime2date(x = na_q$time) -#' -#' un <- get_eurostat("une_rt_m", time_format = "raw") -#' un$time <- eurotime2date(x = un$time) -#' -#' na_a <- get_eurostat("nama_10_pc", time_format = "raw") -#' na_a$time <- eurotime2date(x = na_a$time) -#' -#' eur_d <- get_eurostat("ert_bil_eur_d", time_format = "raw") -#' eur_d$time <- eurotime2date(x = eur_d$time) -#' } -eurotime2date <- function(x, last = FALSE){ +eurotime2date <- function(x, last = FALSE) { if (!is.factor(x)) x <- factor(x) - times <- levels(x) - year <- substr(times, 1, 4) - subyear <- substr(times, 5, 7) - tcode <- substr(subyear[1], 1, 1) # type of time data - if (tcode != "_" && nchar(times[1]) > 7){ - days <- substr(times, 8, 10) - tcode <- substr(days[1], 1, 1) # type of time data if daily + unique_times <- levels(x) + year <- substr(unique_times, 1, 4) + # 5th character is always "-", if there is one + #from "YYYY-QN" the following line would extract "QN", from "YYYY-WNN" "WNN" + subyear <- substr(unique_times, 6, 8) + # the first character tells the type of the date + tcode <- substr(subyear[1], 1, 1) + if (tcode != "_" && nchar(unique_times[1]) > 8) { + days <- substr(unique_times, 8, 10) #extract -DD from YYYY-MM-DD + tcode <- substr(days[1], 1, 1) # tcode for daily data is "-" } - + if (tcode == "") tcode <- "Y" - - day <- "01" # default for day - - # for yearly data + + day <- "01" # default for day + if (tcode == "Y") { + # for yearly data period <- "01" - # for bi-annual } else if (tcode == "S") { + # for bi-annual ("semester") data lookup <- c(S1 = "01", S2 = "07") - period <- lookup[subyear] - # for quarterly + period <- lookup[subyear] } else if (tcode == "Q") { + # quarterly data lookup <- c(Q1 = "01", Q2 = "04", Q3 = "07", Q4 = "10") - period <- lookup[subyear] - # for montly - } else if (tcode == "M") { + period <- lookup[subyear] + } else if (tcode == "0" || tcode == "1") { + # monthly data period <- gsub("M", "", subyear) - # for daily - } else if (tcode == "D") { + } else if (tcode == "W") { + # weekly data + # We need period to be of format "WNN", e.g. W01 for 1st week of the year + period <- subyear + } else if (tcode == "-") { + # daily data period <- gsub("M", "", subyear) day <- gsub("D", "", days) - # for year intervals - } else if (tcode == "_") { - warning("Time format is a year interval. No date conversion was made.") - return(x) - # for unkown } else { - warning("Unknown time code, ", tcode, ". No date conversion was made.\n - Please fill bug report at https://github.com/rOpenGov/eurostat/issues.") + # nocov start + warning( + "Unknown time code, ", tcode, ". No date conversion was made.\n + Please fill bug report at ", + "https://github.com/rOpenGov/eurostat/issues." + ) return(x) + # nocov end } - - levels(x) <- paste0(year, "-", period, "-", day) - + # The date as the last date of the period - if (last == TRUE) { - shift <- c("Y" = 367, "S" = 186, "Q" = 96, "M" = 32, "D" = 0)[tcode] - levels(x) <- lubridate::ymd(cut(lubridate::ymd(levels(x)) + shift, "month")) - 1 + if (tcode == "W") { + # in some datasets week number can be larger than 53, e.g. 99 + # ISOweek2date does not support such week numbers -> they are coerced + # to W01-1 or W01-7 + if (any(substr(period, 2, 3) > 53)) { + warning(paste("Some TIME_PERIOD fields have invalid week values (> 53).", + "Coercing invalid fields to format YYYY-W01", + "(the first week of the year). If you wish to handle", + "weeks with invalid values manually please use", + "parameter time_format = 'raw' in get_eurostat.")) + invalid_w_numbers <- which(substr(period, 2, 3) > 53) + period[invalid_w_numbers] <- "W01" + } + + # Range is 1-7 here, not 01-07. 1 = Monday, 2 = Tuesday etc. + day <- ifelse(last == TRUE, 7, 1) + levels(x) <- paste0(year, "-", period, "-", day) + unique_dates <- unique(x) + column_names <- c("orig", "date") + d <- data.frame( + matrix( + nrow = length(unique_dates), + ncol = length(column_names) + ) + ) + colnames(d) <- column_names + d$orig <- unique_dates + d$date <- ISOweek::ISOweek2date(unique_dates) + + # NEW CODE: data.table + # d <- as.data.table(d) + # x <- as.data.table(x) + + x <- as.data.frame(x) + colnames(x) <- "orig" + + # NEW CODE: data.table + # y <- x[d, on = "orig"]$date + + y <- dplyr::inner_join(x, d, by = "orig") + y <- y$date + return(y) + } + + levels(x) <- paste0(year, "-", period, "-", day) + + # For times other than weeks + if (last == TRUE && tcode != "W") { + shift <- c( + "Y" = 367, "S" = 186, "Q" = 96, "0" = 32, "1" = 32, "D" = 0 + )[tcode] + + levels(x) <- lubridate::ymd( + cut(lubridate::ymd(levels(x)) + shift, "month") + ) - 1 } y <- lubridate::ymd(x) y diff --git a/R/eurotime2num.R b/R/eurotime2num.R index b474d58e..2e5fcb8d 100755 --- a/R/eurotime2num.R +++ b/R/eurotime2num.R @@ -1,60 +1,74 @@ #' @title Conversion of Eurostat Time Format to Numeric #' @description A conversion of a Eurostat time format to numeric. -#' @details Bi-annual, quarterly and monthly data is presented as fraction of -#' the year in beginning of the period. Conversion of daily data is not -#' supported. +#' @details +#' Bi-annual (semester), quarterly, monthly and weekly data can be presented as +#' a fraction of the year in beginning of the period. Conversion of daily data +#' is not supported. #' @param x a charter string with time information in Eurostat time format. +#' @return see [as.numeric()]. +#' @author Janne Huovari , Pyry Kantanen +#' @family helpers +#' @examplesIf check_access_to_data() +#' \donttest{ +#' na_q <- get_eurostat("namq_10_pc", time_format = "raw") +#' na_q$TIME_PERIOD <- eurotime2num(x = na_q$TIME_PERIOD) +#' +#' unique(na_q$TIME_PERIOD) +#' } +#' #' @export -#' @return see \code{\link{as.numeric}}. -#' @author Janne Huovari \email{janne.huovari@@ptt.fi} -#' @examples \dontrun{ -#' na_q <- get_eurostat("namq_10_pc", time_format = "raw") -#' na_q$time <- eurotime2num(x = na_q$time) -#' -#' un <- get_eurostat("une_rt_m", time_format = "raw") -#' un$time <- eurotime2num(x = un$time) -#' -#' na_a <- get_eurostat("nama_10_pc", time_format = "raw") -#' na_a$time <- eurotime2num(x = na_a$time) -#' } -eurotime2num <- function(x){ - +eurotime2num <- function(x) { x <- as.factor(x) times <- levels(x) - if (nchar(times[1]) > 7){ - tcode <- substr(times[1], 8, 8) # daily + if (nchar(times[1]) > 8) { + # Finds the only format that is longer than YYYY-WNN (weeks, 8 chars) + # Day/date notation: YYYY-MM-DD, 10 chars + # tcode <- substr(times[1], 8, 8) + tcode <- "D" } else { - tcode <- substr(times[1], 5, 5) # type of time data - if (tcode == "") tcode <- "Y" + # Possible tcodes: S, Q, 0 or 1 (months), W + # tcode: type of time data + tcode <- substr(times[1], 6, 6) + # if tcode is empty, the data is probably annual + if (tcode == "0" || tcode == "1") { + tcode <- "M" + } else if (tcode == "") { + tcode <- "A" + } } - - # check input type - if (!(tcode %in% c("Y", "S", "Q", "M", "_"))) { + # check input type + if (!(tcode %in% c("A", "S", "Q", "M", "W"))) { # for daily - if (tcode == "D"){ + if (tcode == "D") { warning("Time format is daily data. No numeric conversion was made.") - # for year intervals - } else if (tcode == "_") { - warning("Time format is a year interval. No numeric conversion was made.") - # for unkown } else { - warning("Unknown time code, ", tcode, ". No numeric conversion was made.\n - Please fill bug report at https://github.com/rOpenGov/eurostat/issues.") + # nocov start + warning( + paste0( + "Unknown time code, ", tcode, ". No numeric conversion was made.\n", + "Please fill bug report at ", + "https://github.com/rOpenGov/eurostat/issues." + ) + ) + # nocov end } - - return(x) + + return(x) } - + year <- substr(times, 1, 4) - subyear <- substr(times, 6, 7) + subyear <- substr(times, 6, 8) + # The only characters that can be present are S, Q and W + subyear <- gsub("[SQW]", "", subyear) + subyear[subyear == ""] <- 1 - - levels(x) <- as.numeric(year) + - (as.numeric(subyear) - 1) * 1/c(Y = 1, S = 2, Q = 4, M = 12)[tcode] + levels(x) <- as.numeric(year) + + (as.numeric(subyear) - 1) * + 1 / c(A = 1, S = 2, Q = 4, M = 12, W = 53)[tcode] y <- as.numeric(as.character(x)) y } diff --git a/R/firstlib.R b/R/firstlib.R index 3b11db96..12f2f9e4 100755 --- a/R/firstlib.R +++ b/R/firstlib.R @@ -1,32 +1 @@ -#' @import methods -#' @importFrom broom tidy -#' @importFrom classInt classIntervals -#' @importFrom dplyr %>% -#' @importFrom dplyr filter -#' @importFrom dplyr mutate -#' @importFrom dplyr select -#' @importFrom dplyr filter -#' @importFrom dplyr left_join -#' @importFrom httr build_url -#' @importFrom httr content -#' @importFrom httr GET -#' @importFrom httr status_code -#' @importFrom jsonlite fromJSON -#' @importFrom RColorBrewer brewer.pal -#' @importFrom readr read_tsv -#' @importFrom readr col_character -#' @importFrom sp merge -#' @importFrom stringi stri_match_first_regex -#' @importFrom stringr str_replace_all -#' @importFrom sf st_as_sf -#' @importFrom sf as_Spatial -#' @importFrom sf st_read -#' @importFrom tibble data_frame -#' @importFrom tibble is_tibble -#' @importFrom tibble as_data_frame -#' @importFrom tidyr separate -#' @importFrom tidyr gather_ -#' @importFrom utils download.file -#' @importFrom methods as -#' @importFrom utils data .EurostatEnv <- new.env() diff --git a/R/get_bibentry.R b/R/get_bibentry.R new file mode 100755 index 00000000..0a2fc95e --- /dev/null +++ b/R/get_bibentry.R @@ -0,0 +1,157 @@ +#' @title Create A Data Bibliography +#' @description Creates a bibliography from selected Eurostat data files, +#' including last Eurostat update, URL access data, and optional keywords +#' set by the user. +#' @param code A Eurostat data code or a vector of Eurostat data codes as +#' character or factor. +#' @param keywords A list of keywords to be added to the entries. Defaults +#' to `NULL`. +#' @param format Default is `'Biblatex'`, alternatives are `'bibentry'` +#' or `'Bibtex'` (not case sensitive) +#' @inheritParams get_eurostat +#' @author Daniel Antal, Przemyslaw Biecek +#' @inheritSection eurostat-package Citing Eurostat data +#' +#' @return a bibentry, Bibtex or Biblatex object. +#' +#' @seealso [utils::bibentry] [RefManageR::toBiblatex] +#' +#' @examplesIf check_access_to_data() +#' \dontrun{ +#' my_bibliography <- get_bibentry( +#' code = c("tran_hv_frtra", "tec00001"), +#' keywords = list( +#' c("transport", "freight", "multimodal data", "GDP"), +#' c("economy and finance", "annual", "national accounts", "GDP") +#' ), +#' format = "Biblatex" +#' ) +#' my_bibliography +#' } +#' +#' @importFrom lubridate dmy year month day +#' @importFrom utils toBibtex person +#' @importFrom RefManageR BibEntry toBiblatex +#' @importFrom stringr str_glue +#' +#' @export +get_bibentry <- function(code, + keywords = NULL, + format = "Biblatex", + lang = "en") { + if (!any(class(code) %in% c("character", "factor"))) { + stop("The code(s) must be added as character vector") + } + if (!is.null(keywords) && !inherits(keywords, "list")) { + stop("If keyword(s) are added, they must be added as a list.") + } + + code <- as.character(code) + format <- tolower(as.character(format)) + + if (!format %in% c("bibentry", "bibtex", "biblatex")) { + warning("The ", format, " is not recognized, will return Biblatex as + default.") + format <- "biblatex" + } + + toc <- get_eurostat_toc(lang = lang) + # Remove hierarchy column to make duplicated() check more viable + toc <- toc[, !names(toc) %in% c("hierarchy")] + toc <- toc[toc$code %in% code, ] + toc <- toc[!duplicated(toc), ] + + urldate <- as.character(Sys.Date()) + + lang <- check_lang(lang) + + lang_long <- switch(lang, + en = "english", + fr = "french", + de = "german") + + if (nrow(toc) == 0) { + warning(paste( + "None of the codes were found in the Eurostat table of contents.\n", + "Please check the 'code' argument in get_bibentry() for errors:\n", + paste(code, collapse = ", ") + ) + ) + return() + } + + not_found <- NULL + not_found <- !(code %in% toc$code) + not_found <- code[not_found] + if (is.character(not_found) && length(not_found) != 0) { + warning(paste( + "The following codes were not found in the Eurostat table of contents.\n", + "Bibliography object returned without the following items:\n", + paste(not_found, collapse = ", ") + )) + } + + for (i in seq_len(nrow(toc))) { + last_update_date <- lubridate::dmy(toc[["last.update.of.data"]][[i]]) + last_update_year <- lubridate::year(last_update_date) + last_update_month <- lubridate::month(last_update_date) + last_update_day <- lubridate::day(last_update_date) + + dataset_key <- paste0( + toc$code[i], "-", last_update_year, "-", last_update_month, "-", + last_update_day + ) + # replace troublesome _ with - + dataset_key <- gsub("_", "-", dataset_key) + + dataset_id <- toc$code[i] + # replace troublesome _ with \_ for bibtex and biblatex references + if (format %in% c("bibtex", "biblatex")) { + dataset_id <- gsub("_", "\\\\_", dataset_id) + } + + if (!is.null(keywords)) { # if user entered keywords + if (length(keywords) < i) { # last keyword not entered + keyword_entry <- NULL + } else if (nchar(keywords)[i] > 0) { # not empty keyword entry + keyword_entry <- paste(keywords[[i]], collapse = ", ") + } + } else { + keyword_entry <- NULL + } + + entry <- RefManageR::BibEntry( + bibtype = "misc", + key = dataset_key, + title = paste0(toc$title[i], " (", dataset_id, ")"), + url = paste0("https://ec.europa.eu/eurostat/web/products-datasets/product?code=", + toc$code[i]), + language = lang_long, + # date = last_update_date, + year = last_update_year, + author = c( + utils::person(given = "Eurostat") + ), + keywords = keyword_entry, + urldate = urldate, + type = "Dataset", + note = stringr::str_glue( + paste("Accessed {as.Date(urldate)},", + "dataset last updated {as.Date(last_update_date)}") + ) + ) + + if (i > 1) { + entries <- c(entries, entry) + } else { + entries <- entry + } + } + + if (format == "bibtex") { + entries <- utils::toBibtex(entries) + } else if (format == "biblatex") { + entries <- RefManageR::toBiblatex(entries) + } + entries +} diff --git a/R/get_eurostat.R b/R/get_eurostat.R index 4ef13d79..013fea38 100755 --- a/R/get_eurostat.R +++ b/R/get_eurostat.R @@ -1,197 +1,786 @@ -#' @title Read Eurostat Data -#' @description Download data sets from Eurostat \url{ec.europa.eu/eurostat}. -#' @param id A code name for the dataset of interest. -#' See \code{\link{search_eurostat}} or details for how to get code. -#' @param filters a "none" (default) to get a whole dataset or a named list of -#' filters to get just part of the table. Names of list objects are -#' Eurostat variable codes and values are vectors of observation codes. -#' If \code{NULL} the whole -#' dataset is returned via API. More on details. See more on filters and -#' limitations per query via API from for -#' \code{\link{get_eurostat_json}}. -#' @param time_format a string giving a type of the conversion of the time -#' column from the eurostat format. A "date" (default) convers to -#' a \code{\link{Date}} with a first date of the period. -#' A "date_last" convers to a \code{\link{Date}} with -#' a last date of the period. A "num" convers to a numeric and "raw" -#' does not do conversion. See \code{\link{eurotime2date}} and -#' \code{\link{eurotime2num}}. -#' @param type A type of variables, "code" (default) or "label". -#' @param select_time a character symbol for a time frequence or NULL, -#' which is used by default as most datasets have just one time -#' frequency. For datasets with multiple time -#' frequencies, select the desired time format with: -#' Y = annual, S = semi-annual, Q = quarterly, M = monthly. -#' For all frequencies in same data frame \code{time_format = "raw"} -#' should be used. -#' @param cache a logical whether to do caching. Default is \code{TRUE}. Affects -#' only queries from the bulk download facility. -#' @param update_cache a locigal whether to update cache. Can be set also with -#' options(eurostat_update = TRUE) -#' @param cache_dir a path to a cache directory. The directory have to exist. -#' The \code{NULL} (default) uses and creates -#' 'eurostat' directory in the temporary directory from -#' \code{\link{tempdir}}. Directory can also be set with -#' \code{option} eurostat_cache_dir. -#' @param compress_file a logical whether to compress the -#' RDS-file in caching. Default is \code{TRUE}. -#' @param stringsAsFactors if \code{TRUE} (the default) variables are -#' converted to factors in original Eurostat order. If \code{FALSE} -#' they are returned as a character. -#' @param keepFlags a logical whether the flags (e.g. "confidential", -#' "provisional") should be kept in a separate column or if they -#' can be removed. Default is \code{FALSE}. For flag values see: -#' \url{http://ec.europa.eu/eurostat/data/database/information}. -#' Also possible non-real zero "0n" is indicated in flags column. -#' Flags are not available for eurostat API, so \code{keepFlags} -#' can not be used with a \code{filters}. -#' @param ... further argument for \code{\link{get_eurostat_json}}. -#' @export -#' @author Przemyslaw Biecek, Leo Lahti, Janne Huovari and Markus Kainu \email{ropengov-forum@@googlegroups.com} \url{http://github.com/ropengov/eurostat} -#' @details Data sets are downloaded from -#' \href{http://ec.europa.eu/eurostat/estat-navtree-portlet-prod/BulkDownloadListing}{the Eurostat bulk download facility} or from The Eurostat Web Services -#' \href{http://ec.europa.eu/eurostat/web/json-and-unicode-web-services}{JSON API}. -#' If only the table \code{id} is given, the whole table is downloaded from the -#' bulk download facility. If also \code{filters} are defined the JSON API is -#' used. +#' @title Get Eurostat Data +#' +#' @description +#' Download data sets from Eurostat \url{https://ec.europa.eu/eurostat} +#' +#' @param id +#' A unique identifier / code for the dataset of interest. If code is not +#' known [search_eurostat()] function can be used to search Eurostat table +#' of contents. +#' @param filters +#' A named list of filters. Names of list objects are Eurostat +#' variable codes and values are vectors of observation codes. If `NULL` +#' (default) the whole dataset is returned. See details for more information +#' on filters and limitations per query. +#' @param time_format +#' a string giving a type of the conversion of the time column from the +#' eurostat format. The default argument "`date`" converts to a [Date()] class +#' with the date being the first day of the period. A "`date_last`" argument +#' converts the dataset date to a [Date()] class object with the difference +#' that the exact date is the last date of the period. Period can be year, +#' semester (half year), quarter, month, or week (See [eurotime2date()] for +#' more information). +#' Argument "`num`" converts the date into a numeric (integer) meaning that +#' the first day of the year 2000 is close to 2000.01 and the last day of the +#' year is close to 2000.99 (see [eurotime2num()] for more information). +#' Using the argument "`raw`" preserves the dates as they were in the original +#' Eurostat data. +#' @param type +#' A type of variables, "`code`" (default), "`label`" or "`both`". +#' The parameter "`both`" will return a data_frame with named vectors, +#' labels as values and codes as names. +#' @param select_time +#' a character symbol for a time frequency or `NULL`, +#' which is used by default as most datasets have just one time +#' frequency. For datasets with multiple time +#' frequencies, select one or more of the desired frequencies with: +#' "Y" (or "A") = annual, "S" = semi-annual / semester, "Q" = quarterly, +#' "M" = monthly, "W" = weekly. For all frequencies in same data +#' frame `time_format = "raw"` should be used. +#' @param lang 2-letter language code, default is "`en`" (English), other +#' options are "`fr`" (French) and "`de`" (German). Used for labeling datasets. +#' @param cache +#' a logical whether to do caching. Default is `TRUE`. +#' @param update_cache +#' a logical whether to update cache. Can be set also with +#' `options(eurostat_update = TRUE)` +#' @param cache_dir +#' a path to a cache directory. `NULL` (default) uses and creates +#' 'eurostat' directory in the temporary directory defined by base R +#' [tempdir()] function. The user can set the cache directory to an existing +#' directory by using this argument. The cache directory can also be set with +#' [set_eurostat_cache_dir()] function. +#' @param compress_file +#' a logical whether to compress the RDS-file in caching. Default is `TRUE`. +#' @param stringsAsFactors +#' if `TRUE` (the default) variables are converted to factors in the original +#' Eurostat order. If `FALSE` they are returned as strings. +#' @param keepFlags +#' a logical whether the flags (e.g. "confidential", +#' "provisional") should be kept in a separate column or if they +#' can be removed. Default is `FALSE`. For flag values see: +#' . +#' Also possible non-real zero "0n" is indicated in flags column. +#' Flags are not available for eurostat API, so `keepFlags` +#' can not be used with a `filters`. +#' @param use.data.table Use faster data.table functions? Default is FALSE. +#' On Windows requires that RTools is installed. +#' @inheritDotParams get_eurostat_json +#' +#' @inherit eurostat-package references +#' +#' @inheritSection eurostat-package Eurostat: Copyright notice and free re-use of data +#' @inheritSection eurostat-package Filtering datasets +#' @inheritSection eurostat-package Citing Eurostat data +#' @inheritSection eurostat-package Disclaimer: Availability of filtering functionalities +#' @inheritSection eurostat-package Strategies for handling large datasets more efficiently +#' +#' @author +#' Przemyslaw Biecek, Leo Lahti, Janne Huovari, Markus Kainu and Pyry Kantanen #' +#' @details +#' Datasets are downloaded from +#' [the Eurostat SDMX 2.1 API](https://wikis.ec.europa.eu/display/EUROSTATHELP/Transition+-+from+Eurostat+Bulk+Download+to+API) +#' in TSV format or from The Eurostat +#' [API Statistics JSON API](https://wikis.ec.europa.eu/display/EUROSTATHELP/API+Statistics+-+data+query). +#' If only the table `id` is given, the whole table is downloaded from the +#' SDMX API. If any `filters` are given JSON API is used instead. +#' #' The bulk download facility is the fastest method to download whole datasets. -#' It is also often the only way as the JSON API has limitation of maximum -#' 50 sub-indicators at time and whole datasets usually exceeds that. Also, -#' it seems that multi frequency datasets can only be retrived via -#' bulk download facility and the \code{select_time} is not available for +#' It is also often the only way as the JSON API has limitation of maximum +#' 50 sub-indicators at time and whole datasets usually exceeds that. Also, +#' it seems that multi frequency datasets can only be retrieved via +#' bulk download facility and the `select_time` is not available for #' JSON API method. -#' -#' If your connection is thru a proxy, you probably have to set proxy parameters -#' to use JSON API, see \code{\link{get_eurostat_json}}. -#' -#' By default datasets from the bulk download facility are cached as they are -#' often rather large. Caching is not (currently) possible for datasets from -#' JSON API. +#' +#' If your connection is through a proxy, you may have to set proxy parameters +#' to use JSON API, see [get_eurostat_json()]. +#' +#' By default datasets are cached to reduce load on Eurostat services and +#' because some datasets can be quite large. #' Cache files are stored in a temporary directory by default or in -#' a named directory if cache_dir or option eurostat_cache_dir is defined. -#' The cache can be emptied with \code{\link{clean_eurostat_cache}}. -#' -#' The \code{id}, a code, for the dataset can be searched with -#' the \code{\link{search_eurostat}} or from the Eurostat database -#' \url{http://ec.europa.eu/eurostat/data/database}. The Eurostat +#' a named directory (See [set_eurostat_cache_dir()]). +#' The cache can be emptied with [clean_eurostat_cache()]. +#' +#' The `id`, a code, for the dataset can be searched with +#' the [search_eurostat()] or from the Eurostat database +#' . The Eurostat #' database gives codes in the Data Navigation Tree after every dataset #' in parenthesis. -#' @return a tibble. One column for each dimension in the data, -#' the time column for a time dimension and -#' the values column for numerical values. -#' Eurostat data does not include all missing values and a treatment of -#' missing values depend on source. In bulk download -#' facility missing values are dropped if all dimensions are missing -#' on particular time. In JSON API missing values are dropped -#' only if all dimensions are missing on all times. The data from -#' bulk download facility can be completed for example with -#' \code{\link[tidyr]{complete}}. -#' @seealso \code{\link{search_eurostat}}, \code{\link{label_eurostat}} -#' @examples +#' +#' @return +#' a tibble. +#' +#' One column for each dimension in the data, the time column for a time +#' dimension and the values column for numerical values. Eurostat data does +#' not include all missing values and a treatment of missing values depend +#' on source. In bulk download facility missing values are dropped if all +#' dimensions are missing on particular time. In JSON API missing values are +#' dropped only if all dimensions are missing on all times. The data from +#' bulk download facility can be completed for example with [tidyr::complete()]. +#' +#' @seealso +#' [search_eurostat()], [label_eurostat()] +#' +#' @examplesIf check_access_to_data() #' \dontrun{ #' k <- get_eurostat("nama_10_lp_ulc") #' k <- get_eurostat("nama_10_lp_ulc", time_format = "num") #' k <- get_eurostat("nama_10_lp_ulc", update_cache = TRUE) -#' dir.create(file.path(tempdir(), "r_cache")) -#' k <- get_eurostat("nama_10_lp_ulc", -#' cache_dir = file.path(tempdir(), "r_cache")) +#' +#' k <- get_eurostat("nama_10_lp_ulc", +#' cache_dir = file.path(tempdir(), "r_cache") +#' ) #' options(eurostat_update = TRUE) #' k <- get_eurostat("nama_10_lp_ulc") #' options(eurostat_update = FALSE) -#' options(eurostat_cache_dir = file.path(tempdir(), "r_cache")) +#' +#' set_eurostat_cache_dir(file.path(tempdir(), "r_cache2")) #' k <- get_eurostat("nama_10_lp_ulc") #' k <- get_eurostat("nama_10_lp_ulc", cache = FALSE) #' k <- get_eurostat("avia_gonc", select_time = "Y", cache = FALSE) -#' -#' dd <- get_eurostat("nama_10_gdp", -#' filters = list(geo = "FI", -#' na_item = "B1GQ", -#' unit = "CLV_I10")) +#' +#' dd <- get_eurostat("nama_10_gdp", +#' filters = list( +#' geo = "FI", +#' na_item = "B1GQ", +#' unit = "CLV_I10" +#' ) +#' ) +#' +#' # A dataset with multiple time series in one +#' dd2 <- get_eurostat("AVIA_GOR_ME", +#' select_time = c("A", "M", "Q"), +#' time_format = "date_last" +#' ) +#' +#' # An example of downloading whole dataset from JSON API +#' dd3 <- get_eurostat("AVIA_GOR_ME", +#' filters = list() +#' ) +#' +#' # Filtering a dataset from a local file +#' dd3_filter <- get_eurostat("AVIA_GOR_ME", +#' filters = list( +#' tra_meas = "FRM_BRD" +#' ) +#' ) +#' #' } -get_eurostat <- function(id, time_format = "date", filters = "none", +#' +#' @importFrom digest digest +#' @importFrom jsonlite toJSON fromJSON +#' @importFrom dplyr filter +#' @importFrom rlang !! sym +#' @export +get_eurostat <- function(id, + time_format = "date", + filters = NULL, type = "code", select_time = NULL, - cache = TRUE, update_cache = FALSE, cache_dir = NULL, + lang = "en", + cache = TRUE, + update_cache = FALSE, + cache_dir = NULL, compress_file = TRUE, - stringsAsFactors = default.stringsAsFactors(), - keepFlags = FALSE, ...){ - #Warning for flags with filter - if (keepFlags & !is.character(filters) && filters != "none") { - warning("keepFlags can be used only without filters. No Flags returned.") - } + stringsAsFactors = FALSE, + keepFlags = FALSE, + use.data.table = FALSE, + ...) { + + # Check if you have access to ec.europe.eu. + # If dataset is cached, access to ec.europe.eu is not needed + # Therefore this is a warning, not a stop + if (!check_access_to_data()) { + # nocov start + warning("You have no access to ec.europe.eu. + Please check your connection and/or review your proxy settings") + # nocov end + } - # No cache for json - if (is.null(filters) || filters != "none") { - cache <- FALSE + # For better code clarity, use only NULL in code + if (is.character(filters) && identical(tolower(filters), "none")) { + filters <- NULL + } else if (is.character(filters) && !identical(tolower(filters), "null")) { + message("Non-standard filters argument. Using argument 'filters = NULL'") + filters <- NULL + } + + # Inform user with message if keepFlags == TRUE cannot be delivered + if (keepFlags && !is.null(filters)) { + message("The keepFlags argument of the get_eurostat function + can be used only without filters. No Flags returned.") + keepFlags <- FALSE } - if (cache){ + # Sanity check + type <- tolower(type) + time_format <- tolower(time_format) + lang <- check_lang(lang) + + if (cache) { + # check option for update update_cache <- update_cache | getOption("eurostat_update", FALSE) # get cache directory - if (is.null(cache_dir)){ - cache_dir <- getOption("eurostat_cache_dir", NULL) - if (is.null(cache_dir)){ - cache_dir <- file.path(tempdir(), "eurostat") - if (!file.exists(cache_dir)) dir.create(cache_dir) + cache_dir <- eur_helper_cachedir(cache_dir) + + cache_list <- file.path( + cache_dir, + paste0( + "cache_list", + ".json" + ) + ) + + # cache file connection + cache_list_conn <- file(cache_list, "a") + + # Sort filters alphabetically #### + # Subsetting with NULL turns list("") (List of 1) to list() (List of 0) + # This needs to be looked into, even if it's useful, it's unexpected + # if structure below prevents subsetting when names(filters) is NULL + if (!is.null(names(filters))) { + filters <- filters[sort(names(filters), decreasing = FALSE)] + } + + # Sort items inside each individual filter to alphabetical order + for (i in seq_along(filters)) { + if (length(filters[i]) > 1) { + filters[i] <- sort(filters[i]) } + } + + # Turn query into lists with predefined order + # Order is defined by the order of arguments in function documentation + query <- list( + list( + id = id, + time_format = time_format, + filters = filters, + type = type, + select_time = select_time, + stringsAsFactors = stringsAsFactors, + keepFlags = keepFlags, + source = ifelse(is.null(filters), "bulk", "json"), + download_date = Sys.Date() + ) + ) + + if (is.null(filters)) { + query_unfiltered <- list( + list( + id = id, + time_format = time_format, + filters = NULL, + type = type, + select_time = select_time, + stringsAsFactors = stringsAsFactors, + keepFlags = keepFlags, + source = "bulk", + download_date = Sys.Date() + ) + ) } else { - if (!file.exists(cache_dir)) { - stop("The folder ", cache_dir, " does not exist") + # This is to make it possible to filter local dataset + # The only way to return a whole dataset from JSON API is to use + # empty list with filters argument + query_unfiltered <- list( + list( + id = id, + time_format = time_format, + filters = list(), + type = type, + select_time = select_time, + stringsAsFactors = stringsAsFactors, + keepFlags = keepFlags, + source = "json", + download_date = Sys.Date() + ) + ) + } + + query_hash <- digest::digest(query, algo = "md5") + query_hash_unfiltered <- digest::digest(query_unfiltered, algo = "md5") + names(query) <- digest::digest(query, algo = "md5") + cache_list_current <- readLines(cache_list) + + if (any(grepl(query_hash, cache_list_current))) { + # Check if the same query has already been made + message("Dataset query already saved in cache_list.json...") + } else if (!any(grepl(query_hash, cache_list_current))) { + # If query was not made, append cache_list with new json query + if (length(cache_list_current) == 0) { + # close previous connection with mode "a" + close(cache_list_conn) + cache_list_conn <- file(cache_list, "w") + + json_query <- jsonlite::toJSON( + query, + pretty = TRUE, + null = "null" + ) + + writeLines(text = json_query, + con = cache_list_conn, + sep = "\n") + + } else if (length(cache_list_current) != 0) { + # read previously saved queries and save them + cache_list_history <- jsonlite::fromJSON(cache_list) + # close previous connection with mode "a" + close(cache_list_conn) + # open a new connection with mode "w" that wipes the file + cache_list_conn <- file(cache_list, "w") + cache_list_history_and_query <- c(cache_list_history, query) + + json_query <- jsonlite::toJSON( + cache_list_history_and_query, + pretty = TRUE, + null = "null" + ) + + writeLines( + text = paste0(json_query), + con = cache_list_conn, + sep = "\n" + ) } } + close(cache_list_conn) + + # If query_hash and query_hash_unfiltered are not identical + # it means that it makes sense to see if a superset of the data exists + data_superset_exists <- FALSE + + # Re-read cache_list file if there were any changes + cache_list_current <- readLines(cache_list) + + if (!identical(query_hash, query_hash_unfiltered) && + any(grepl(query_hash_unfiltered, cache_list_current))) { + message("Dataset query not in cache_list.json but the whole dataset is") + data_superset_exists <- TRUE + } + # cache filename - cache_file <- file.path(cache_dir, - paste0(id, "_", time_format, - "_", type, select_time, "_", - strtrim(stringsAsFactors, 1), - strtrim(keepFlags, 1), - ".rds")) + cache_file <- file.path( + cache_dir, + paste0( + query_hash, + ".rds" + ) + ) + + # bulk cache filename + cache_file_bulk <- file.path( + cache_dir, + paste0( + query_hash_unfiltered, + ".rds" + ) + ) } - # if cache = FALSE or update or new: dowload else read from cache - if (!cache || update_cache || !file.exists(cache_file)){ - - if (is.null(filters) || is.list(filters)){ - # api download - y <- get_eurostat_json(id, filters, type = type, - stringsAsFactors = stringsAsFactors, ...) + # Download always files from server if any of the following is TRUE + # cache = FALSE + # -> no caching, always downloading + # update_cache = TRUE + # -> want to update a cache -> redownload + # suitable cache_file AND cache_file_bulk do not exist + # -> no cache files -> no reading from cache -> download + if (!cache || update_cache || + (!file.exists(cache_file) && !file.exists(cache_file_bulk))) { + if (is.list(filters)) { + # If filters value is some type of a list + # -> Download from Eurostat Web Service (replaces "JSON API") + + y <- get_eurostat_json( + id, + filters, + type, + lang, + stringsAsFactors, + ... + ) y$time <- convert_time_col(factor(y$time), time_format = time_format) - # bulk download - } else if (filters == "none") { - y_raw <- get_eurostat_raw(id) - y <- tidy_eurostat(y_raw, time_format, select_time, - stringsAsFactors = stringsAsFactors, - keepFlags = keepFlags) - if (type == "code") { - y <- y - } else if (type == "label") { - y <- label_eurostat(y) - } else if (type == "both"){ - stop("type = \"both\" can be only used with JSON API. Set filters argument") + } else if (is.null(filters)) { + # If filters value is NULL + # -> Download from SDMX 2.1 REST API (replaces old "Bulk download") + + y <- try(get_eurostat_raw(id, use.data.table = use.data.table), silent = TRUE) + if ("try-error" %in% class(y)) { + stop(paste("get_eurostat_raw fails with the id", id)) + } + + # If download from SDMX 2.1 REST API is successful + # -> tidy the dataset with tidy_eurostat function + + y <- tidy_eurostat( + y, + time_format, + select_time, + stringsAsFactors = stringsAsFactors, + keepFlags = keepFlags, use.data.table = use.data.table + ) + + if (identical(type, "code")) { + # do nothing + # y <- y + } else if (identical(type, "label")) { + y <- label_eurostat(y, lang) + } else if (identical(type, "both")) { + stop(paste("type = \"both\" can be only used with JSON API.", + "Set filters argument")) } else { stop("Invalid type.") } - } - - } else { + } else if (file.exists(cache_file_bulk) && data_superset_exists) { + # Somewhat redundant as data_superset_exists checks cache_list.json + # which lists files downloaded and saved to cache but maybe in some + # situations the cached file could go missing? Not very likely though + + message(paste("Reading cache file", cache_file_bulk, "and filtering it")) + y <- readRDS(cache_file_bulk) + for (i in seq_along(filters)) { + y <- dplyr::filter(y, + !!rlang::sym(names(filters)[i]) == filters[i]) + } + # y <- y_raw + } else if (file.exists(cache_file)) { cf <- path.expand(cache_file) message(paste("Reading cache file", cf)) y <- readRDS(cache_file) message(paste("Table ", id, " read from cache file: ", cf)) } - # if update or new: save - if (cache && (update_cache || !file.exists(cache_file))){ + # if update_cache = TRUE or cache file does not yet exist + # -> save cache file to cache directory + if (cache && (update_cache || !file.exists(cache_file))) { saveRDS(y, file = cache_file, compress = compress_file) message("Table ", id, " cached at ", path.expand(cache_file)) } y +} + +#' @title Get all datasets in a folder +#' @description +#' Loops over all files in a Eurostat database folder, downloads the data and +#' assigns the datasets to environment. +#' @details +#' The datasets are assigned into .EurostatEnv by default, using dataset codes +#' as object names. The datasets are downloaded from SDMX API as TSV files, +#' meaning that they are returned without filtering. No filters can be +#' provided using this function. +#' +#' Please do not attempt to download too many datasets or the whole database +#' at once. The number of datasets that can be downloaded at once is hardcoded +#' to 20. The function also asks the user for confirmation if the number of +#' datasets in a folder is more than 10. This is by design to discourage +#' straining Eurostat API. +#' @param code Folder code from Eurostat Table of Contents. +#' @param env Name of the environment where downloaded datasets are assigned. +#' Default is .EurostatEnv. If NULL, datasets are returned as a list object. +#' +#' @inheritSection eurostat-package Data source: Eurostat Table of Contents +#' @inheritSection eurostat-package Data source: Eurostat SDMX 2.1 Dissemination API +#' +#' @author Pyry Kantanen +#' +#' @inherit set_eurostat_toc seealso +#' +#' @importFrom stringr str_glue +#' @importFrom utils menu +#' +#' +#' @export +get_eurostat_folder <- function(code, env = .EurostatEnv) { + + # Limit after which the function prompts the user whether they really want + # to proceed + soft_limit <- 10 + # Limit that cannot be crossed with this function + hard_limit <- 20 + + toc <- get_eurostat_toc() + if (toc[["type"]][which(toc[["code"]] == code)] != "folder") { + warning("The code you provided is not a folder.") + return(invisible()) + } + children <- toc_list_children(code) + # Filter out potential subfolders + children <- children[which(children$type %in% c("dataset", "table")), ] + + if (nrow(children) == 0) { + warning("The folder code you provided did not have any items.") + return(invisible()) + } + if (nrow(children) > hard_limit) { + warning(stringr::str_glue( + "The number of datasets in folder ({nrow(children)}) is too large. ", + "Please use some other method for retrieving datasets." + )) + return(invisible()) + } + + if (nrow(children) > soft_limit) { + title_msg <- stringr::str_glue( + "The number of items in the folder is more than {soft_limit}. ", + "Do you wish to proceed?") + switch(menu(c("Yes", "No"), title = title_msg) + 1, + cat("Nothing done\n"), + message("Proceeding to download datasets in folder..."), + return(invisible())) + } + + if (!is.null(env)) { + for (i in seq_len(nrow(children))) { + dataset <- get_eurostat(children$code[i], cache = TRUE) + assign(children$code[i], dataset, envir = env) + message( + stringr::str_glue( + "Dataset {i} / {nrow(children)} assigned to environment\n\n") + ) + } + return(invisible()) + } else { + list_of_datasets <- list() + for (i in seq_len(nrow(children))) { + dataset <- get_eurostat(children$code[i], cache = TRUE) + list_of_datasets[[i]] <- dataset + # names(list_of_datasets[i]) <- children$code[i] + message( + stringr::str_glue( + "Dataset {i} / {nrow(children)} assigned to a list\n\n") + ) + } + names(list_of_datasets) <- children[["code"]] + return(list_of_datasets) + } +} + +#' @title Get Eurostat data interactive +#' @description +#' A simple interactive helper function to go through the steps of downloading +#' and/or finding suitable eurostat datasets. +#' +#' @details +#' This function is intended to enable easy exploration of different eurostat +#' package functionalities and functions. In order to not drown the end user +#' in endless menus this function does not allow for setting +#' all possible [get_eurostat()] function arguments. It is possible to set +#' `time_format`, `type`, `lang`, `stringsAsFactors`, `keepFlags`, and +#' `use.data.table` in the interactive menus. +#' +#' In some datasets setting these parameters may result in a +#' "Error in label_eurostat" error, for example: +#' "labels for XXXXXX includes duplicated labels in the Eurostat dictionary". +#' In these cases, and with other more complex queries, please +#' use [get_eurostat()] function directly. +#' +#' @param code +#' A unique identifier / code for the dataset of interest. If code is not +#' known [search_eurostat()] function can be used to search Eurostat table +#' of contents. +#' +#' @seealso [get_eurostat()] +#' @importFrom stringr str_glue +#' @importFrom utils capture.output +#' @export +get_eurostat_interactive <- function(code = NULL) { + # Interactive function, not feasible to test + # nocov start + lang_selection <- switch( + menu(c("English", "French", "German"), title = "Select language") + 1, + return(invisible()), + "en", + "fr", + "de" + ) + + if (is.null(code)) { + + search_term <- readline(prompt = "Enter search term for data: ") + results <- search_eurostat(pattern = search_term, lang = lang_selection) + code_and_title <- paste0("[", results$code, "] ", results$title) + if (nrow(results) > 0) { + choice <- menu(choices = code_and_title, title = "Which dataset would you like to download?") + if (choice == 0) { + # message("Nothing done\n") + return(invisible()) + } + } else { + stop(paste("No data found with given search term:", search_term)) + } + code <- results$code[choice] + } + + download_selection <- switch( + menu(choices = c("Yes", "No"), + title = "Download the dataset?") + 1, + return(invisible()), + TRUE, + FALSE + ) + # Set manual_selection to FALSE here to make it possible to print code + # for downloading dataset later + manual_selection <- FALSE + + if (download_selection) { + manual_selection <- switch( + menu(choices = c("Default", "Manually selected"), + title = "Would you like to use default download arguments or set them manually?") + 1, + return(invisible()), + FALSE, + TRUE + ) + + if (manual_selection) { + time_format_selection <- switch( + menu(choices = c("Convert to date, first day of the period (2000-04-01) (default)", + "Convert to date, last day of the period (2000-06-30)", + "Convert to numeric (2000.25)", + "Use raw data (2000-Q2)")) + 1, + "date", + "date", + "date_last", + "num", + "raw" + ) + + type_selection <- switch( + menu(choices = c("Return categorical variables as short codes (default)", + "Return categorical variables in labeled (long) format"), + title = "Note: The option 'both' is supported only when using the JSON API.") + 1, + "code", + "code", + "label" + ) + + stringsAsFactors_selection <- switch( + menu(choices = c("Return categorical data as characters (default)", + "Convert categorical data into factors"), + title = "Converting text data into factors may help reduce time used in data processing, reduce RAM usage and cache file size") + 1, + FALSE, + FALSE, + TRUE + ) + + keepFlags_selection <- switch( + menu(choices = c("Do not return flags, just remove them (default)", + "Return flags in separate column")) + 1, + FALSE, + FALSE, + TRUE + ) + + use.data.table_selection <- switch( + menu(choices = c("Do not use data.table functions (default", + "Use data.table functions"), + title = "Using data.table functions may help reduce time used in data processing and reduce RAM usage. It is advisable especially when dealing with large datasets.") + 1, + FALSE, + FALSE, + TRUE + ) + eurostat_data <- tryCatch({ + get_eurostat(id = code, + time_format = time_format_selection, + type = type_selection, + lang = lang_selection, + stringsAsFactors = stringsAsFactors_selection, + keepFlags = keepFlags_selection, + use.data.table = use.data.table_selection) + }, error=function(error_message) { + message("\nEncountered the following error message while attempting to modify the downloaded data:\n") + message(error_message) + message("\nUsing default options for downloading data...\n") + # Use scoping assignment here to influence code print below + time_format_selection <<- "date" + type_selection <<- "code" + lang_selection <<- lang_selection + stringsAsFactors_selection <<- FALSE + keepFlags_selection <<- FALSE + use.data.table_selection <<- FALSE + get_eurostat(id = code, + time_format = time_format_selection, + type = type_selection, + lang = lang_selection, + stringsAsFactors = stringsAsFactors_selection, + keepFlags = keepFlags_selection, + use.data.table = use.data.table_selection) + }) + } else if (!manual_selection) { + eurostat_data <- get_eurostat(id = code) + } + } + + tempfile_for_sinking <- tempfile() + + # eurostat_data <- get_eurostat(id = code) + print_citation <- switch( + menu(choices = c("Yes", "No"), + title = "Print dataset citation?") + 1, + return(invisible()), + TRUE, + FALSE + ) + + if (print_citation) { + citation <- get_bibentry(code, lang = lang_selection) + capture.output(cat("##### DATASET CITATION:\n\n"), file = tempfile_for_sinking, append = TRUE) + capture.output(print(citation), file = tempfile_for_sinking, append = TRUE) + capture.output(cat("\n"), file = tempfile_for_sinking, append = TRUE) + } + + print_code <- switch( + menu(choices = c("Yes", "No"), + title = "Print code for downloading dataset?") + 1, + return(invisible()), + TRUE, + FALSE + ) + + if (print_code == TRUE && manual_selection == TRUE) { + capture.output(cat("##### DOWNLOAD PARAMETERS:\n\n")) + capture.output(print(stringr::str_glue(paste0("get_eurostat(id = '{code}', time_format = '{time_format_selection}', ", + "type = '{type_selection}', lang = '{lang_selection}', ", + "stringsAsFactors = {stringsAsFactors_selection}, ", + "keepFlags = {keepFlags_selection}, ", + "use.data.table = {use.data.table_selection})"))), file = tempfile_for_sinking, append = TRUE) + capture.output(cat("\n")) + } else if (print_code == TRUE && manual_selection == FALSE) { + capture.output(cat("##### DOWNLOAD PARAMETERS:\n\n"), file = tempfile_for_sinking, append = TRUE) + capture.output(print(stringr::str_glue("get_eurostat(id = '{code}')")), file = tempfile_for_sinking, append = TRUE) + capture.output(cat("\n"), file = tempfile_for_sinking, append = TRUE) + } + + if (exists("eurostat_data")) { + print_code <- switch( + menu(choices = c("Yes", "No"), + title = "Print dataset fixity checksum?") + 1, + return(invisible()), + TRUE, + FALSE + ) + + if (print_code) { + capture.output(cat("##### FIXITY CHECKSUM:\n\n"), file = tempfile_for_sinking, append = TRUE) + capture.output(print(stringr::str_glue("Fixity checksum (md5) for dataset {code}: {eurostat:::fixity_checksum(eurostat_data, algorithm = 'md5')}")), file = tempfile_for_sinking, append = TRUE) + capture.output(cat("\n"), file = tempfile_for_sinking, append = TRUE) + } + } + + if (exists("eurostat_data")) { + cat(readLines(tempfile_for_sinking), sep = "\n") + return(eurostat_data) + } else { + cat(readLines(tempfile_for_sinking), sep = "\n") + return(invisible()) + } + # nocov end } diff --git a/R/get_eurostat_dic.R b/R/get_eurostat_dic.R index dded4a47..b4236869 100755 --- a/R/get_eurostat_dic.R +++ b/R/get_eurostat_dic.R @@ -1,35 +1,58 @@ #' @title Download Eurostat Dictionary #' @description Download a Eurostat dictionary. -#' @details For given coded variable from Eurostat \url{ec.europa.eu/eurostat}. -#' The dictionaries link codes with human-readable labels. -#' To translate codes to labels, use \code{\link{label_eurostat}}. +#' @details For given coded variable from Eurostat +#' . The dictionaries link codes with +#' human-readable labels. To translate codes to labels, use +#' [label_eurostat()]. #' @param dictname A character, dictionary for the variable to be downloaded. -#' @param lang A character, language code. Options: "en" (default) / "fr" / "de". +#' @param lang A character, language code. Options: "en" (default), "fr", "de". #' @return tibble with two columns: code names and full names. #' @export -#' @seealso \code{\link{label_eurostat}}, \code{\link{get_eurostat}}, -#' \code{\link{search_eurostat}}. -#' @references See citation("eurostat"). -#' @author Przemyslaw Biecek and Leo Lahti \email{leo.lahti@@iki.fi}. Thanks to Wietse Dol for contributions. -#' @examples \dontrun{ -#' tmp <- get_eurostat_dic("crop_pro") -#' head(tmp) -#' tmp <- get_eurostat_dic("crop_pro", lang = "fr") -#' } +#' @seealso [label_eurostat()], [get_eurostat()], +#' [search_eurostat()]. +#' @references +#' See `citation("eurostat")`: +#' +#' ```{r, echo=FALSE, comment="#" } +#' citation("eurostat") +#' ``` +#' +#' @author Przemyslaw Biecek and Leo Lahti . Thanks to +#' Wietse Dol for contributions. Updated by Pyry Kantanen to support XML +#' codelists. +#' @examplesIf check_access_to_data() +#' \donttest{ +#' get_eurostat_dic("crop_pro") +#' +#' # Try another language +#' get_eurostat_dic("crop_pro", lang = "fr") +#' } +#' +#' @importFrom readr read_tsv cols col_character +#' #' @keywords utilities database get_eurostat_dic <- function(dictname, lang = "en") { + + lang <- check_lang(lang) + dictlang <- paste0(dictname, "_", lang) if (!exists(dictlang, envir = .EurostatEnv)) { url <- getOption("eurostat_url") - tname <- paste0(url, - "estat-navtree-portlet-prod/BulkDownloadListing?file=dic%2F", lang, "%2F", - dictname, ".dic") - dict <- readr::read_tsv(url(tname), col_names = c("code_name", "full_name"), - col_types = readr::cols(.default = readr::col_character())) - dict$full_name <- gsub(pattern="\u0092", replacement="'", dict$full_name) + tname <- paste0( + url, + "api/dissemination/sdmx/2.1/codelist/ESTAT/", dictname, + "?format=TSV&lang=", lang + ) + dict <- readr::read_tsv(url(tname), + col_names = c("code_name", "full_name"), + col_types = readr::cols(.default = readr::col_character()) + ) + dict$full_name <- gsub( + pattern = "\u0092", replacement = "'", + dict$full_name + ) assign(dictlang, dict, envir = .EurostatEnv) } get(dictlang, envir = .EurostatEnv) } - diff --git a/R/get_eurostat_geospatial.R b/R/get_eurostat_geospatial.R index 5f309a0a..6f7525c6 100755 --- a/R/get_eurostat_geospatial.R +++ b/R/get_eurostat_geospatial.R @@ -1,229 +1,285 @@ -#' @title Download Geospatial Data from GISGO -#' @description Downloads either a simple features (sf), SpatialPolygonDataFrame or a data_frame preprocessed using -#' \code{broom::tidy()}. -#' @param output_class A string. Class of object returned, -#' either \code{sf} \code{simple features}, \code{df} (\code{data_frame}) or -#' \code{spdf} (\code{SpatialPolygonDataFrame}) +#' @title Download Geospatial Data from GISCO +#' +#' @description Downloads either a simple features (sf) or a data_frame +#' of NUTS regions. This function is a wrapper of [giscoR::gisco_get_nuts()]. +#' This function requires to have installed the packages \CRANpkg{sf} and +#' \CRANpkg{giscoR}. +#' +#' @seealso [giscoR::gisco_get_nuts()] +#' @param output_class Class of object returned, +#' either `sf` `simple features` or `df` (`data_frame`). `spdf` output has +#' been soft-deprecated, the function would switch to `sf`. #' @param resolution Resolution of the geospatial data. One of -#' "60" (1:60million), "20" (1:20million), "10" (1:10million), "03" (1:3million) or "01" (1:1million). +#' * "60" (1:60million), +#' * "20" (1:20million) +#' * "10" (1:10million) +#' * "03" (1:3million) or +#' * "01" (1:1million). #' @param nuts_level Level of NUTS classification of the geospatial data. One of #' "0", "1", "2", "3" or "all" (mimics the original behaviour) #' @param year NUTS release year. One of -#' "2003", "2006", "2010", "2013" or "2016" -#' @param cache a logical whether to do caching. Default is \code{TRUE}. Affects -#' only queries from the bulk download facility. -#' @param update_cache a locigal whether to update cache. Can be set also with -#' options(eurostat_update = TRUE) -#' @param cache_dir a path to a cache directory. The directory have to exist. -#' The \code{NULL} (default) uses and creates -#' 'eurostat' directory in the temporary directory from -#' \code{\link{tempdir}}. Directory can also be set with -#' \code{option} eurostat_cache_dir. -#' @export -#' @details The data source URL is \url{http://ec.europa.eu/eurostat/web/gisco/geodata/reference-data/administrative-units-statistical-units}. -#' @author Markus Kainu -#' @return a sf, data_frame or SpatialPolygonDataFrame. +#' "2003", "2006", "2010", "2013", "2016" or "2021" +#' @param cache a logical whether to do caching. Default is `TRUE`. +#' @param update_cache a logical whether to update cache. Can be set also with +#' `options(eurostat_update = TRUE)` +#' @param cache_dir a path to a cache directory. See +#' [set_eurostat_cache_dir()]. If `NULL` and the cache dir has not been set +#' globally the file would be stored in the [tempdir()]. +#' @param crs projection of the map: 4-digit +#' [EPSG code](https://spatialreference.org/ref/epsg/). One of: +#' * "4326" - WGS84 +#' * "3035" - ETRS89 / ETRS-LAEA +#' * "3857" - Pseudo-Mercator +#' +#' @param make_valid Deprecated +#' +#' @inheritDotParams giscoR::gisco_get_nuts -epsg +#' +#' @details +#' The objects downloaded from GISCO should contain all or some of the +#' following variable columns: +#' * **id**: JSON id code, the same as **NUTS_ID**. See **NUTS_ID** below for +#' further clarification. +#' * **LEVL_CODE**: NUTS level code: 0 (national level), 1 (major +#' socio-economic regions), 2 (basic regions for the application of regional +#' policies) or 3 (small regions). +#' * **NUTS_ID**: NUTS ID code, consisting of country code and numbers (1 for +#' NUTS 1, 2 for NUTS 2 and 3 for NUTS 3) +#' * **CNTR_CODE**: Country code: two-letter ISO code (ISO 3166 alpha-2), except +#' in the case of Greece (EL). +#' * **NAME_LATN**: NUTS name in local language, transliterated to Latin script +#' * **NUTS_NAME**: NUTS name in local language, in local script. +#' * **MOUNT_TYPE**: Mountain typology for NUTS 3 regions. +#' * 1: "where more than 50 % of the surface is covered by topographic +#' mountain areas" +#' * 2: "in which more than 50 % of the regional population lives in +#' topographic mountain areas" +#' * 3: "where more than 50 % of the surface is covered by topographic +#' mountain areas and where more than 50 % of the regional population lives +#' in these mountain areas" +#' * 4: non-mountain region / other region +#' * 0: no classification provided (e.g. in the case of NUTS 1 and NUTS 2 and +#' non-EU countries) +#' * **URBN_TYPE**: Urban-rural typology for NUTS 3 regions. +#' * 1: predominantly urban region +#' * 2: intermediate region +#' * 3: predominantly rural region +#' * 0: no classification provided (e.g. in the case of NUTS 1 and NUTS 2 +#' regions) +#' * **COAST_TYPE**: Coastal typology for NUTS 3 regions. +#' * 1: coastal (on coast) +#' * 2: coastal (>= 50% of population living within 50km of the coastline) +#' * 3: non-coastal region +#' * 0: no classification provided (e.g. in the case of NUTS 1 and NUTS 2 +#' regions) +#' * **FID**: Same as NUTS_ID. +#' * **geo**: Same as NUTS_ID, added for for easier joins with dplyr. Consider +#' the status of this column "questioning" and use other columns for joins +#' when possible. +#' * **geometry**: geospatial information. +#' +#' @author +#' Markus Kainu , Diego Hernangomez +#' +#' @return a sf or data_frame +#' +#' @source +#' Data source: Eurostat +#' +#' © EuroGeographics for the administrative boundaries +#' +#' Data downloaded using \pkg{giscoR} +#' +#' @inheritSection eurostat-package Eurostat: Copyright notice and free re-use of data +#' @inheritSection eurostat-package Data source: GISCO - General Copyright +#' @inheritSection eurostat-package Data source: GISCO - Administrative Units / Statistical Units +#' +#' @family geospatial #' @examples -#' \dontrun{ -#' lp <- get_eurostat_geospatial(output_class = "sf", resolution = "60", nuts_level = "all") -#' lp %>% select(NUTS_ID) %>% plot() -#' lp <- get_eurostat_geospatial(output_class = "spdf", resolution = "60", nuts_level = "all") -#' spplot(lp, "STAT_LEVL_") -#' # or -#' lp <- get_eurostat_geospatial(output_class = "df", resolution = "60", nuts_level = "all") -#' ggplot(lp, aes(x=long,y=lat,group=group,fill=STAT_LEVL_),color="white") + geom_polygon() -#' } -#' -get_eurostat_geospatial <- function(output_class="sf",resolution="60", nuts_level = "all", year = "2016", - cache = TRUE, update_cache = FALSE, cache_dir = NULL){ - - eurostat_geodata_60_2016 <- NULL - LEVL_CODE <- NULL - # output_class <- NULL - - data("eurostat_geodata_60_2016", envir = environment(), package = "eurostat") - - # Check resolution is of correct format - resolution <- as.character(resolution) - resolution <- gsub("^0+", "", resolution) - if (!as.numeric(resolution) %in% c(1, 3, 10, 20, 60)) { - stop("Resolution should be one of 01, 1, 03, 3, 10, 20, 60") +#' \donttest{ +#' # Uses cached dataset +#' sf <- get_eurostat_geospatial( +#' output_class = "sf", +#' resolution = "60", +#' nuts_level = "all" +#' ) +#' # Downloads dataset from server +#' sf2 <- get_eurostat_geospatial( +#' output_class = "sf", +#' resolution = "20", +#' nuts_level = "all" +#' ) +#' df <- get_eurostat_geospatial( +#' output_class = "df", +#' nuts_level = "0" +#' ) +#' } +#' +#' @export +get_eurostat_geospatial <- function(output_class = "sf", + resolution = "60", + nuts_level = "all", year = "2016", + cache = TRUE, update_cache = FALSE, + cache_dir = NULL, crs = "4326", + make_valid = "DEPRECATED", ...) { + # nocov start + if (!requireNamespace("sf")) { + message("'sf' package is required for geospatial functionalities") + return(invisible()) } - resolution <- gsub("^1$", "01", resolution) - resolution <- gsub("^3$", "03", resolution) - - # Check year is of correct format - year <- as.character(year) - if (!as.numeric(year) %in% c(2003, 2006, 2010, 2013, 2016)) { - stop("Year should be one of 2003, 2006, 2010, 2013 or 2016") + # nocov end + # Simplified and leaving most of the heavy-lifting to giscoR + + # Deprecation messages + stopifnot(length(output_class) == 1L) + if (output_class == "spdf") { + message("'spdf' output deprecated. Switching to sf output") + output_class <- "sf" } - - if (as.numeric(year) == 2003 & as.numeric(resolution) == 60) { - stop("NUTS 2003 is not provided at 1:60 million resolution. Try 1:1 million, 1:3 million, 1:10 million or 1:20 million") + + if (!identical(make_valid, "DEPRECATED")) { + message("'make_valid' argument has been deprecated") } - message(" -COPYRIGHT NOTICE - -When data downloaded from this page - -is used in any printed or electronic publication, -in addition to any other provisions -applicable to the whole Eurostat website, -data source will have to be acknowledged -in the legend of the map and -in the introductory page of the publication -with the following copyright notice: - -- EN: (C) EuroGeographics for the administrative boundaries -- FR: (C) EuroGeographics pour les limites administratives -- DE: (C) EuroGeographics bezuglich der Verwaltungsgrenzen - -For publications in languages other than -English, French or German, -the translation of the copyright notice -in the language of the publication shall be used. - -If you intend to use the data commercially, -please contact EuroGeographics for -information regarding their licence agreements. - ") - - if (resolution == "60" & year == 2016){ - - if (nuts_level %in% c("all")){ - shp <- eurostat_geodata_60_2016 - } - if (nuts_level == "0") shp <- filter(eurostat_geodata_60_2016, LEVL_CODE == 0) - if (nuts_level == "1") shp <- filter(eurostat_geodata_60_2016, LEVL_CODE == 1) - if (nuts_level == "2") shp <- filter(eurostat_geodata_60_2016, LEVL_CODE == 2) - if (nuts_level == "3") shp <- filter(eurostat_geodata_60_2016, LEVL_CODE == 3) - - if (output_class == "df"){ - nuts_sp <- as(shp, "Spatial") - nuts_sp$id <- row.names(nuts_sp) - nuts_ff <- broom::tidy(nuts_sp) - shp <- left_join(nuts_ff,nuts_sp@data) - } - if (output_class == "spdf"){ - shp <- as(shp, "Spatial") + # Leaving only specific validations - rest of call would be handled by giscoR + output_class <- match.arg(as.character(output_class), c("sf", "df")) + + # Sanity check for nuts_level + stopifnot(length(nuts_level) == 1L) + nuts_level <- regmatches(nuts_level, regexpr("^(all|[0-9]+)", nuts_level)) + nuts_level <- match.arg(nuts_level, c("all", 0:3)) + + # Performance - If df requested resolution and crs are meaningless. Switching + # to 60 and 4326 for speed (except for 2003, no available) + if (output_class == "df") { + resolution <- "60" + crs <- "4326" + + if (as.integer(year) == 2003) resolution <- "20" + } + + + # If cache file requested get the info from the internal dataset + capture_dots <- list(...) + + # Check if the pre-set call to the function has been modified on + # relevant parameters + use_local <- all( + as.character(resolution) == "60", + as.character(year) == "2016", + isFALSE(update_cache), + as.character(crs) == "4326", + # Check dots are empty + length(capture_dots) == 0 + ) + + if (use_local) { + # Not modified - using dataset included with eurostat package + message("Extracting data from eurostat::eurostat_geodata_60_2016") + shp <- eurostat::eurostat_geodata_60_2016 + if (nuts_level != "all") { + shp <- shp[shp$LEVL_CODE == nuts_level, ] } - } else { + # Check if package "giscoR" is installed + # nocov start + if (!requireNamespace("giscoR")) { + message("'giscoR' package is required for geospatial functionalities") + return(invisible()) + } + # nocov end + + message(paste0( + "Extracting data using giscoR package, please report issues", + " on https://github.com/rOpenGov/giscoR/issues" + )) - # if (resolution != "60"){ - # if (resolution != "60" & year != 2013){ - - if (cache){ - # check option for update - update_cache <- update_cache | getOption("eurostat_update", FALSE) - - # get cache directory - if (is.null(cache_dir)){ - cache_dir <- getOption("eurostat_cache_dir", NULL) - if (is.null(cache_dir)){ - cache_dir <- file.path(tempdir(), "eurostat") - if (!file.exists(cache_dir)) dir.create(cache_dir) - } + # Manage cache: Priority is eurostat cache (if set) + # If not make use of giscoR default options + detect_eurostat_cache <- eur_helper_detect_cache_dir() + if (!is.null(cache_dir)) { + # Already set by the user, no need message + cache_dir <- eur_helper_cachedir(cache_dir) + } else if (identical( + detect_eurostat_cache, + file.path(tempdir(), "eurostat") + )) { + # eurostat not set, using default giscoR cache management + message("Cache management as per giscoR. see 'giscoR::gisco_get_nuts()'") } else { - if (!file.exists(cache_dir)) { - stop("The folder ", cache_dir, " does not exist") - } + cache_dir <- eur_helper_cachedir(cache_dir) } - - # cache filename - cache_file <- file.path(cache_dir, - paste0( - output_class, resolution, nuts_level, year, ".RData") + + # giscoR call with parameters + # on input errors giscoR would show warnings, etc + shp <- giscoR::gisco_get_nuts( + resolution = resolution, + nuts_level = nuts_level, year = year, + cache = cache, update_cache = update_cache, + cache_dir = cache_dir, epsg = crs, + ... ) } - - # if cache = FALSE or update or new: dowload else read from cache - if (!cache || update_cache || !file.exists(cache_file)){ - - - if (nuts_level %in% c("0","all")){ - resp <- GET(paste0("http://ec.europa.eu/eurostat/cache/GISCO/distribution/v2/nuts/geojson/NUTS_RG_",resolution,"M_",year,"_4258_LEVL_0.geojson")) - nuts0 <- st_read(content(resp, as="text"), stringsAsFactors = FALSE, quiet = TRUE) - } - if (nuts_level %in% c("1","all")){ - resp <- GET(paste0("http://ec.europa.eu/eurostat/cache/GISCO/distribution/v2/nuts/geojson/NUTS_RG_",resolution,"M_",year,"_4258_LEVL_1.geojson")) - nuts1 <- st_read(content(resp, as="text"), stringsAsFactors = FALSE, quiet = TRUE) - } - if (nuts_level %in% c("2","all")){ - resp <- GET(paste0("http://ec.europa.eu/eurostat/cache/GISCO/distribution/v2/nuts/geojson/NUTS_RG_",resolution,"M_",year,"_4258_LEVL_2.geojson")) - nuts2 <- st_read(content(resp, as="text"), stringsAsFactors = FALSE, quiet = TRUE) - } - if (nuts_level %in% c("3","all")){ - resp <- GET(paste0("http://ec.europa.eu/eurostat/cache/GISCO/distribution/v2/nuts/geojson/NUTS_RG_",resolution,"M_",year,"_4258_LEVL_3.geojson")) - nuts3 <- st_read(content(resp, as="text"), stringsAsFactors = FALSE, quiet = TRUE) - } - if (nuts_level %in% c("all")){ - shp <- rbind(nuts0,nuts1,nuts2,nuts3) - } - if (nuts_level == "0") shp <- nuts0 - if (nuts_level == "1") shp <- nuts1 - if (nuts_level == "2") shp <- nuts2 - if (nuts_level == "3") shp <- nuts3 - - - if (output_class == "df"){ - nuts_sp <- as(shp, "Spatial") - nuts_sp$id <- row.names(nuts_sp) - nuts_ff <- broom::tidy(nuts_sp) - shp <- left_join(nuts_ff,nuts_sp@data) - } - if (output_class == "spdf"){ - shp <- as(shp, "Spatial") - } - - } - } - if (resolution != "60" & year != 2016){ - if (cache & file.exists(cache_file)) { - cf <- path.expand(cache_file) - message(paste("Reading cache file", cf)) - # y <- readRDS(cache_file) - load(file = cache_file) - if (output_class == "sf") message(paste("sf at resolution 1:", resolution, " from year ",year," read from cache file: ", cf)) - if (output_class == "df") message(paste("data_frame at resolution 1:", resolution, " from year ",year," read from cache file: ", cf)) - if (output_class == "spdf") message(paste("SpatialPolygonDataFrame at resolution 1:", resolution, " from year ",year," read from cache file: ", cf)) - } - - # if update or new: save - if (cache && (update_cache || !file.exists(cache_file))){ - save(shp, file = cache_file) - if (output_class == "sf") message(paste("sf at resolution 1:", resolution, " cached at: ", path.expand(cache_file))) - if (output_class == "df") message(paste("data_frame at resolution 1:", resolution, " cached at: ", path.expand(cache_file))) - if (output_class == "spdf") message(paste("SpatialPolygonDataFrame at resolution 1:", resolution, " cached at: ", path.expand(cache_file))) - } + # Just to capture potential NULL outputs from giscoR - this can happen + # on some errors + if (is.null(shp)) { + return(NULL) } - - if (resolution == "60" & year == 2016){ - if (output_class == "sf") message(paste("sf at resolution 1:60 read from local file")) - if (output_class == "df") message(paste("data_frame at resolution 1:60 read from local file")) - if (output_class == "spdf") message(paste("SpatialPolygonDataFrame at resolution 1:60 read from local file")) - + + # Post-data treatments + # Manage col names + shp <- geo_names(shp) + + # to df + if (output_class == "df") { + # Remove geometry + shp <- sf::st_drop_geometry(shp) } - - message(" -# -------------------------- -HEADS UP!! - -Function now returns the data in 'sf'-class (simple features) -by default which is different -from previous behaviour's 'SpatialPolygonDataFrame'. - -If you prefer either 'SpatialPolygonDataFrame' or -fortified 'data_frame' (for ggplot2::geom_polygon), -please specify it explicitly to 'output_class'-argument! - -# -------------------------- - ") - - # Adding a `geo` column for easier joins with dplyr - shp$geo <- shp$NUTS_ID + return(shp) +} + + +# Helper function, add names and reorder +geo_names <- function(x) { + # Case for border (BN), there are no NUTS_ID , do nothing + if (!"NUTS_ID" %in% names(x)) { + return(x) + } + + + # Add `id` and `geo` column for easier joins with dplyr + x$geo <- x$NUTS_ID + x$id <- x$geo + + # Arrange names in proper order + the_geom <- sf::st_geometry(x) + the_df <- sf::st_drop_geometry(x) + rest <- c( + "id", "LEVL_CODE", "NUTS_ID", "CNTR_CODE", "NAME_LATN", "NUTS_NAME", + "MOUNT_TYPE", "URBN_TYPE", "COAST_TYPE", "FID", "geo" + ) + + # Check what needed columns are not present in the source file + miss_cols <- setdiff(unique(rest), names(the_df)) + extra_cols <- setdiff(names(the_df), rest) + + + # Add missing cols with NAs + list_df <- lapply(miss_cols, function(x) { + template_df <- data.frame(somecol = NA) + names(template_df) <- x + template_df + }) + new_df <- dplyr::bind_cols(c(list(the_df), list_df)) + + # Final column order + order_cols <- unique(c(rest, extra_cols)) + xend <- new_df[, order_cols] + + # Back to sf + final_sf <- sf::st_sf(xend, geometry = the_geom) + final_sf } diff --git a/R/get_eurostat_json.R b/R/get_eurostat_json.R index eb76ca34..3549e327 100755 --- a/R/get_eurostat_json.R +++ b/R/get_eurostat_json.R @@ -1,120 +1,337 @@ #' @title Get Data from Eurostat API in JSON #' @description Retrieve data from Eurostat API in JSON format. -#' @details +#' @details #' Data to retrieve from -#' \href{http://ec.europa.eu/eurostat/web/json-and-unicode-web-services}{The -#' Eurostat Web Services} can be specified with filters. Normally, it is -#' better to use JSON query through \code{\link{get_eurostat}}, than to use -#' \code{\link{get_eurostat_json}} directly. -#' +#' [The Eurostat Web Services](https://ec.europa.eu/eurostat/web/main/data/web-services) +#' can be specified with filters. Normally, it is +#' better to use JSON query through [get_eurostat()], than to use +#' [get_eurostat_json()] directly. +#' #' Queries are limited to 50 sub-indicators at a time. A time can be #' filtered with fixed "time" filter or with "sinceTimePeriod" and -#' "lastTimePeriod" filters. A \code{sinceTimePeriod = 2000} returns -#' observations from 2000 to a last available. A \code{lastTimePeriod = 10} -#' returns a 10 last observations. -#' -#' To use a proxy to connect, a \code{\link[httr]{use_proxy}} can be -#' passed to \code{\link[httr]{GET}}. For example -#' \code{get_eurostat_json(id, filters, -#' config = httr::use_proxy(url, port, username, password))}. -#' -#' @param id A code name for the dataset of interested. See the table of -#' contents of eurostat datasets for more details. -#' @param filters A named list of filters. Names of list objects are Eurostat -#' variable codes and values are vectors of observation codes. If \code{NULL} -#' (default) the whole dataset is returned. See details for more on filters -#' and limitations per query. -#' @param lang A language used for metadata (en/fr/de). -#' @param type A type of variables, "code" (default), "label" or "both". The -#' "both" will return a data_frame with named vectors, labels as values and -#' codes as names. -#' @param stringsAsFactors if \code{TRUE} (the default) variables are converted -#' to factors in original Eurostat order. If \code{FALSE} they are returned as -#' a character. -#' @param ... Other arguments passed on to \code{\link[httr]{GET}}. For example -#' a proxy parameters, see details. -#' . +#' "lastTimePeriod" filters. A `sinceTimePeriod = 2000` returns +#' observations from 2000 to a last available. A `lastTimePeriod = 10` +#' returns a 10 last observations. See "Filtering datasets" section below +#' for more detailed information about filters. #' -#' @return A dataset as a data_frame. -#' @export -#' @author Przemyslaw Biecek, Leo Lahti, Janne Huovari and Markus Kainu -#' \email{ropengov-forum@@googlegroups.com} -#' \url{http://github.com/ropengov/eurostat} +#' To use a proxy to connect, proxy arguments can be +#' passed to [httr2::req_perform()] via [httr2::req_proxy()] - see latter +#' function documentation for parameter names that can be passed with `...`. +#' A non-functional example: +#' `get_eurostat_json(id, filters, proxy = TRUE, url = "127.0.0.1", port = 80)`. +#' +#' When retrieving data from Eurostat JSON API the user may encounter errors. +#' For end user convenience, we have provided a ready-made internal dataset +#' `sdmx_http_errors` that contains descriptive labels and descriptions about +#' the possible interpretation or cause of each error. These messages are +#' returned if the API returns a status indicating a HTTP error +#' (400 or greater). +#' +#' The Eurostat implementation seems to be based on SDMX 2.1, which is the +#' reason we've used SDMX Standards guidelines as a supplementary source +#' that we have included in the dataset. What this means in practice is that +#' the dataset contains error codes and their mappings that are not mentioned +#' in the Eurostat website. We hope you never encounter them. +#' +#' @param proxy Use proxy, TRUE or FALSE (default). +#' @inheritParams get_eurostat +#' @inheritDotParams httr2::req_proxy +#' @inherit get_eurostat references +#' +#' @return A dataset as an object of `data.frame` class. +#' @author +#' Przemyslaw Biecek, Leo Lahti, Janne Huovari Markus Kainu and Pyry Kantanen + #' @examples -#' \dontrun{ -#' tmp <- get_eurostat_json("cdh_e_fos") -#' yy <- get_eurostat_json(id = "nama_gdp_c", filters = list(geo=c("EU28", "FI"), -#' unit="EUR_HAB", -#' indic_na="B1GM")) +#' \dontrun{ +#' # Generally speaking these queries would be done through get_eurostat +#' tmp <- get_eurostat_json("nama_10_gdp") +#' yy <- get_eurostat_json("nama_10_gdp", filters = list( +#' geo = c("FI", "SE", "EU28"), +#' time = c(2015:2023), +#' lang = "FR", +#' na_item = "B1GQ", +#' unit = "CLV_I10" +#' )) +#' +#' # TIME_PERIOD filter works also with the new JSON API +#' yy2 <- get_eurostat_json("nama_10_gdp", filters = list( +#' geo = c("FI", "SE", "EU28"), +#' TIME_PERIOD = c(2015:2023), +#' lang = "FR", +#' na_item = "B1GQ", +#' unit = "CLV_I10" +#' )) +#' +#' # An example from get_eurostat +#' dd <- get_eurostat("nama_10_gdp", +#' filters = list( +#' geo = "FI", +#' na_item = "B1GQ", +#' unit = "CLV_I10" +#' )) #' } +#' @importFrom httr2 request req_user_agent req_retry req_perform req_proxy +#' @importFrom httr2 resp_body_json resp_content_type resp_is_error req_error +#' @importFrom jsonlite fromJSON +#' @importFrom tibble as_tibble +#' @importFrom stringr str_glue +#' @importFrom httr2 %>% +#' +#' @inheritSection eurostat-package Data source: Eurostat API Statistics (JSON API) +#' @inheritSection eurostat-package Filtering datasets +#' @inheritSection eurostat-package Eurostat: Copyright notice and free re-use of data +#' @inheritSection eurostat-package Citing Eurostat data +#' @inheritSection eurostat-package Disclaimer: Availability of filtering functionalities +#' +#' @seealso +#' [httr2::req_proxy()] +#' #' @keywords utilities database -get_eurostat_json <- function(id, filters = NULL, - type = c("code", "label", "both"), - lang = c("en", "fr", "de"), - stringsAsFactors = default.stringsAsFactors(), - ...){ - - #get response - url <- eurostat_json_url(id = id, filters = filters, lang = lang) - resp <- httr::GET(url, ...) - status <- httr::status_code(resp) - - # check status and get json - msg <- ". Some datasets are not accessible via the eurostat interface. You can try to search the data manually from the comext database at http://epp.eurostat.ec.europa.eu/newxtweb/ or bulk download facility at http://ec.europa.eu/eurostat/estat-navtree-portlet-prod/BulkDownloadListing or annual Excel files http://ec.europa.eu/eurostat/web/prodcom/data/excel-files-nace-rev.2" - if (status == 200){ - jdat <- jsonlite::fromJSON(url) - } else if (status == 400){ - stop("Failure to get data. Probably invalid dataset id. Status code: ", - status, msg) - } else if (status == 500){ - stop("Failure to get data. Probably filters did not return any data - or data exceeded query size limitation. Status code: ", status, msg) - } else { - stop("Failure to get data. Status code: ", status, msg) +#' @export +get_eurostat_json <- function(id, + filters = NULL, + type = "code", + lang = "en", + stringsAsFactors = FALSE, + proxy = FALSE, + ...) { + + ## Special products that must be built to matrix + ## User is prompted to halt and use iotables::iotables_download() + user_want_stop <- special_id_values(id) + if (user_want_stop) { + return(NULL) + } + + # Check if you have access to ec.europe.eu. + if (!check_access_to_data()) { + # nocov start + message("You have no access to ec.europe.eu. + Please check your connection and/or review your proxy settings") + # nocov end } + + # construct url + url <- eurostat_json_url(id = id, filters = filters, lang = lang) + # set user agent with version + # ua <- httr::user_agent(paste0("eurostat_", + # packageDescription("eurostat", fields = "Version"))) + # ua <- httr::user_agent("https://github.com/rOpenGov/eurostat") - # get json data - dims <- jdat[[1]]$dimension - ids <- dims$id + if (proxy == TRUE) { + # Check if "..." has arguments needed for proxy + args <- list(...) + dot_url <- dot_port <- dot_username <- dot_password <- NULL + if("url" %in% names(args)) dot_url <- args$url + if("port" %in% names(args)) dot_port <- as.numeric(args$port) + if("username" %in% names(args)) dot_username <- args$username + if("password" %in% names(args)) dot_port <- args$password + if("auth" %in% names(args)) { + dot_auth <- args$auth + } else { + dot_auth <- "basic" + } - dims_list <- lapply(dims[rev(ids)], function(x){ + resp <- httr2::request(url) %>% + httr2::req_user_agent(string = "https://github.com/rOpenGov/eurostat") %>% + httr2::req_proxy(url = dot_url, + port = dot_port, + username = dot_username, + password = dot_password, + auth = dot_auth) %>% + httr2::req_retry(max_tries = 3, max_seconds = 60) %>% + httr2::req_error(is_error = function(resp) FALSE) %>% + httr2::req_perform() + } + resp <- httr2::request(url) %>% + httr2::req_user_agent(string = "https://github.com/rOpenGov/eurostat") %>% + httr2::req_retry(max_tries = 3, max_seconds = 60) %>% + httr2::req_error(is_error = function(resp) FALSE) %>% + httr2::req_perform() + + # RETRY GET 3 times + # resp <- httr::RETRY(verb = "GET", + # url = url, + # times = 3, + # terminate_on = c(404), + # ua) + + # Source: httr vignette "Best practices for API packages" [httr_vignette] + if (httr2::resp_content_type(resp) != "application/json") { + stop("API did not return json", call. = FALSE) + } + + # parse JSON data into R object (as per [httr_vignette]) + # assume that content encoding is utf8 + result <- httr2::resp_body_json( + resp = resp, + simplifyVector = TRUE) + + if (httr2::resp_is_error(resp)) { + + # These objects are only needed if there is an error + json_data_frame <- as.data.frame(result) + status <- json_data_frame$error.status + id <- json_data_frame$error.id + label <- json_data_frame$error.label + + # sdmx_http_errors is stored in R/sysdata.rda + # same data in extdata/sdmx_to_http_error_mapping.csv file + faultstring <- sdmx_http_errors$sdmx.faultstring[which(sdmx_http_errors$sdmx.faultcode == id & sdmx_http_errors$http.status_code == status)] + status_code_label <- sdmx_http_errors$http.status_code.label[grep(status, sdmx_http_errors$http.status_code)][1] + + if (status == 416) { + stop(stringr::str_glue("Too many categories have been requested. Maximum is 50.\n", + "HTTP status: {status} ({status_code_label})\n", + " Error id: {id} ({faultstring})\n", + " Error label from API: {label}") + ) + } else { + stop(stringr::str_glue("\n", + "HTTP status: {status} ({status_code_label})\n", + " Error id: {id} ({faultstring})\n", + " Error label from API: {label}") + ) + } + } + + if (resp$status_code == 200 && length(result$value) == 0) { + + # nocov start + msg <- paste(" Please also note that some datasets are not accessible via", + "the eurostat API interface. You can try to search the data", + "manually from the comext database at", + "https://ec.europa.eu/eurostat/comext/newxtweb/ or explore", + "data at https://ec.europa.eu/eurostat/web/main/data/database") + # nocov end + + stop(paste("HTTP status: 200, but the dataset didn't have any values.\n", + " Editing the query parameters may resolve the issue.\n", + msg) + ) + } + + #status <- httr::status_code(resp) + + # check status and get json + jdat <- result + # no need to download same data twice + # jdat <- jsonlite::fromJSON(url, simplifyVector = TRUE) + + # dims <- jdat[[1]]$dimension # Was called like this in API v1.1 + dims <- jdat$dimension # Switched to this with API v2.1 + # ids <- dims$id # v1.1 + ids <- jdat$id # v2.1 + + dims_list <- lapply(dims[rev(ids)], function(x) { y <- x$category$label - if (type[1] == "label") { + if (type == "label") { y <- unlist(y, use.names = FALSE) - } else if (type[1] == "code"){ + } else if (type == "code") { y <- names(unlist(y)) - } else if (type[1] == "both"){ + } else if (type == "both") { y <- unlist(y) } else { stop("Invalid type ", type) } }) - - variables <- expand.grid(dims_list, KEEP.OUT.ATTRS = FALSE, - stringsAsFactors = stringsAsFactors) - - dat <- data.frame(variables[rev(names(variables))], values = jdat[[1]]$value) - - as_data_frame(dat) - -} + variables <- expand.grid(dims_list, + KEEP.OUT.ATTRS = FALSE, + stringsAsFactors = stringsAsFactors + ) + + # dat <- data.frame(variables[rev(names(variables))], values = jdat[[1]]$value) # v1.1 + dat <- as.data.frame(variables[rev(names(variables))]) + vals <- unlist(jdat$value, use.names = FALSE) + dat$values <- rep(NA, nrow(dat)) + inds <- 1 + as.numeric(names(jdat$value)) # 0-indexed + if (!length(vals) == length(inds)) { + stop("Complex indexing not implemented.") + } + dat$values[inds] <- vals + + tibble::as_tibble(dat) +} -# Internal function to build json url -eurostat_json_url <- function(id, filters, lang){ +#' @title Internal function to build json url +#' @description Internal function to build json url +#' @importFrom utils hasName +#' @importFrom httr2 url_parse url_build +#' @noRd +#' @keywords internal utilities +eurostat_json_url <- function(id, filters = NULL, lang = NULL) { # prepare filters for query filters2 <- as.list(unlist(filters)) + # Give items names without numbers names(filters2) <- rep(names(filters), lapply(filters, length)) - - # prepare url - url_list <- list(scheme = "http", - hostname = "ec.europa.eu", - path = file.path("eurostat/wdds/rest/data/v1.1/json", - lang[1], id), - query = filters2) - class(url_list) <- "url" - url <- httr::build_url(url_list) + + # The “format” parameter’s only possible value is "JSON". + if (!hasName(filters2, "format")) { + filters2$format <- "JSON" + } + + filters2$lang <- check_lang(lang) + + host_url <- "https://ec.europa.eu/eurostat/api/dissemination/" + service <- "statistics/" + version <- "1.0/" + response_type <- "data/" + datasetCode <- id + + # Parse host_url and add relevant information in the standard list + url_list <- httr2::url_parse(host_url) + # Paste "statistics/1.0/data/{id}" at the end of the fixed part of the URL + url_list$path <- paste0(url_list$path, + service, + version, + response_type, + datasetCode) + url_list$query <- filters2 + + url <- httr2::url_build(url_list) url -} \ No newline at end of file +} + +# Internal function to give warning if symmetric input-output tables need to download into strict matirx formats. +special_id_values <- function(id) { + siot_id_codes <- c( + "naio_10_cp1700", "naio_10_pyp1700", + "naio_10_cp1750", "naio_10_pyp1750", + "naio_10_cp15", "naio_10_cp16", + "naio_10_cp1610", "naio_10_pyp1610", + "naio_10_cp1620", "naio_10_pyp1620", + "naio_10_cp1630", "naio_10_pyp1630" + ) + if (id %in% siot_id_codes) { + message( + "The requested product id is a special input-output matrix.", + "\nTo keep the matrix structure for further use, download it with iotables::iotables_download().\nThe iotables package is an extension for such cases to the eurostat package." + ) + answer <- readline(prompt = "Do you want to stop downloading now? [y/n] ") + if (tolower(answer) == "y") TRUE else FALSE + } else { + # By default evaluates to FALSE and no interruption happens + FALSE + } +} + +# Internal function to give warning if sub-national geo codes need validation +is_regional_nuts_present <- function(dat, geo) { + potentional_regional_codes <- unique(dat$geo)[nchar(unique(dat$geo)) > 2] + + potentional_regional_codes <- potentional_regional_codes[!substr(potentional_regional_codes, 1, 2) %in% c("EU", "EA")] + + if (length(potentional_regional_codes) > 0) { + types_found <- paste(sort(unique(validate_geo_code(potentional_regional_codes, nuts_year = 2021))), collapse = ", ") + message( + "The following sub-national geographical codes present in the dataset:\n", types_found, + "\nRegional and metropolitian area boundaries, codes and names are changing frequently.", + "\nSee ?validate_geo_code, ?validate_nuts_regions and ?recode_nuts or the", + "\n'Mapping Regional Data, Mapping Metadata Problems' vignette for a tutorial." + ) + } +} diff --git a/R/get_eurostat_raw.R b/R/get_eurostat_raw.R index dd180531..edb01459 100755 --- a/R/get_eurostat_raw.R +++ b/R/get_eurostat_raw.R @@ -1,50 +1,103 @@ -#' @title Download Data from Eurostat Database -#' @description Download data from the eurostat database. -#' @param id A code name for the dataset of interested. See the table of -#' contents of eurostat datasets for more details. -#' @return A dataset in tibble format. First column contains comma -#' separated codes of cases. Other columns usually corresponds to -#' years and column names are years with preceding X. Data is in -#' character format as it contains values together with eurostat -#' flags for data. -#' @seealso \code{\link{get_eurostat}}. -#' @details Data is downloaded from -#' \url{http://ec.europa.eu/eurostat/estat-navtree-portlet-prod/BulkDownloadListing} and transformed into tabular format. -#' @references see citation("eurostat") -#' @author Przemyslaw Biecek, Leo Lahti and Janne Huovari \email{ropengov-forum@@googlegroups.com} -#' @examples \dontrun{ -#' tmp <- eurostat:::get_eurostat_raw("educ_iste") -#' head(tmp) -#' } +#' @title Download Data from Eurostat Dissemination API +#' @description Download data from the eurostat database through the new +#' dissemination API. +#' @inheritParams get_eurostat +#' @return A dataset in tibble format. First column contains comma +#' separated codes of cases. Other columns usually corresponds to +#' years and column names are years with preceding X. Data is in +#' character format as it contains values together with eurostat +#' flags for data. +#' @seealso +#' [get_eurostat()] +#' +#' @inheritSection eurostat-package Data source: Eurostat SDMX 2.1 Dissemination API +#' @inheritSection eurostat-package Eurostat: Copyright notice and free re-use of data +#' @inheritSection eurostat-package Citing Eurostat data +#' @inheritSection eurostat-package Disclaimer: Availability of filtering functionalities +#' @references +#' See `citation("eurostat")`: +#' +#' ```{r, echo=FALSE, comment="#" } +#' citation("eurostat") +#' ``` +#' +#' @author Przemyslaw Biecek, Leo Lahti, Janne Huovari and Pyry Kantanen +#' @examplesIf check_access_to_data() +#' \donttest{ +#' eurostat:::get_eurostat_raw("educ_iste") +#' } +#' +#' @importFrom readr read_tsv cols col_character +#' @importFrom utils download.file +#' @importFrom tibble as_tibble +#' @importFrom curl curl_download +#' @importFrom data.table fread +#' #' @keywords utilities database -get_eurostat_raw <- function(id) { - +get_eurostat_raw <- function(id, use.data.table = FALSE) { base <- getOption("eurostat_url") - url <- paste0(base, - "estat-navtree-portlet-prod/BulkDownloadListing?sort=1&file=data%2F", - id, ".tsv.gz") + url <- paste0( + base, + "api/dissemination/sdmx/2.1/data/", + id, + "?format=TSV&compressed=true" + ) tfile <- tempfile() on.exit(unlink(tfile)) + + if (.Platform$OS.type == "windows") { + curl::curl_download(url = url, destfile = tfile) + } else { + # R Packages (2e): Restore state with base::on.exit() + # timeout = 120 should in most cases be enough for even the biggest datasets + op <- options(timeout = 120) + on.exit(options(op), add = TRUE) + utils::download.file(url, tfile) + } - # download and read file - utils::download.file(url, tfile) - - dat <- readr::read_tsv(gzfile(tfile), na = ":", - col_types = readr::cols(.default = readr::col_character())) - + if (!use.data.table) { + # OLD CODE + dat <- readr::read_tsv(gzfile(tfile), + na = ":", + progress = TRUE, + col_types = readr::cols(.default = readr::col_character()) + ) + } else if (use.data.table) { + # NEW CODE: data.table + dat <- data.table::fread(cmd = paste("gzip -dc", tfile), + na.strings = ":", + header = TRUE, + colClasses = "character") + + # OLD CODE + # data.table object does not need to be converted into a tibble at this + # point as it will handled by data.table functions in tidy_eurostat. + # dat <- tibble::as_tibble(dat) + } + # check validity - - if (ncol(dat) < 2 | nrow(dat) < 1) { - msg <- ". Some datasets are not accessible via the eurostat interface. You can try to search the data manually from the comext database at http://epp.eurostat.ec.europa.eu/newxtweb/ or bulk download facility at http://ec.europa.eu/eurostat/estat-navtree-portlet-prod/BulkDownloadListing or annual Excel files http://ec.europa.eu/eurostat/web/prodcom/data/excel-files-nace-rev.2" + if (ncol(dat) < 2 || nrow(dat) < 1) { + # nocov start + msg <- paste0( + ". Some datasets (for instance the comext type) are not ", + "accessible via the eurostat interface. You can try to ", + "search the data manually from the comext database at ", + "http://epp.eurostat.ec.europa.eu/newxtweb/ ", + "or bulk download facility at ", + "http://ec.europa.eu/eurostat/estat-navtree-portlet-prod/BulkDownloadListing ", + "or annual Excel files at ", + "http://ec.europa.eu/eurostat/web/prodcom/data/excel-files-nace-rev.2" + ) + # nocov end + if (grepl("does not exist or is not readable", dat[1])) { - stop(id, " does not exist or is not readable", msg) - } else { + } else { stop(paste("Could not download ", id, msg)) } } - + dat } diff --git a/R/get_eurostat_toc.R b/R/get_eurostat_toc.R index 1e93d923..3c1d13bf 100755 --- a/R/get_eurostat_toc.R +++ b/R/get_eurostat_toc.R @@ -1,30 +1,82 @@ #' @title Download Table of Contents of Eurostat Data Sets -#' @description Download table of contents (TOC) of eurostat datasets. -#' @return A tibble with eight columns -#' \itemize{ -#' \item{title}{The name of dataset of theme} -#' \item{code}{The codename of dataset of theme, will be used by the eurostat and get_eurostat_raw functions.} -#' \item{type}{Is it a dataset, folder or table.} -#' \item{last.update.of.data, last.table.structure.change, data.start, data.end}{Dates.} -#' } -#' @export -#' @seealso \code{\link{get_eurostat}}, \code{\link{search_eurostat}}. -#' @details The TOC is downloaded from \url{http://ec.europa.eu/eurostat/estat-navtree-portlet-prod/BulkDownloadListing?sort=1&file=table_of_contents_en.txt}. The values in column 'code' should be used to download a selected dataset. -#' @references See citation("eurostat"). -#' @author Przemyslaw Biecek and Leo Lahti \email{ropengov-forum@@googlegroups.com} -#' @examples \dontrun{tmp <- get_eurostat_toc(); head(tmp)} +#' @description Download table of contents (TOC) of eurostat datasets. +#' @details In the downloaded Eurostat Table of Contents the 'code' column +#' values are refer to the function 'id' that is used as an argument in certain +#' functions when downloading datasets. +#' @return A tibble with nine columns: +#' \describe{ +#' \item{title}{Dataset title in English (default)} +#' \item{code}{ Each item (dataset, table and folder) of the TOC has a +#' unique code which allows it to be identified in the API. Used in the +#' [get_eurostat()] and [get_eurostat_raw()] functions to retrieve datasets.} +#' \item{type}{dataset, folder or table} +#' \item{last.update.of.data}{Date, indicates the last time the +#' dataset/table was updated (format `DD.MM.YYYY` or `%d.%m.%Y`)} +#' \item{last.table.structure.change}{Date, indicates the last time the +#' dataset/table structure was modified (format `DD.MM.YYYY` or `%d.%m.%Y`)} +#' \item{data.start}{Date of the oldest value included in the dataset +#' (if available) (format usually `YYYY` or `%Y` but can also be `YYYY-MM`, +#' `YYYY-MM-DD`, `YYYY-SN`, `YYYY-QN` etc.)} +#' \item{data.end}{Date of the most recent value included in the dataset +#' (if available) (format usually `YYYY` or `%Y` but can also be `YYYY-MM`, +#' `YYYY-MM-DD`, `YYYY-SN`, `YYYY-QN` etc.)} +#' \item{values}{Number of actual values included in the dataset} +#' \item{hierarchy}{Hierarchy of the data navigation tree, represented +#' in the original txt file by a 4-spaces indentation prefix in the title} +#' } +#' +#' @seealso [get_eurostat()], [search_eurostat()] +#' @inheritSection eurostat-package Data source: Eurostat Table of Contents +#' @inherit get_eurostat references +#' @inheritParams get_eurostat +#' +#' @author +#' Przemyslaw Biecek, Leo Lahti and Pyry Kantanen +#' +#' @examplesIf check_access_to_data() +#' \donttest{ +#' tmp <- get_eurostat_toc() +#' head(tmp) +#' +#' # Convert columns containing dates as character into Date class +#' # Last update of data +#' tmp[[4]] <- as.Date(tmp[[4]], format = c("%d.%m.%Y")) +#' # Last table structure change +#' tmp[[5]] <- as.Date(tmp[[5]], format = c("%d.%m.%Y")) +#' # Data start, contains several formats (date, week, month quarter, semester) +#' # Unfortunately semesters are not directly supported so they need to be +#' # changed into quarters +#' tmp$data.start <- gsub("S2", "Q3", tmp$data.start) +#' tmp$data.start <- lubridate::as_date( +#' x = tmp$data.start, +#' format = c("%Y", "%Y-Q%q", "%Y-W%W", "%Y-S%q", "%Y-%m-%d", "%Y-%m") +#' ) +#' # Data end, same as data start +#' tmp$data.end <- gsub("S2", "Q3", tmp$data.end) +#' tmp$data.end <- lubridate::as_date( +#' x = tmp$data.end, +#' format = c("%Y", "%Y-Q%q", "%Y-W%W", "%Y-S%q", "%Y-%m-%d", "%Y-%m") +#' ) +#' } +#' #' @keywords utilities database -get_eurostat_toc <- function() { - set_eurostat_toc() - invisible(get(".eurostatTOC", envir = .EurostatEnv)) +#' @export +get_eurostat_toc <- function(lang = "en") { + + lang <- check_lang(lang) + + language_version <- switch(lang, + en = ".eurostatTOC", + fr = ".eurostatTOC_fr", + de = ".eurostatTOC_de") + + set_eurostat_toc(lang = lang) + + invisible(get(language_version, envir = .EurostatEnv)) } -# @describeIn get_eurostat_toc Old deprecated version -# @export -#getEurostatTOC <- function() { -# .Deprecated("get_eurostat_toc") -# get_eurostat_toc() -#} - - - +clean_eurostat_toc <- function() { + objects_in_env <- objects(envir = .EurostatEnv, all.names = TRUE) + toc_objects_in_env <- objects_in_env[grep(".eurostatTOC", objects_in_env)] + remove(list = toc_objects_in_env, envir = .EurostatEnv) +} diff --git a/R/harmonize_country_code.R b/R/harmonize_country_code.R index 97426e2d..55a6a1aa 100755 --- a/R/harmonize_country_code.R +++ b/R/harmonize_country_code.R @@ -4,23 +4,23 @@ #' represent Greece, and UK (not GB) is used to represent the #' United Kingdom. This function turns country codes into to ISO #' 3166-1 alpha-2. -#' @param x A character or a factor vector of eurostat countycodes. +#' @param x A character or a factor vector of eurostat countycodes. #' @export -#' @author Janne Huovari \email{janne.huovari@@ptt.fi} +#' @author Janne Huovari #' @return a vector. -#' @examples -#' \dontrun{ -#' lp <- get_eurostat("nama_aux_lp") -#' lp$geo <- harmonize_country_code(lp$geo) -#' } - -harmonize_country_code <- function (x) { - - if (is.factor(x)){ +#' @family helpers +#' @examplesIf check_access_to_data() +#' \donttest{ +#' lp <- get_eurostat("nama_10_lp_ulc") +#' lp$geo <- harmonize_country_code(lp$geo) +#' } +#' +harmonize_country_code <- function(x) { + if (is.factor(x)) { levels(x) <- harmonize_country_code(levels(x)) } else { x <- gsub("EL", "GR", x) - x <- gsub("UK", "GB", x) + x <- gsub("UK", "GB", x) } - x -} \ No newline at end of file + x +} diff --git a/R/label_eurostat.R b/R/label_eurostat.R index 9b478a6f..bf2ad8bf 100755 --- a/R/label_eurostat.R +++ b/R/label_eurostat.R @@ -1,63 +1,87 @@ -#' @title Get Eurostat Codes +#' @title Get Eurostat Codes for data downloaded from new dissemination API #' @description Get definitions for Eurostat codes from Eurostat dictionaries. -#' @details A character or a factor vector of codes returns a corresponding -#' vector of definitions. \code{label_eurostat} labels also data_frames from -#' \code{\link{get_eurostat}}. For vectors a dictionary name have to be -#' supplied. For data_frames dictonary names are taken from column names. -#' "time" and "values" columns are returned as they were, so you can supply -#' data_frame from \code{\link{get_eurostat}} and get data_frame with +#' @details A character or a factor vector of codes returns a corresponding +#' vector of definitions. [label_eurostat()] labels also data_frames from +#' [get_eurostat()]. For vectors a dictionary name have to be +#' supplied. For data_frames dictionary names are taken from column names. +#' "time" and "values" columns are returned as they were, so you can supply +#' data_frame from [get_eurostat()] and get data_frame with #' definitions instead of codes. -#' -#' Some Eurostat dictionaries includes dublicated labels. By default -#' dublicated labels cause an error, but they can be fixed automatically -#' with \code{fix_duplicated = TRUE}. -#' +#' +#' Some Eurostat dictionaries includes duplicated labels. By default +#' duplicated labels cause an error, but they can be fixed automatically +#' with `fix_duplicated = TRUE`. +#' #' @param x A character or a factor vector or a data_frame. #' @param dic A string (vector) naming eurostat dictionary or dictionaries. -#' If \code{NULL} (default) dictionry names taken from column names of +#' If `NULL` (default) dictionary names taken from column names of #' the data_frame. #' @param code For data_frames names of the column for which also code columns #' should be retained. The suffix "_code" is added to code column names. #' @param eu_order Logical. Should Eurostat ordering used for label levels. #' Affects only factors. -#' @param lang A character, code for language. Available are "en" (default), -#' "fr" and "de". -#' @param countrycode A \code{NULL} or a name of the coding scheme for -#' the \code{\link[countrycode]{countrycode}} +#' @param countrycode A `NULL` or a name of the coding scheme for +#' the [countrycode::countrycode()] #' to label "geo" variable with countrycode-package. It can be used to #' convert to short and long country names in many different languages. -#' If \code{NULL} (default) eurostat dictionary is used instead. -#' @param countrycode_nomatch What to do when using the countrycode to label a "geo" and -#' countrycode fails to find a match, for example other than country codes like EU28. -#' the original code is used with -#' a \code{NULL} (default), eurostat dictionary label is used with "eurostat", -#' and \code{NA} is used with NA. -#' @param custom_dic a named vector or named list of named vectors to give an own dictionary -#' for (part of) codes. Names of the vector should be codes and values labels. List -#' can be used to spesify dictonaries and then list names should be dictionary codes. +#' If `NULL` (default) eurostat dictionary is used instead. +#' @param countrycode_nomatch What to do when using the countrycode to label +#' a "geo" and countrycode fails to find a match, for example other than +#' country codes like EU28. The original code is used with +#' a `NULL` (default), eurostat dictionary label is used with "eurostat", +#' and `NA` is used with NA. +#' @param custom_dic a named vector or named list of named vectors to give an +#' own dictionary for (part of) codes. Names of the vector should be codes +#' and values labels. List can be used to specify dictionaries and then +#' list names should be dictionary codes. #' @param fix_duplicated A logical. If TRUE, the code is added to the -#' duplicated label values. If FALSE (default) error is given if -#' labelling produce duplicates. -#' @export -#' @author Janne Huovari \email{janne.huovari@@ptt.fi} +#' duplicated label values. If FALSE (default) error is given if +#' labeling produce duplicates. +#' @inheritParams get_eurostat +#' @author Janne Huovari +#' @family helpers +#' @seealso [countrycode::countrycode()] #' @return a vector or a data_frame. #' @examples -#' \dontrun{ -#' lp <- get_eurostat("nama_10_lp_ulc") -#' lpl <- label_eurostat(lp) -#' str(lpl) -#' lpl_order <- label_eurostat(lp, eu_order = TRUE) -#' lpl_code <- label_eurostat(lp, code = "unit") -#' label_eurostat_vars(names(lp)) -#' label_eurostat_tables("nama_10_lp_ulc") -#' label_eurostat(c("FI", "DE", "EU28"), dic = "geo") -#' label_eurostat(c("FI", "DE", "EU28"), dic = "geo", custom_dic = c(DE = "Germany")) -#' label_eurostat(c("FI", "DE", "EU28"), dic = "geo", countrycode = "country.name", -#' custom_dic = c(EU28 = "EU")) -#' label_eurostat(c("FI", "DE", "EU28"), dic = "geo", countrycode = "country.name") -#' # In Finnish -#' label_eurostat(c("FI", "DE", "EU28"), dic = "geo", countrycode = "cldr.short.fi") -#' } +#' \dontrun{ +#' lp <- get_eurostat("nama_10_lp_ulc") +#' lpl <- label_eurostat(lp) +#' str(lpl) +#' lpl_order <- label_eurostat(lp, eu_order = TRUE) +#' lpl_code <- label_eurostat(lp, code = "unit") +#' # Note that the dataset id must be provided in label_eurostat_vars +#' label_eurostat_vars(id = "nama_10_lp_ulc", x = "geo", lang = "en") +#' label_eurostat_tables("nama_10_lp_ulc") +#' label_eurostat(c("FI", "DE", "EU28"), dic = "geo") +#' label_eurostat( +#' c("FI", "DE", "EU28"), +#' dic = "geo", +#' custom_dic = c(DE = "Germany") +#' ) +#' label_eurostat( +#' c("FI", "DE", "EU28"), +#' dic = "geo", countrycode = "country.name", +#' custom_dic = c(EU28 = "EU") +#' ) +#' label_eurostat( +#' c("FI", "DE", "EU28"), +#' dic = "geo", +#' countrycode = "country.name" +#' ) +#' # In Finnish +#' label_eurostat( +#' c("FI", "DE", "EU28"), +#' dic = "geo", +#' countrycode = "cldr.short.fi" +#' ) +#' } +#' +#' @importFrom countrycode countrycode +#' @importFrom tibble as_tibble +#' @importFrom dplyr filter coalesce +#' @importFrom stringr str_glue +#' +#' @export label_eurostat <- function(x, dic = NULL, @@ -69,16 +93,26 @@ label_eurostat <- custom_dic = NULL, fix_duplicated = FALSE) { - # Avoid warnings - code_name <- NULL - - if (is.data.frame(x)) { - y <- x - - mynams <- names(y)[!(names(y) %in% c("time", "values", "flags"))] - - for (i in names(y)[!(names(y) %in% c("time", "values", "flags"))]) { - y[[i]] <- label_eurostat(y[[i]], i, + # Check if you have access to ec.europe.eu. + if (!check_access_to_data()) { + message(paste("You have no access to ec.europe.eu. Please check your", + "connection and/or review your proxy settings")) + } else { + + # Avoid warnings + code_name <- NULL + + if (is.data.frame(x)) { + y <- x + + mynams <- names(y)[!(names(y) %in% + c("TIME_PERIOD", "time", "values", "flags"))] + + for (i in names(y)[!(names(y) %in% + c("TIME_PERIOD", "time", "values", "flags"))]) { + y[[i]] <- label_eurostat( + y[[i]], + i, eu_order = eu_order, lang = lang, countrycode = countrycode, @@ -86,135 +120,284 @@ label_eurostat <- custom_dic = custom_dic, fix_duplicated = fix_duplicated ) - } - - # Fix the first two variables - #nams <- names(y) - #y <- cbind(as.vector(unlist(x[[1]])), - # as.vector(unlist(x[[2]])), - # x[, 3:ncol(x)]) - #colnames(y) <- nams - - # Codes added if asked - if (!is.null(code)) { - code_in <- code %in% names(y) - if (!all(code_in)) - stop("code column name(s) ", shQuote(code[!code_in]), " not found on x") - y_code <- x[, code, drop = FALSE] - names(y_code) <- paste0(names(y_code), "_code") - y <- cbind(y_code, y) - } - #return data.frame - return(as_data_frame(y)) - - } else { - if (is.null(dic)) - stop("Dictionary information is missing") - - dic_df <- get_eurostat_dic(dic, lang = lang) - - if (is.factor(x)) { - if (eu_order) { - ord <- dic_order(levels(x), dic_df, "code") - } else { - ord <- seq_along(levels(x)) } - - y <- factor(x, levels(x)[ord], - labels = label_eurostat(levels(x), dic = dic, - eu_order = eu_order, - lang = lang, - countrycode = countrycode, - countrycode_nomatch = countrycode_nomatch, - custom_dic = custom_dic, - fix_duplicated = fix_duplicated)[ord] - ) - - #return factor - return(y) - - } else if (dic == "geo" & !is.null(countrycode)){ - if (is.null(countrycode_nomatch)){ - y <- countrycode::countrycode(x, origin = "eurostat", destination = countrycode, nomatch = NULL) - } else if (is.na(countrycode_nomatch)) { - y <- countrycode::countrycode(x, origin = "eurostat", destination = countrycode, nomatch = NA) - } else if (countrycode_nomatch == "eurostat") { - y <- countrycode::countrycode(x, origin = "eurostat", destination = countrycode, nomatch = NA) - y[is.na(y)] <- label_eurostat(x[is.na(y)], dic = "geo", lang = lang, fix_duplicated = fix_duplicated) - } else { - stop("unknown argument ", countrycode_nomatch, " for countrycode_nomatch") + + # Fix the first two variables + # nams <- names(y) + # y <- cbind(as.vector(unlist(x[[1]])), + # as.vector(unlist(x[[2]])), + # x[, 3:ncol(x)]) + # colnames(y) <- nams + + # Codes added if asked + if (!is.null(code)) { + code_in <- code %in% names(y) + if (!all(code_in)) { + stop( + stringr::str_glue( + "The following code column name(s) not found on x:\n", + "{code[!code_in]}") + ) + } + y_code <- x[, code, drop = FALSE] + names(y_code) <- paste0(names(y_code), "_code") + y <- cbind(y_code, y) } + + return(tibble::as_tibble(y)) } else { - # dics are in upper case, change if x is not - test_n <- min(length(x), 5) - if (!all(toupper(x[1:test_n]) == x[1:test_n])) - x <- toupper(x) - # test duplicates - dic_sel <- dplyr::filter(dic_df, code_name %in% x) - - if (anyDuplicated(dic_sel$full_name)) { - if (fix_duplicated) { - dup_labels <- - dic_sel$full_name %in% dic_sel$full_name[duplicated(dic_sel$full_name)] - modif_dup_labels <- paste(dic_sel$code_name[dup_labels], - dic_sel$full_name[dup_labels], - sep = " ") - dic_sel$full_name[dup_labels] <- modif_dup_labels - message( - "Labels for ", - dic, - " includes duplicated labels in the Eurostat dictionary. ", - "Codes have been added as a prefix for dublicated.\n", - "Modified labels are: ", - paste0(modif_dup_labels, collapse = ", ") - ) + if (is.null(dic)) { + stop("Dictionary information is missing") + } + + dic_df <- get_eurostat_dic(dic, lang = lang) + + if (is.factor(x)) { + if (eu_order) { + ord <- dic_order(levels(x), dic_df, "code") + } else { + ord <- seq_along(levels(x)) + } + + y <- factor( + x, + levels(x)[ord], + labels = + label_eurostat( + levels(x), + dic = dic, + eu_order = eu_order, + lang = lang, + countrycode = countrycode, + countrycode_nomatch = countrycode_nomatch, + custom_dic = custom_dic, + fix_duplicated = fix_duplicated + )[ord] + ) + + # return factor + return(y) + } else if (dic == "geo" && !is.null(countrycode)) { + if (is.null(countrycode_nomatch)) { + y <- countrycode::countrycode(x, + origin = "eurostat", + destination = countrycode, + nomatch = NULL) + } else if (is.na(countrycode_nomatch)) { + y <- countrycode::countrycode(x, + origin = "eurostat", + destination = countrycode, + nomatch = NA) + } else if (countrycode_nomatch == "eurostat") { + y <- countrycode::countrycode(x, + origin = "eurostat", + destination = countrycode, + nomatch = NA) + y[is.na(y)] <- label_eurostat(x[is.na(y)], + dic = "geo", + lang = lang, + fix_duplicated = fix_duplicated) } else { stop( - "Labels for ", - dic, - " includes duplicated labels in the Eurostat dictionary. ", - "Use fix_duplicated = TRUE with label_eurostat() to fix duplicated - labels automatically." - ) + stringr::str_glue( + "unknown argument {countrycode_nomatch} for countrycode_nomatch" + ) + ) } + } else { + # dics are in upper case, change if x is not + test_n <- min(length(x), 5) + if (!all(toupper(x[1:test_n]) == x[1:test_n])) { + x <- toupper(x) + } + # test duplicates + dic_sel <- dplyr::filter(dic_df, code_name %in% x) + + if (anyDuplicated(dic_sel$full_name)) { + if (fix_duplicated) { + dup_labels <- dic_sel$full_name %in% + dic_sel$full_name[duplicated(dic_sel$full_name)] + modif_dup_labels <- paste( + dic_sel$code_name[dup_labels], + dic_sel$full_name[dup_labels], + sep = " " + ) + dic_sel$full_name[dup_labels] <- modif_dup_labels + message( + "Labels for ", + dic, + " includes duplicated labels in the Eurostat dictionary. ", + "Codes have been added as a prefix for duplicated.\n", + "Modified labels are: ", + paste0(modif_dup_labels, collapse = ", ") + ) + } else { + stop( + "Labels for ", + dic, + " includes duplicated labels in the Eurostat dictionary. ", + "Use fix_duplicated = TRUE with label_eurostat() to fix ", + "duplicated labels automatically." + ) + } + } + # mapvalues + y <- dic_sel[[2]][match(x, dic_sel[[1]])] + } + + # apply custom_dic + if (!is.null(custom_dic)) { + if (is.list(custom_dic)) custom_dic <- custom_dic[[dic]] + y <- dplyr::coalesce(unname(custom_dic[x]), y) + } + + if (any(is.na(y))) { + warning("All labels for ", dic, " were not found.") } - # mapvalues - y <- dic_sel[[2]][match(x, dic_sel[[1]])] - - } - - # apply custom_dic - if (!is.null(custom_dic)){ - if (is.list(custom_dic)) custom_dic <- custom_dic[[dic]] - y <- dplyr::coalesce(unname(custom_dic[x]), y) } - - if (any(is.na(y))) - warning("All labels for ", dic, " were not found.") - - } - - - y - + y + } } -#' @describeIn label_eurostat Get definitions for variable (column) names. For -#' objects other than characters or factors definitions are get for names. +## OLD CODE +# @rdname eurostat-deprecated +# @inheritParams label_eurostat +# @export +# label_eurostat_vars <- function(x, lang = "en") { +# .Deprecated("label_eurostat_vars2") +# dictname <- "dimlst" +# +# if (!(is.character(x) || is.factor(x))) { +# x <- names(x) +# } +# x <- x[!grepl("values", x)] # remove values column +# +# url <- getOption("eurostat_url") +# tname <- paste0( +# url, +# "estat-navtree-portlet-prod/BulkDownloadListing?file=dic%2F", lang, "%2F", +# dictname, ".dic" +# ) +# dict <- readr::read_tsv(url(tname), +# col_names = c("code_name", "full_name"), +# col_types = readr::cols(.default = readr::col_character()) +# ) +# dict$full_name <- gsub( +# pattern = "\u0092", replacement = "'", +# dict$full_name +# ) +# +# +# y <- dict$full_name[which(dict$code_name %in% toupper(x))] +# +# if (length(y) < length(x)) { +# warning(paste( +# "The query did not return names for the following variables:\n", +# x[which(!(toupper(x) %in% dict$code_name))] +# ) +# ) +# } +# +# y +# } + + +#' @describeIn label_eurostat Get definitions for variable (column) names. +#' @inheritParams get_eurostat +#' @importFrom httr2 url_build url_parse +#' #' @export -label_eurostat_vars <- function(x, lang = "en") { - if (!(is.character(x) | is.factor(x))) - x <- names(x) - x <- x[!grepl("values", x)] # remove values column - label_eurostat(x, dic = "dimlst", lang = lang) +label_eurostat_vars <- function(x = NULL, id, lang = "en") { + + eurostat_base_url <- getOption("eurostat_url") + api_base_uri <- paste0(eurostat_base_url, "api/dissemination/sdmx/2.1") + resource <- "conceptscheme" + agencyID <- "ESTAT" + resourceID <- id + parameters <- list( + compressed = "false" + ) + + lang <- check_lang(lang) + + req_url <- paste(api_base_uri, resource, agencyID, resourceID, sep = "/") + req_url <- httr2::url_parse(req_url) + req_url$query <- parameters + req_url <- httr2::url_build(req_url) + + columns <- c("code_name", "full_name") + dict = data.frame(matrix(nrow = 0, ncol = length(columns))) + + xml_obj <- xml2::read_xml(req_url) + concepts <- xml_obj %>% + xml2::xml_find_all(xpath = stringr::str_glue(".//s:Concept")) %>% + xml2::xml_attr(attr = "id") + + for (i in seq_len(length(concepts))) { + concept <- concepts[i] + var_name <- xml2::xml_find_all( + xml_obj, + xpath = stringr::str_glue(".//s:Concept[@id='{concept}']/c:Name[@xml:lang='{lang}']") + ) %>% + xml2::xml_text() + + dict <- rbind(dict, c(concept, var_name), make.row.names = FALSE) + } + + colnames(dict) <- columns + + if (nrow(dict) == 0) { + warning("The query did not return any names for dataset columns") + return(invisible()) + } else if (nrow(dict) < length(concepts)) { + warning("The query did not return names for all concepts") + } + + if (!is.null(x)) { + filtered_dict <- dict$full_name[which(dict$code_name %in% x)] + return(filtered_dict) + } + + unfiltered_dict <- dict$full_name + unfiltered_dict } #' @describeIn label_eurostat Get definitions for table names +#' @importFrom xml2 xml_find_all xml_text read_xml +#' @importFrom httr2 url_parse url_build +#' @importFrom dplyr %>% +#' @importFrom stringr str_glue #' @export label_eurostat_tables <- function(x, lang = "en") { - if (!(is.character(x) | - is.factor(x))) + if (!(is.character(x) || is.factor(x))) { stop("x have to be a character or a factor") - label_eurostat(x, dic = "table_dic", lang = lang) + } + eurostat_base_url <- getOption("eurostat_url") + api_base_uri <- paste0(eurostat_base_url, "api/dissemination/sdmx/2.1") + resource <- "dataflow" + agencyID <- "ESTAT" + resourceID <- x + parameters <- list( + compressed = "false" + ) + + lang <- check_lang(lang) + + req_url <- paste(api_base_uri, resource, agencyID, resourceID, sep = "/") + req_url <- httr2::url_parse(req_url) + req_url$query <- parameters + req_url <- httr2::url_build(req_url) + + xml_obj <- xml2::read_xml(req_url) + table_name <- xml_obj %>% + xml2::xml_find_all(xpath = stringr::str_glue(".//c:Name[@xml:lang='{lang}']")) %>% + xml2::xml_text() + + if (length(table_name) == 0) { + warning("The query did not return a name for the dataset") + return(invisible()) + } + + table_name } diff --git a/R/regional_coding_functions.R b/R/regional_coding_functions.R new file mode 100755 index 00000000..bd7316a2 --- /dev/null +++ b/R/regional_coding_functions.R @@ -0,0 +1,109 @@ +#' @title Recode Region Codes From Source To Target NUTS Typology +#' @param dat A data frame with a 3-5 character `geo_var` variable +#' to be validated. +#' @param geo_var Defaults to `"geo"`. The variable that contains +#' the 3-5 character geo codes to be validated. +#' @param nuts_year The year of the NUTS typology to use. +#' You can select any valid +#' NUTS definition, i.e. `1999`, `2003`, `2006`, +#' `2010`, `2013`, the currently used `2016` and the +#' already announced and defined `2021`. Defaults to the current +#' typology in force, which is `2016`. +#' @importFrom regions recode_nuts +#' @return The original data frame with a `'geo_var'` column is extended +#' with a `'typology'` column that states in which typology is the `'geo_var'` +#' a valid code. For invalid codes, looks up potential reasons of invalidity +#' and adds them to the `'typology_change'` column, and at last it +#' adds a column of character vector containing the desired codes in the +#' target typology, for example, in the NUTS2013 typology. +#' @family regions functions +#' @export +#' @examples{ +#' foo <- data.frame ( +#' geo = c("FR", "DEE32", "UKI3" , +#' "HU12", "DED", +#' "FRK"), +#' values = runif(6, 0, 100 ), +#' stringsAsFactors = FALSE ) +#' +#' recode_nuts(foo, nuts_year = 2013) +#' } +regions::recode_nuts + +#' @title Validate Conformity With NUTS Geo Codes +#' @details While country codes are technically not part of the NUTS typologies, +#' Eurostat de facto uses a `NUTS0` typology to identify countries. +#' This de facto typology has three exception which are handled by the +#' [validate_nuts_countries][regions::validate_nuts_countries] function. +#' +#' NUTS typologies have different versions, therefore the conformity +#' is validated with one specific versions, which can be any of these: +#' `1999`, `2003`, `2006`, `2010`, +#' `2013`, the currently used `2016` and the already +#' announced and defined `2021`. +#' +#' The NUTS typology was codified with the `NUTS2003`, and the +#' pre-1999 NUTS typologies may confuse programmatic data processing, +#' given that some NUTS1 regions were identified with country codes +#' in smaller countries that had no `NUTS1` divisions. +#' +#' Currently the `2016` is used by Eurostat, but many datasets +#' still contain `2013` and sometimes earlier metadata. +#' +#' @param dat A data frame with a 3-5 character `geo_var` +#' variable to be validated. +#' @param geo_var Defaults to `"geo"`. The variable that contains +#' the 3-5 character geo codes to be validated. +#' @param nuts_year The year of the NUTS typology to use. +#' Defaults to `2016`. You can select any valid +#' NUTS definition, i.e. `1999`, `2003`, `2006`, +#' `2010`, `2013`, the currently used `2016` and the +#' already announced and defined `2021`. +#' @importFrom regions validate_nuts_regions +#' @return Returns the original `dat` data frame with a column +#' that specifies the comformity with the NUTS definition of the year +#' `nuts_year`. +#' @family regions functions +#' @export +#' @examples +#' \donttest{ +#' my_reg_data <- data.frame( +#' geo = c( +#' "BE1", "HU102", "FR1", +#' "DED", "FR7", "TR", "DED2", +#' "EL", "XK", "GB" +#' ), +#' values = runif(10) +#' ) +#' +#' validate_nuts_regions(my_reg_data) +#' +#' validate_nuts_regions(my_reg_data, nuts_year = 2013) +#' +#' validate_nuts_regions(my_reg_data, nuts_year = 2003) +#' } +regions::validate_nuts_regions + + +#' @title Validate Conformity with NUTS Geo Codes (vector) +#' @param geo A vector of geographical code to validate. +#' @param nuts_year A valid NUTS edition year. +#' @importFrom regions validate_geo_code +#' @family regions functions +#' @return A character list with the valid typology, or 'invalid' in the cases +#' when the geo coding is not valid. +#' @export +#' @examples +#' \donttest{ +#' my_reg_data <- data.frame( +#' geo = c( +#' "BE1", "HU102", "FR1", +#' "DED", "FR7", "TR", "DED2", +#' "EL", "XK", "GB" +#' ), +#' values = runif(10) +#' ) +#' +#' validate_geo_code(my_reg_data$geo) +#' } +regions::validate_geo_code diff --git a/R/search_eurostat.R b/R/search_eurostat.R index 6b34b918..ae439dbc 100755 --- a/R/search_eurostat.R +++ b/R/search_eurostat.R @@ -1,46 +1,85 @@ #' @title Grep Datasets Titles from Eurostat -#' @description Lists names of dataset from eurostat with the particular -#' pattern in the description. +#' @description Lists datasets from eurostat table of contents with the +#' particular pattern in item titles. #' @details Downloads list of all datasets available on #' eurostat and return list of names of datasets that contains particular #' pattern in the dataset description. E.g. all datasets related to -#' education of teaching. -#' @param pattern Character, datasets, folder or tables with this pattern in -#' the description will be returned (depending on the 'type' argument) -#' @param type Grep the Eurostat table of contents either for -#' 'dataset' (default), 'folder', 'table' or "all" (for all types). -#' @param fixed logical. If TRUE, pattern is a string to be matched as is. -#' Change to FALSE if more complex regex matching is needed. -#' @return A tibble with eight columns -#' \itemize{ -#' \item{title}{The name of dataset of theme} -#' \item{code}{The codename of dataset of theme, will be used by the get_eurostat and get_eurostat_raw functions.} -#' \item{type}{Is it a dataset, folder or table.} -#' \item{last.update.of.data, last.table.structure.change, data.start, data.end}{Dates.} -#' } -#' @export -#' @seealso \code{\link{get_eurostat}}, \code{\link{get_eurostat_toc}} -#' @references See citation("eurostat") -#' @author Przemyslaw Biecek and Leo Lahti \email{ropengov-forum@@googlegroups.com} -#' @examples \dontrun{ -#' tmp <- search_eurostat("education") -#' head(tmp) -#' # Use "fixed = TRUE" when pattern has characters that would need escaping. -#' # Here, parentheses would normally need to be escaped in regex -#' tmp <- search_eurostat("Live births (total) by NUTS 3 region", fixed = TRUE) +#' education of teaching. +#' +#' If you wish to perform searches on other fields than item title, +#' you can download the Eurostat Table of Contents manually using +#' `get_eurostat_toc()` function and use `grep()` function normally. The data +#' browser on Eurostat website may also return useful results. +#' @param pattern +#' Text string that is used to search from dataset, folder or table titles, +#' depending on the type argument. +#' @param type +#' Selection for types of datasets to be searched. Default is `dataset`, other +#' possible options are `table`, `folder` and `all` for all types. +#' @param column +#' Selection for the column of TOC where search is done. Default is `title`, +#' other possible option is `code`. +#' @param fixed +#' logical. If TRUE (default), pattern is a string to be matched as is. +#' See `grep()` documentation for more information. +#' @inheritParams get_eurostat +#' @inherit get_eurostat_toc return seealso +#' @inherit eurostat-package references +#' @inheritSection eurostat-package Data source: Eurostat Table of Contents +#' +#' @author Przemyslaw Biecek and Leo Lahti +#' +#' @examplesIf check_access_to_data() +#' \donttest{ +#' tmp <- search_eurostat("education") +#' head(tmp) +#' # Use "fixed = TRUE" when pattern has characters that would need escaping. +#' # Here, parentheses would normally need to be escaped in regex +#' tmp <- search_eurostat("Live births (total) by NUTS 3 region", fixed = TRUE) #' } +#' #' @keywords utilities database -search_eurostat <- function(pattern, type = "dataset", fixed = TRUE) { - set_eurostat_toc() - tmp <- get(".eurostatTOC", envir = .EurostatEnv) - if (type != "all") tmp <- tmp[ tmp$type %in% type, ] - tmp[ grep(tmp$title, pattern = pattern, fixed = fixed), ] -} +#' +#' @export +search_eurostat <- function(pattern, + type = "dataset", + column = "title", + fixed = TRUE, + lang = "en") { + # Sanity check + type <- tolower(as.character(type)) + column <- tolower(as.character(column)) + lang <- check_lang(lang) -#' @describeIn search_eurostat Old deprecated version -#' @export -grepEurostatTOC <- function(pattern, type = "dataset"){ - .Deprecated("search_eurostat") - search_eurostat(pattern = pattern, type = type) + if (!type %in% c("dataset", "table", "folder", "all")) { + warning(stringr::str_glue("The type \"{type}\" is not recognized, ", + "will return the search results using the ", + "default argument: type = \"dataset\".")) + type <- "dataset" + } + + if (!column %in% c("title", "code")) { + warning(stringr::str_glue("The column \"{column}\" is not recognized, ", + "will return the search results using the ", + "default argument: column = \"title\".")) + column <- "title" + } + + # Check if you have access to ec.europe.eu. + if (!check_access_to_data()) { + message("You have no access to ec.europe.eu. + Please check your connection and/or review your proxy settings") + return(invisible()) + } + + #set_eurostat_toc() + #tmp <- get(".eurostatTOC", envir = .EurostatEnv) + tmp <- get_eurostat_toc(lang = lang) + + + if (!identical(type, "all")) { + tmp <- tmp[tmp$type %in% type, ] + } + tmp <- tmp[grep(tmp[[column]], pattern = pattern, fixed = fixed), ] } diff --git a/R/set_eurostat_cache.R b/R/set_eurostat_cache.R new file mode 100644 index 00000000..eaf66c6e --- /dev/null +++ b/R/set_eurostat_cache.R @@ -0,0 +1,244 @@ +#' Set Eurostat Cache +#' +#' @description +#' This function will store your `cache_dir` path on your local machine +#' and would load it for future sessions. Type +#' `Sys.getenv("EUROSTAT_CACHE_DIR")` to +#' find your cached path. +#' +#' Alternatively, you can store the `cache_dir` manually with the following +#' options: +#' * Run `Sys.setenv(EUROSTAT_CACHE_DIR = "cache_dir")`. You +#' would need to run this command on each session +#' (Similar to `install = FALSE`). +#' * Set `options(eurostat_cache_dir = "cache_dir")`. Similar to +#' the previous option. This is provided for backwards compatibility +#' purposes. +#' * Write this line on your .Renviron file: +#' `EUROSTAT_CACHE_DIR = "value_for_cache_dir"` (same behavior than +#' `install = TRUE`). This would store your `cache_dir` +#' permanently. +#' +#' @param cache_dir A path to a cache directory. On missing value the function +#' would store the cached files on a temporary dir (See +#' [base::tempdir()]). +#' @param overwrite If this is set to `TRUE`, it will overwrite an existing +#' `EUROSTAT_CACHE_DIR` that you already have in local machine. +#' @param verbose Logical, displays information. Useful for debugging, +#' default is `FALSE`. +#' @param install if `TRUE`, will install the key in your local machine for +#' use in future sessions. Defaults to `FALSE`. If `cache_dir` is +#' `FALSE` this parameter is set to `FALSE` automatically. +#' +#' @family cache utilities +#' @seealso [rappdirs::user_config_dir()] +#' +#' @return An (invisible) character with the path to your `cache_dir`. +#' +#' @author Diego Hernangómez +#' @examples +#' +#' # Don't run this! It would modify your current state +#' \dontrun{ +#' set_eurostat_cache_dir(verbose = TRUE) +#' } +#' +#' Sys.getenv("EUROSTAT_CACHE_DIR") +#' @export +set_eurostat_cache_dir <- function(cache_dir, + overwrite = FALSE, + install = FALSE, + verbose = TRUE) { + + # nocov start + # Default if not provided + if (missing(cache_dir) || cache_dir == "") { + if (verbose) { + message( + "Using a temporary cache dir. ", + "Set 'cache_dir' to a value for store permanently" + ) + } + # Create a folder on tempdir + cache_dir <- file.path(tempdir(), "eurostat") + is_temp <- TRUE + install <- FALSE + } else { + is_temp <- FALSE + } + # nocov end + + cache_dir <- path.expand(cache_dir) + + + # Validate + stopifnot( + is.character(cache_dir), + is.logical(overwrite), + is.logical(install) + ) + + + # Create cache dir if it doesn't exists + if (!dir.exists(cache_dir)) { + dir.create(cache_dir, recursive = TRUE) + } + + if (verbose) { + message( + "eurostat cache dir is: ", + cache_dir + ) + } + + + # Install path on environ var. + + # nocov start + if (install) { + config_dir <- rappdirs::user_config_dir("eurostat", "R") + # Create cache dir if not presente + if (!dir.exists(config_dir)) { + dir.create(config_dir, recursive = TRUE) + } + + eurostat_file <- file.path(config_dir, "eurostat_cache_dir") + + if (!file.exists(eurostat_file) || overwrite == TRUE) { + # Create file if it doesn't exist + writeLines(cache_dir, con = eurostat_file) + } else { + stop( + "A cache_dir path already exists.\nYou can overwrite it with the ", + "argument overwrite = TRUE", + call. = FALSE + ) + } + # nocov end + } else { + if (verbose && !is_temp) { + message( + "To install your cache_dir path for use in future sessions,", + "\nrun this function with `install = TRUE`." + ) + } + } + + Sys.setenv(EUROSTAT_CACHE_DIR = cache_dir) + return(invisible(cache_dir)) +} + + +#' Detect cache dir for eurostat +#' +#' @noRd +eur_helper_detect_cache_dir <- function() { + + # Try from getenv + getvar <- Sys.getenv("EUROSTAT_CACHE_DIR") + + + # 1. Get from option - This is from backwards compatibility only + # nocov start + from_option <- getOption("eurostat_cache_dir", NULL) + + if (!is.null(from_option) && (is.null(getvar) || getvar == "")) { + cache_dir <- set_eurostat_cache_dir(from_option, install = FALSE) + return(cache_dir) + } + + + + + if (is.null(getvar) || is.na(getvar) || getvar == "") { + # Not set - tries to retrieve from cache + cache_config <- file.path( + rappdirs::user_config_dir("eurostat", "R"), + "EUROSTAT_CACHE_DIR" + ) + + if (file.exists(cache_config)) { + cached_path <- readLines(cache_config) + + # Case on empty cached path - would default + if (is.null(cached_path) || is.na(cached_path) || cached_path == "") { + cache_dir <- set_eurostat_cache_dir(overwrite = TRUE, verbose = FALSE) + return(cache_dir) + } + + # 3. Return from cached path + Sys.setenv(EUROSTAT_CACHE_DIR = cached_path) + return(cached_path) + } else { + # 4. Default cache location + + cache_dir <- set_eurostat_cache_dir( + overwrite = TRUE, + verbose = FALSE + ) + return(cache_dir) + } + } else { + return(getvar) + } + # nocov end +} + +#' Creates `cache_dir` +#' +#' +#' @noRd +eur_helper_cachedir <- function(cache_dir = NULL) { + # Check cache dir from options if not set + if (is.null(cache_dir)) { + cache_dir <- eur_helper_detect_cache_dir() + } + + # Reevaluate + if (is.null(cache_dir)) { + cache_dir <- file.path(tempdir(), "eurostat") + } + + # Create cache dir if needed + if (isFALSE(dir.exists(cache_dir))) { + dir.create(cache_dir, recursive = TRUE) + } + return(cache_dir) +} + +#' Output cache information as data.frame +#' @description +#' Parses cache_list.json file and returns a data.frame +#' @return +#' A data.frame object with 3 columns: dataset code, download date and +#' query md5 hash +#' +#' @inheritParams get_eurostat +#' @importFrom jsonlite fromJSON +#' @export +list_eurostat_cache_items <- function(cache_dir = NULL) { + if (is.null(cache_dir)) { + cache_dir <- eur_helper_detect_cache_dir() + } + + path <- paste0(cache_dir, "/cache_list.json") + + if (!file.exists(path)) { + warning("No cache_list.json file found!") + return(invisible()) + } + + json_file <- jsonlite::fromJSON(path) + # return(json_file) + columns <- c("code", "download_date", "query_md5_hash") + df <- data.frame(matrix(nrow = 0, ncol = length(columns))) + for (i in seq_len(length(json_file))) { + df_i <- data.frame( + code = json_file[[i]][["id"]], + download_date = json_file[[i]][["download_date"]], + query_md5_hash = names(json_file[i]) + ) + df <- rbind(df, df_i) + } + df +} \ No newline at end of file diff --git a/R/set_eurostat_toc.R b/R/set_eurostat_toc.R index fa9c7908..bf1b58b2 100755 --- a/R/set_eurostat_toc.R +++ b/R/set_eurostat_toc.R @@ -1,20 +1,213 @@ #' @title Set Eurostat TOC #' @description Internal function. -#' @param ... Arguments to be passed +#' @inheritParams get_eurostat #' @return Empty element #' @references see citation("eurostat") -#' @author Przemyslaw Biecek and Leo Lahti \email{ropengov-forum@@googlegroups.com} +#' @author Przemyslaw Biecek and Leo Lahti +#' +#' @importFrom readr read_tsv cols col_character +#' @importFrom stringr str_glue +#' +#' @seealso [get_eurostat_toc()] [toc_count_children()] [toc_determine_hierarchy()] +#' [toc_list_children()] [toc_count_whitespace()] +#' #' @keywords internal -set_eurostat_toc <- function(...) { - if (!exists(".eurostatTOC", envir = .EurostatEnv)) { - base <- getOption("eurostat_url") - url <- paste(base, "estat-navtree-portlet-prod/", - "BulkDownloadListing?sort=1&downfile=table_of_contents_en.txt", - sep = "") - .eurostatTOC <- readr::read_tsv(url(url), - col_types = readr::cols(.default = readr::col_character())) - - assign(".eurostatTOC", .eurostatTOC, envir = .EurostatEnv) +set_eurostat_toc <- function(lang = "en") { + lang <- check_lang(lang) + + language_version <- switch(lang, + en = ".eurostatTOC", + fr = ".eurostatTOC_fr", + de = ".eurostatTOC_de") + + if (!exists(language_version, envir = .EurostatEnv)) { + base <- getOption("eurostat_url") + url <- stringr::str_glue( + paste0(base, "api/dissemination/catalogue/toc/txt?lang={lang}") + ) + + .eurostatTOC <- readr::read_tsv( + file = url(url), + col_types = readr::cols(.default = readr::col_character()), + name_repair = make.names, + trim_ws = FALSE + ) + + .eurostatTOC$hierarchy <- toc_determine_hierarchy(.eurostatTOC$title) + .eurostatTOC$title <- trimws(.eurostatTOC$title, which = "left") + .eurostatTOC$values <- as.numeric(.eurostatTOC$values) + + assign(language_version, .eurostatTOC, envir = .EurostatEnv) } invisible(0) } + +#' @title Count white space at the start of the title +#' @description Counts the number of white space characters at the start +#' of the string. +#' @inherit toc_determine_hierarchy details +#' @inheritParams toc_determine_hierarchy +#' @return Numeric (number of white space characters) +#' @importFrom stringr str_extract +#' @examples +#' strings <- c(" abc", " cdf", "no_spaces") +#' for (string in strings) { +#' whitespace_count <- eurostat:::toc_count_whitespace(string) +#' cat("String:", string, "\tWhitespace Count:", whitespace_count, "\n") +#' } +#' +#' @inherit set_eurostat_toc seealso +#' +#' @author Pyry Kantanen +#' +#' @keywords internal +toc_count_whitespace <- function(input_string) { + # Counts white space chars \s before encountering the 1st non-ws char \S + pattern <- "^\\s*(?=\\S)" + extracted_ws <- stringr::str_extract(input_string, pattern) + + nchar(extracted_ws) +} + +#' @title Determine level in hierarchy +#' @description Divides the number of spaces before alphanumeric characters +#' with 4 and uses the result to determine hierarchy. Top level is 0. +#' @details Used in toc_determine_hierarchy function to determine hierarchy. +#' Hierarchy is defined in Eurostat .txt format TOC files by the number of +#' white space characters at intervals of four. For example, +#' " Foo" (4 white space characters) is one level higher than +#' " Bar" (8 white space characters). +#' "Database by themes" (0 white space characters before the first +#' alphanumeric character) is highest in the hierarchy. +#' +#' The function will return a warning if the input has white space in anything +#' else than as increments of 4. 0, 4, 8... are acceptable but 3, 6, 10... +#' are not. +#' @param input_string +#' A string containing Eurostat TOC titles +#' @return Numeric +#' @examples +#' strings <- c(" abc", " cdf", "no_spaces") +#' eurostat:::toc_determine_hierarchy(strings) +#' +#' @inherit set_eurostat_toc seealso +#' +#' @author Pyry Kantanen +#' +#' @keywords internal +toc_determine_hierarchy <- function(input_string) { + number_of_whitespace <- toc_count_whitespace(input_string) + + # If all x mod y calculations equal 0 everything is ok. + # If not, input is somehow mangled + # For example " General and regional statistics" (4 whitespace) returns 1 + # whereas " " (12 whitespace without any letters) returns also 1 + # Normally all dataset items are expected to have a title to determine + # their place in hierarchy. Testing for this might be a bit tricky. + if (!all((number_of_whitespace %% 4) %in% c(0))) { + warning( + paste( + "TOC indentation was not uniform in all rows or there were some", + "items that were missing a proper title. Hierarchy value set to NA", + "for problematic rows." + ) + ) + invalid_rows <- which(!(number_of_whitespace %% 4) %in% c(0)) + # return(invisible()) + hierarchy <- number_of_whitespace %/% 4 + hierarchy[invalid_rows] <- NA + return(hierarchy) + } + + # If white space is 0, it gets number 0 in hierarchy + hierarchy <- number_of_whitespace %/% 4 + hierarchy + # Or should it be 1? + # (number_of_whitespace %/% 4) + 1 +} + +#' @title Count number of children +#' @description +#' Determine how many children a certain TOC item (usually a folder) has. +#' @param code Eurostat TOC item code (folder, dataset, table) +#' +#' @importFrom stringr str_glue +#' +#' @inherit set_eurostat_toc seealso +#' +#' @author Pyry Kantanen +#' +#' @keywords internal +#' +toc_count_children <- function(code) { + toc <- get_eurostat_toc() + + # Line number for hit + initial_pos <- which(toc$code == code) + + if (length(initial_pos) > 1) { + warning(stringr::str_glue( + "Unambiguous code input: \"{code}\". ", + "TOC contains multiple items with the same code.")) + return(invisible()) + } + + initial_hierarchy <- toc$hierarchy[initial_pos] + i <- initial_pos + 1 + num_children <- 0 + + while (toc$hierarchy[i] > initial_hierarchy) { + # Check for the 1st iteration: If the next item is of the same hierarchy + # break the while loop and determine that the number of children is 0 + if (toc$hierarchy[i] == initial_hierarchy && num_children == 0) { + num_children <- 0 + break + } + num_children <- i - initial_pos + i <- i + 1 + } + num_children +} + +#' @title List children +#' @description +#' List children of a specific folder. +#' @inheritParams toc_count_children +#' +#' @importFrom stringr str_glue +#' +#' @inherit set_eurostat_toc seealso +#' +#' @author Pyry Kantanen +#' +#' @keywords internal +#' +toc_list_children <- function(code) { + toc <- get_eurostat_toc() + # Line number for hit + initial_pos <- which(toc$code == code) + + if (length(initial_pos) > 1) { + warning(stringr::str_glue( + "Unambiguous code input: \"{code}\". ", + "TOC contains multiple items with the same code.")) + return(invisible()) + } + + final_pos <- initial_pos + toc_count_children(code) + + if (final_pos == initial_pos) { + initial_pos_type <- toc$type[initial_pos] + message(stringr::str_glue( + "The TOC item with code \"{code}\" (type: {initial_pos_type}) ", + "does not have any children. Please use another code.") + ) + return(invisible()) + } + + # Add 1 to omit root folder + initial_pos <- initial_pos + 1 + + children <- toc[initial_pos:final_pos, ] + children +} diff --git a/R/sysdata.rda b/R/sysdata.rda new file mode 100644 index 00000000..689c70af Binary files /dev/null and b/R/sysdata.rda differ diff --git a/R/tidy_eurostat.R b/R/tidy_eurostat.R index 815d8d74..ee3e9aa9 100755 --- a/R/tidy_eurostat.R +++ b/R/tidy_eurostat.R @@ -1,139 +1,251 @@ #' @title Transform Data into Row-Column-Value Format -#' @description Transform raw Eurostat data table into the row-column-value -#' format (RCV). -#' @param dat a data_frame from \code{\link{get_eurostat_raw}}. -#' @param time_format a string giving a type of the conversion of the -#' time column from the eurostat format. -#' A "date" (default) convers to a \code{\link{Date}} -#' with a first date of the period. A "date_last" -#' convers to a \code{\link{Date}} with -#' a last date of the period. A "num" convers to a numeric and "raw" -#' does not do conversion. See \code{\link{eurotime2date}} and -#' \code{\link{eurotime2num}}. -#' @param select_time a character symbol for a time frequence or NULL -#' (default). -#' @param stringsAsFactors if \code{TRUE} (the default) variables are -#' converted to factors in original Eurostat order. If \code{FALSE} -#' they are returned as strings. -#' @param keepFlags a logical whether the flags (e.g. "confidential", -#' "provisional") should be kept in a separate column or if they -#' can be removed. Default is \code{FALSE} -#' @return tibble in the molten format with the last column 'values'. -#' @seealso \code{\link{get_eurostat}} -#' @references See citation("eurostat"). -#' @author Przemyslaw Biecek, Leo Lahti and Janne Huovari \email{ropengov-forum@@googlegroups.com} \url{http://github.com/ropengov/eurostat} +#' @description Transform raw Eurostat data table downloaded from the +#' API into a tidy row-column-value format (RCV). +#' @param dat +#' a data_frame from [get_eurostat_raw()]. +#' @inheritParams get_eurostat +#' @return tibble in the melted format with the last column 'values'. +#' @seealso [get_eurostat()], [convert_time_col()], [eurotime2date()] +#' @inherit eurostat-package references +#' @author Przemyslaw Biecek, Leo Lahti, Janne Huovari and Pyry Kantanen +#' +#' @importFrom stringi stri_extract_first_regex stri_replace_all_regex +#' @importFrom stringi stri_replace_all_fixed +#' @importFrom tidyr separate pivot_longer +#' @importFrom dplyr filter +#' @importFrom data.table setDT melt .SD := +#' @importFrom stats na.omit +#' +#' @examples +#' \dontrun{ +#' # Example of a dataset with multiple time series +#' get_eurostat("AVIA_GOR_ME", +#' time_format = "date_last", +#' cache = F +#' ) +#' } +#' #' @keywords internal utilities database -tidy_eurostat <- function(dat, time_format = "date", select_time = NULL, - stringsAsFactors = default.stringsAsFactors(), - keepFlags = FALSE) { +tidy_eurostat <- function(dat, + time_format = "date", + select_time = NULL, + stringsAsFactors = FALSE, + keepFlags = FALSE, + use.data.table = FALSE) { - # To avoid warnings - time <- values <- NULL + # To avoid warnings + TIME_PERIOD <- values <- NULL - # Separate codes to columns - cnames <- strsplit(colnames(dat)[1], split = "[\\,]")[[1]] - cnames1 <- cnames[-length(cnames)] # for columns - cnames2 <- cnames[length(cnames)] # for colnames - - # Separe variables from first column - dat <- tidyr::separate_(dat, col = colnames(dat)[1], - into = cnames1, - sep = ",", convert = FALSE) + # Separate codes to columns + cnames <- strsplit(colnames(dat)[1], split = "[\\,]")[[1]] + cnames1 <- cnames[-length(cnames)] # for columns + cnames2 <- cnames[length(cnames)] # for colnames + + # Separate variables from first column + # OLD CODE + dat <- tidyr::separate(dat, + col = colnames(dat)[1], + into = cnames1, + sep = ",", + convert = FALSE + ) + if (!use.data.table) { # Get variable from column names - - cnames2_quo <- as.name(cnames2) - dat <- tidyr::gather(dat, !!cnames2_quo, values, - -seq_along(cnames1), - convert = FALSE) + # OLD CODE + dat <- tidyr::pivot_longer(data = dat, + cols = -seq_along(cnames1), + names_to = cnames2, + values_to = "values") # to save memory (and backward compatibility) + # OLD CODE dat <- dplyr::filter(dat, !is.na(values)) ## separate flags into separate column - if(keepFlags == TRUE) { + if (keepFlags == TRUE) { dat$flags <- as.vector( - stringi::stri_extract_first_regex(dat$values, - c("(^0n( [A-Za-z]+)*)|[A-Za-z]+"))) + stringi::stri_extract_first_regex( + dat$values, + c("(^0n( [A-Za-z]+)*)|[A-Za-z]+") + ) + ) } # clean time and values - dat$time <- gsub("X", "", dat$time) + # OLD CODE + dat$TIME_PERIOD <- gsub("X", "", dat$TIME_PERIOD, fixed = TRUE) dat$values <- as.numeric(gsub("[^0-9.-]+", "", as.character(dat$values))) - + # variable columns - var_cols <- names(dat)[!(names(dat) %in% c("time", "values"))] + var_cols <- names(dat)[!(names(dat) %in% c("TIME_PERIOD", "values"))] # reorder to standard order - dat <- dat[c(var_cols, "time", "values")] + # OLD CODE + dat <- dat[c(var_cols, "TIME_PERIOD", "values")] # columns from var_cols are converted into factors # avoid convert = FALSE since it converts T into TRUE instead of TOTAL - if (stringsAsFactors){ - dat[,var_cols] <- lapply(dat[, var_cols, drop = FALSE], - function(x) factor(x, levels = unique(x))) + if (stringsAsFactors) { + dat[, var_cols] <- lapply( + dat[, var_cols, drop = FALSE], + function(x) factor(x, levels = unique(x)) + ) } - - # For multiple time frequency - freqs <- available_freq(dat$time) + } else if (use.data.table) { + # NEW CODE: data.table + # defining dat as data.table object is necessary to use data.table functions + # dat <- data.table::as.data.table(dat) + # Coerce data.frame to data.table by reference + data.table::setDT(dat) - if (!is.null(select_time)){ - if (length(select_time) > 1) stop( - "Only one frequency should be selected in select_time. Selected: ", - shQuote(select_time)) - - # Annual - if (select_time == "Y"){ - dat <- subset(dat, nchar(time) == 4) - # Others - } else { - dat <- subset(dat, grepl(select_time, time)) - } - # Test if data - if (nrow(dat) == 0) stop( - "No data selected with select_time:", dQuote(select_time), "\n", - "Available frequencies: ", shQuote(freqs)) - } else { - - if (length(freqs) > 1 & time_format != "raw") stop( - "Data includes several time frequencies. Select frequency with - select_time or use time_format = \"raw\". - Available frequencies: ", shQuote(freqs )) + # Use factors by default to reduce RAM use (?) + dat[, (cnames1) := lapply(.SD, as.factor), .SDcols = cnames1] + + # NEW CODE: data.table + # Use pipe to reduce RAM use (?) + dat <- data.table::melt(data = dat, + measure.vars = setdiff(names(dat), cnames1), + variable.name = cnames2, + value.name = "values") %>% + na.omit(cols = "values") + + # NEW CODE: data.table + # should be using S3 method for data.table here... + # Problem has been with "vector memory exhausted (limit reached?)" + # dat <- na.omit(object = dat, cols = "values") + + ## separate flags into separate column + # Use data.table update := for smaller RAM footprint + if (keepFlags == TRUE) { + dat[, `:=`(flags = as.vector( + stringi::stri_extract_first_regex(values, c("(^0n( [A-Za-z]+)*)|[A-Za-z]+")) + ))] + } + + # clean time and values + # NEW CODE: use stringi instead of gsub for faster execution + # Use data.table update := for smaller RAM footprint + dat[, TIME_PERIOD := stringi::stri_replace_all_fixed(TIME_PERIOD, "X", "")] + # dat$TIME_PERIOD <- stringi::stri_replace_all_fixed(dat$TIME_PERIOD, "X", "") + dat[, values := stringi::stri_replace_all_regex(values, "[^0-9.-]+", "")] + dat[, values := as.numeric(values)] + # dat$values <- as.numeric( + # stringi::stri_replace_all_regex(as.character(dat$values), "[^0-9.-]+", "") + # ) + + # variable columns + # cnames1 is the same as var_cols so cnames1 is used + # var_cols <- names(dat)[!(names(dat) %in% c("TIME_PERIOD", "values"))] + # selected_cols <- c(var_cols, "TIME_PERIOD", "values") + + # reorder to standard order + # NEW CODE: data.table + # either this way + # dat <- dat[, ..selected_cols] + # or this way + # reorder to standard order + data.table::setcolorder(dat, c(cnames1, "TIME_PERIOD", "values")) + + # Turn factors back into characters if stringsAsFactors = FALSE + # columns from cnames1 (var_cols) are converted into factors + if (!stringsAsFactors) { + dat[, (cnames1) := lapply(.SD, as.character), .SDcols = cnames1] } - # convert time column - dat$time <- convert_time_col(dat$time, - time_format = time_format) + dat <- tibble::as_tibble(dat) + } + # For multiple time frequency + freqs <- unique(dat$freq) + if (!is.null(select_time)) { + if (length(select_time) > 1) { + message( + "Selected multiple time frequencies with select_time parameter: ", + shQuote(select_time) + ) + } - dat + # Filter dataset according to select_time filter + # This only works when a single frequency is chosen + if (identical(select_time, "Y")) { + # Annual with old style notation, "Y" for annual + dat <- subset(dat, dat$freq == "A") + } else if (identical(select_time, "A")) { + # Annual with new notation, "A" for annual + dat <- subset(dat, dat$freq == "A") + } else { + # Others, subset the data with whatever choices + dat <- subset(dat, dat$freq %in% select_time) + } + # Test if filtered dataset actually contains any data + if (nrow(dat) == 0) { + stop( + "No data selected with select_time:", dQuote(select_time), "\n", + "Available frequencies: ", shQuote(freqs) + ) + } + } else { + if (length(freqs) > 1 && time_format != "raw") { + message( + "Data includes several time frequencies. Select a single frequency \n", + "with select_time or use time_format = \"raw\" to return all data \n", + "without any filtering. Available frequencies: ", shQuote(freqs), "\n", + "Returning the dataset with multiple frequencies." + ) + } + } + + if (length(select_time) > 1) { + dat_copy <- data.frame() + for (i in seq_along(select_time)) { + dat_subset <- subset(dat, dat$freq == select_time[i]) + dat_subset$TIME_PERIOD <- convert_time_col(x = dat_subset$TIME_PERIOD, + time_format = time_format) + dat_copy <- rbind(dat_copy, dat_subset) + } + dat <- dat_copy + } else { + # convert time column to Date + dat$TIME_PERIOD <- convert_time_col(x = dat$TIME_PERIOD, + time_format = time_format) + } + + # NEW CODE: data.table + # This is needed if we still want to return tibbles at the end + # dat <- tibble::as_tibble(dat) + dat } -#' @title Time Column Conversions -#' @description Internal function to convert time column. -#' @param x A time column (vector) -#' @param time_format see \code{\link{tidy_eurostat}} +#' @title +#' Time Column Conversions for data from new dissemination API +#' @description +#' Internal function to convert time column. +#' @param x +#' A time column (vector) from a downloaded dataset +#' @param time_format +#' one of the following: `date`, `date_last`, or `num`. +#' See [tidy_eurostat()] for more information. #' @keywords internal -convert_time_col <- function(x, time_format){ - - if (time_format == "raw"){ +convert_time_col <- function(x, time_format) { + if (time_format == "raw") { y <- x } else { x <- factor(x) - if (time_format == "date"){ + if (time_format == "date") { y <- eurotime2date(x, last = FALSE) - } else if (time_format == "date_last"){ + } else if (time_format == "date_last") { y <- eurotime2date(x, last = TRUE) - } else if (time_format == "num"){ + } else if (time_format == "num") { y <- eurotime2num(x) - } else if (time_format == "raw") { - } else { - stop("An unknown time_format argument: ", time_format, - " Allowed are date, date_last, num and raw") + stop( + "An unknown time_format argument: ", time_format, + " Allowed are date, date_last, num and raw" + ) } } y diff --git a/R/utils.R b/R/utils.R index e22063c7..71b323c9 100755 --- a/R/utils.R +++ b/R/utils.R @@ -2,13 +2,107 @@ # Should not be exported # Return vector of available frequencies # param x a vector of "raw" time variable -available_freq <- function(x){ +available_freq <- function(x) { if (is.factor(x)) x <- levels(x) x <- gsub("X", "", x) freq <- c() if (any(nchar(x) == 4)) freq <- c(freq, "Y") freq_char <- unique( - substr(grep("[[:alpha:]]", x, value = TRUE), 5,5)) + substr(grep("[[:alpha:]]", x, value = TRUE), 5, 5) + ) freq <- c(freq, freq_char) freq -} \ No newline at end of file +} + +## load a eurostat package data without causing binding errors +## controlled loading in functions without loading the data +## to the global environment + +load_package_data <- function(dataset) { + .new_data_environment <- new.env(parent = emptyenv()) # a new environment + + if (!exists(x = dataset, envir = .new_data_environment)) { + utils::data( + list = dataset, + package = "eurostat", + envir = .new_data_environment + ) + } + .new_data_environment[[dataset]] +} + +check_lang <- function(lang) { + if (!is.null(lang)) { + # The Language parameter (“lang”) can have only three values: + # "en" (English), "fr" (French), and "de" (German). + lang <- tolower(lang) + if (lang %in% c("en", "fr", "de")) { + return(lang) + } else { + message( + "Unsupported language code used. Using the default language: \"en\"" + ) + lang <- "en" + } + } else { + # In case the parameter isn’t specified, the default value "en" is taken. + message("Using the default language: \"en\"") + lang <- "en" + } + lang +} + +#' @title Calculate a fixity checksum for an object +#' @description +#' Uses a hash function (md5) on an object and calculates a digest of the object +#' in the form of a character string. +#' +#' @details +#' “Fixity, in the preservation sense, means the assurance that a digital file +#' has remained unchanged, i.e. fixed.” (Bailey, 2014). In practice, fixity +#' can most easily be established by calculating a checksum for the data object +#' that changes if anything in the data object has changed. What we use as a +#' checksum here is by default calculated with md5 hash algorithm. It is +#' possible to use other algorithms supported by the imported digest function, +#' see function documentation. +#' +#' In the case of big objects with millions of rows of data calculating a +#' checksum can take a bit longer and require some amount of RAM to be +#' available. Selecting another algorithm might perform faster and/or more +#' efficiently. Whichever algorithm you are using, please make sure to report +#' it transparently in your work for transparency and ensuring replicability. +#' +#' This function takes the whole data object as an input, meaning that +#' everything counts when calculating the fixity checksum. If the dataset +#' column names are labeled, if the data itself is labeled, if stringsAsFactors +#' is TRUE, if flags are removed or kept, if data is somehow edited... all these +#' affect the calculated checksum. It is advisable to calculate the checksum +#' immediately after downloading the data, before adding any labels or doing +#' other mutating operations. If you are using other arguments than the default +#' ones when downloading data, it is also good to report the exact arguments +#' used. +#' +#' This implementation fulfills the level 1 requirement of National Digital +#' Stewardship Alliance (NDSA) preservation levels by creating "fixity info +#' if it wasn’t provided with the content". In the current version of the +#' package, fixity information has to be created manually and is at the +#' responsibility of the user. +#' +#' @param data_object A dataset downloaded with some eurostat package function. +#' @param algorithm Algorithm to use when calculating a checksum for a dataset. +#' Default is 'md5', but can be any supported algorithm in digest function. +#' +#' @seealso [digest::digest()] +#' @source https://www.dpconline.org/handbook/technical-solutions-and-tools/fixity-and-checksums +#' @importFrom digest digest +#' @keywords internal utilities +fixity_checksum <- function(data_object, algorithm = "md5") { + if (!(algorithm %in% c("md5", "sha1", "crc32", "sha256", "sha512", + "xxhash32", "xxhash64", "murmur32", "spookyhash", + "blake3", "crc32c"))) { + stop("Use a valid algorithm. See digest::digest function documentation") + } + + fixity <- digest::digest(data_object, algo = algorithm) + fixity +} diff --git a/R/zzz.R b/R/zzz.R index 2fabc867..b72f1bdc 100755 --- a/R/zzz.R +++ b/R/zzz.R @@ -1,10 +1,10 @@ .onLoad <- function(libname, pkgname) { - op <- options() - op.eurostat <- list( - eurostat_url = "https://ec.europa.eu/eurostat/" - ) - # Only set options that are not already set - toset <- !(names(op.eurostat) %in% names(op)) - if (any(toset)) options(op.eurostat[toset]) - invisible() + op <- options() + op.eurostat <- list( + eurostat_url = "https://ec.europa.eu/eurostat/" + ) + # Only set options that are not already set + toset <- !(names(op.eurostat) %in% names(op)) + if (any(toset)) options(op.eurostat[toset]) + invisible() } diff --git a/README.Rmd b/README.Rmd index 94b01248..33ff09ff 100755 --- a/README.Rmd +++ b/README.Rmd @@ -1,9 +1,8 @@ --- -output: - html_document: - keep_md: yes +output: github_document --- + ```{r, echo = FALSE} knitr::opts_chunk$set( @@ -13,42 +12,87 @@ knitr::opts_chunk$set( ) ``` -
- - - - - -[![Build Status](https://travis-ci.org/rOpenGov/eurostat.svg?branch=master)](https://travis-ci.org/rOpenGov/eurostat) -[![AppVeyor Status](https://ci.appveyor.com/api/projects/status/github/rOpenGov/eurostat?branch=master&svg=true)](https://ci.appveyor.com/project/rOpenGov/eurostat) -[![codecov.io](https://codecov.io/github/rOpenGov/eurostat/coverage.svg?branch=master)](https://codecov.io/github/rOpenGov/eurostat?branch=master) + +[![rOG-badge](https://ropengov.github.io/rogtemplate/reference/figures/ropengov-badge.svg)](https://ropengov.org/) +[![R-CMD-check](https://github.com/rOpenGov/eurostat/actions/workflows/check-full.yaml/badge.svg)](https://github.com/rOpenGov/eurostat/actions/workflows/check-full.yaml) +[![R-CMD-check (standard)](https://github.com/rOpenGov/eurostat/actions/workflows/check-standard.yaml/badge.svg)](https://github.com/rOpenGov/eurostat/actions/workflows/check-standard.yaml) +[![cran version](http://www.r-pkg.org/badges/version/eurostat)](https://CRAN.R-project.org/package=eurostat) +[![lifecycle](https://img.shields.io/badge/lifecycle-stable-brightgreen.svg)](https://lifecycle.r-lib.org/articles/stages.html#stable-1) +[![DOI](https://img.shields.io/badge/DOI-10.32614/RJ--2017--019-blue)](https://doi.org/10.32614/RJ-2017-019) +[![codecov](https://codecov.io/gh/rOpenGov/eurostat/branch/master/graph/badge.svg?token=Wp2VVvpWQA)](https://app.codecov.io/gh/rOpenGov/eurostat) [![Downloads](http://cranlogs.r-pkg.org/badges/grand-total/eurostat)](https://cran.r-project.org/package=eurostat) [![Downloads](http://cranlogs.r-pkg.org/badges/eurostat)](https://cran.r-project.org/package=eurostat) -[![Gitter](https://badges.gitter.im/rOpenGov/eurostat.svg)](https://gitter.im/rOpenGov/eurostat?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) +[![Gitter](https://badges.gitter.im/rOpenGov/eurostat.svg)](https://app.gitter.im/#/room/#rOpenGov_eurostat:gitter.im?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) +[![r-universe](https://ropengov.r-universe.dev/badges/eurostat)](https://ropengov.r-universe.dev/) + [![Watch on GitHub][github-watch-badge]][github-watch] [![Star on GitHub][github-star-badge]][github-star] -[![Follow](https://img.shields.io/twitter/follow/ropengov.svg?style=social)](https://twitter.com/intent/follow?screen_name=ropengov) - +[![Follow](https://img.shields.io/twitter/follow/ropengov.svg?style=social)](https://twitter.com/ropengov) + + + + + + - - -
+ -# eurostat R package +# eurostat R package - - -R tools to access open data from [Eurostat](http://ec.europa.eu/eurostat). Data search, download, manipulation and visualization. +R tools to access open data from [Eurostat](https://ec.europa.eu/eurostat). Data search, download, manipulation and visualization. ### Installation and use -See the [package homepage](http://ropengov.github.io/eurostat) for more. +Install stable version from CRAN: + +```{r, eval = FALSE} +install.packages("eurostat") +``` + +Alternatively, install development version from GitHub: + +```{r, eval = FALSE} +# Install from GitHub +library(devtools) +devtools::install_github("ropengov/eurostat") +``` + +Development version can be also installed using the +[r-universe](https://ropengov.r-universe.dev): + +```{r, eval=FALSE} +# Enable this universe +options(repos = c( + ropengov = "https://ropengov.r-universe.dev", + CRAN = "https://cloud.r-project.org" +)) + +install.packages("eurostat") +``` + +The package provides several different ways to get datasets from Eurostat. Searching for data is one way, if you know what to look for. + +```{r example, eval = TRUE} +# Load the package +library(eurostat) + +# Perform a simple search and print a table +passengers <- search_eurostat("passenger transport") +knitr::kable(head(passengers)) +``` + + +See the [Tutorial](https://ropengov.github.io/eurostat/articles/articles/eurostat_tutorial.html) and other resources at the [package homepage](https://ropengov.github.io/eurostat/) for more information and examples. + +### Recommended packages + +It is recommended to install the `giscoR` package (https://dieghernan.github.io/giscoR/). This is another API package that provides R tools for Eurostat geographic data to support geospatial analysis and visualization. ### Contribute @@ -57,43 +101,35 @@ Contributions are very welcome: * [Use issue tracker](https://github.com/ropengov/eurostat/issues) for feedback and bug reports. * [Send pull requests](https://github.com/ropengov/eurostat/) - * [Star us on the Github page](https://github.com/ropengov/eurostat) - * [Join the discussion in Gitter](https://gitter.im/rOpenGov/eurostat) + * [Star us on the Github page](https://github.com/ropengov/eurostat/) + * [Join the discussion in Gitter](https://app.gitter.im/#/room/#rOpenGov_eurostat:gitter.im) ### Acknowledgements -**Kindly cite this work** as follows: [Leo Lahti](https://github.com/antagomir), Przemyslaw Biecek, Markus Kainu and Janne Huovari. Retrieval and analysis of Eurostat open data with the eurostat package. [R Journal 9(1):385-392, 2017](https://journal.r-project.org/archive/2017/RJ-2017-019/index.html). R package version `r sessionInfo()$otherPkgs$eurostat$Version`. URL: [http://ropengov.github.io/eurostat](http://ropengov.github.io/eurostat) +**Kindly cite this package** by citing the following R Journal article: -We are greatful to all [contributors](https://github.com/rOpenGov/eurostat/graphs/contributors), including Joona Lehtomäki, Francois Briatte, and Oliver Reiter, and for the [Eurostat](http://ec.europa.eu/eurostat/) open data portal! This project is part of [rOpenGov](http://ropengov.github.io). +[Lahti L.](https://github.com/antagomir), Huovari J., Kainu M., and Biecek P. (2017). Retrieval and analysis of Eurostat open data with the eurostat package. [The R Journal 9(1), pp. 385-392](https://journal.r-project.org/archive/2017/RJ-2017-019/index.html). doi: [10.32614/RJ-2017-019](https://doi.org/10.32614/RJ-2017-019). +In addition, please provide a citation to the specific software version used: +Lahti, L., Huovari J., Kainu M., Biecek P., Hernangomez D., Antal D., and Kantanen P. (2023). eurostat: Tools for Eurostat Open Data [Computer software]. R package version 4.0.0.9003. https://github.com/rOpenGov/eurostat + +We are grateful to all [contributors](https://github.com/ropengov/eurostat/graphs/contributors), including Daniel Antal, Joona Lehtomäki, Francois Briatte, and Oliver Reiter, and for the [Eurostat](https://ec.europa.eu/eurostat/) open data portal! This project is part of [rOpenGov](https://ropengov.org). + +This project has received funding from the European Union under grant No 101095295 (OpenMUSE), the FIN-CLARIAH research infrastructure and the Strategic Research Council's YOUNG program by the Research Council of Finland (decisions 345630, 358720, 367756, 352604). ### Disclaimer This package is in no way officially related to or endorsed by Eurostat. +When using data retrieved from Eurostat database in your work, please indicate that the data source is Eurostat. If your re-use involves some kind of modification to data or text, please state this clearly to the end user. See Eurostat policy on [copyright and free re-use of data](https://ec.europa.eu/eurostat/about/policies/copyright) for more detailed information and certain exceptions. -[chat-badge]: https://img.shields.io/badge/chat-on%20gitter-46BC99.svg?style=flat-square -[chat]: https://gitter.im/ropengov/eurostat?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge -[build-badge]: https://img.shields.io/travis/ropengov/eurostat.svg?style=flat-square -[build]: https://travis-ci.org/ropengov/eurostat -[version-badge]: https://img.shields.io/npm/v/eurostat.svg?style=flat-square -[package]: https://www.npmjs.com/package/eurostat [license-badge]: https://img.shields.io/npm/l/eurostat.svg?style=flat-square [license]: https://github.com/ropengov/eurostat/blob/master/LICENSE -[prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square -[prs]: http://makeapullrequest.com -[donate-badge]: https://img.shields.io/badge/$-support-green.svg?style=flat-square -[donate]: http://kcd.im/donate -[coc-badge]: https://img.shields.io/badge/code%20of-conduct-ff69b4.svg?style=flat-square -[coc]: https://github.com/ropengov/eurostat/blob/master/other/CODE_OF_CONDUCT.md -[implementations-badge]: https://img.shields.io/badge/%F0%9F%92%A1-implementations-8C8E93.svg?style=flat-square -[implementations]: https://github.com/ropengov/eurostat/blob/master/other/IMPLEMENTATIONS.md + [github-watch-badge]: https://img.shields.io/github/watchers/ropengov/eurostat.svg?style=social [github-watch]: https://github.com/ropengov/eurostat/watchers [github-star-badge]: https://img.shields.io/github/stars/ropengov/eurostat.svg?style=social [github-star]: https://github.com/ropengov/eurostat/stargazers -[twitter]: https://twitter.com/intent/tweet?text=Check%20out%20eurostat!%20%E2%9C%A8%20Recognize%20all%20contributors,%20not%20just%20the%20ones%20who%20commit%20code%20%E2%9C%A8%20https://github.com/ropengov/eurostat%20%F0%9F%A4%97 -[twitter-badge]: https://img.shields.io/twitter/url/https/github.com/ropengov/eurostat.svg?style=social -[emojis]: https://github.com/ropengov/eurostat#emoji-key -[eurostat]: https://github.com/ropengov/eurostat + +[eurostat]: https://github.com/ropengov/eurostat/ diff --git a/README.md b/README.md old mode 100755 new mode 100644 index 236549d0..db0aa2e0 --- a/README.md +++ b/README.md @@ -1,93 +1,152 @@ ---- -output: - html_document: - keep_md: yes ---- - - + + + +[![rOG-badge](https://ropengov.github.io/rogtemplate/reference/figures/ropengov-badge.svg)](https://ropengov.org/) +[![R-CMD-check](https://github.com/rOpenGov/eurostat/actions/workflows/check-full.yaml/badge.svg)](https://github.com/rOpenGov/eurostat/actions/workflows/check-full.yaml) +[![R-CMD-check +(standard)](https://github.com/rOpenGov/eurostat/actions/workflows/check-standard.yaml/badge.svg)](https://github.com/rOpenGov/eurostat/actions/workflows/check-standard.yaml) +[![cran +version](http://www.r-pkg.org/badges/version/eurostat)](https://CRAN.R-project.org/package=eurostat) +[![lifecycle](https://img.shields.io/badge/lifecycle-stable-brightgreen.svg)](https://lifecycle.r-lib.org/articles/stages.html#stable-1) +[![DOI](https://img.shields.io/badge/DOI-10.32614/RJ--2017--019-blue)](https://doi.org/10.32614/RJ-2017-019) +[![codecov](https://codecov.io/gh/rOpenGov/eurostat/branch/master/graph/badge.svg?token=Wp2VVvpWQA)](https://app.codecov.io/gh/rOpenGov/eurostat) +[![Downloads](http://cranlogs.r-pkg.org/badges/grand-total/eurostat)](https://cran.r-project.org/package=eurostat) +[![Downloads](http://cranlogs.r-pkg.org/badges/eurostat)](https://cran.r-project.org/package=eurostat) +[![Gitter](https://badges.gitter.im/rOpenGov/eurostat.svg)](https://app.gitter.im/#/room/#rOpenGov_eurostat:gitter.im?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) +[![r-universe](https://ropengov.r-universe.dev/badges/eurostat)](https://ropengov.r-universe.dev/) -
+[![Watch on +GitHub](https://img.shields.io/github/watchers/ropengov/eurostat.svg?style=social)](https://github.com/ropengov/eurostat/watchers) +[![Star on +GitHub](https://img.shields.io/github/stars/ropengov/eurostat.svg?style=social)](https://github.com/ropengov/eurostat/stargazers) +[![Follow](https://img.shields.io/twitter/follow/ropengov.svg?style=social)](https://twitter.com/ropengov) + + -[![Build Status](https://travis-ci.org/rOpenGov/eurostat.svg?branch=master)](https://travis-ci.org/rOpenGov/eurostat) -[![AppVeyor Status](https://ci.appveyor.com/api/projects/status/github/rOpenGov/eurostat?branch=master&svg=true)](https://ci.appveyor.com/project/rOpenGov/eurostat) -[![codecov.io](https://codecov.io/github/rOpenGov/eurostat/coverage.svg?branch=master)](https://codecov.io/github/rOpenGov/eurostat?branch=master) -[![Downloads](http://cranlogs.r-pkg.org/badges/grand-total/eurostat)](https://cran.r-project.org/package=eurostat) -[![Downloads](http://cranlogs.r-pkg.org/badges/eurostat)](https://cran.r-project.org/package=eurostat) -[![Gitter](https://badges.gitter.im/rOpenGov/eurostat.svg)](https://gitter.im/rOpenGov/eurostat?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) -[![Watch on GitHub][github-watch-badge]][github-watch] -[![Star on GitHub][github-star-badge]][github-star] -[![Follow](https://img.shields.io/twitter/follow/ropengov.svg?style=social)](https://twitter.com/intent/follow?screen_name=ropengov) - - - - + -
+# eurostat R package -# eurostat R package +R tools to access open data from +[Eurostat](https://ec.europa.eu/eurostat). Data search, download, +manipulation and visualization. - +### Installation and use -R tools to access open data from [Eurostat](http://ec.europa.eu/eurostat). Data search, download, manipulation and visualization. +Install stable version from CRAN: +``` r +install.packages("eurostat") +``` -### Installation and use +Alternatively, install development version from GitHub: + +``` r +# Install from GitHub +library(devtools) +devtools::install_github("ropengov/eurostat") +``` + +Development version can be also installed using the +[r-universe](https://ropengov.r-universe.dev): + +``` r +# Enable this universe +options(repos = c( + ropengov = "https://ropengov.r-universe.dev", + CRAN = "https://cloud.r-project.org" +)) + +install.packages("eurostat") +``` + +The package provides several different ways to get datasets from +Eurostat. Searching for data is one way, if you know what to look for. + +``` r +# Load the package +library(eurostat) -See the [package homepage](http://ropengov.github.io/eurostat) for more. +# Perform a simple search and print a table +passengers <- search_eurostat("passenger transport") +knitr::kable(head(passengers)) +``` +| title | code | type | last.update.of.data | last.table.structure.change | data.start | data.end | values | hierarchy | +|:---------------------------------------------------------------------------------------------|:-----------------|:--------|:--------------------|:----------------------------|:-----------|:---------|--------:|----------:| +| Air passenger transport | enps_avia_pa | dataset | 13.03.2023 | 13.03.2023 | 2005 | 2021 | 406 | 6 | +| Modal split of air, sea and inland passenger transport | tran_hv_ms_psmod | dataset | 29.06.2023 | 29.06.2023 | 2008 | 2021 | 2100 | 4 | +| Modal split of inland passenger transport | tran_hv_psmod | dataset | 29.06.2023 | 29.06.2023 | 1990 | 2021 | 4219 | 4 | +| Volume of passenger transport relative to GDP | tran_hv_pstra | dataset | 11.08.2023 | 29.06.2023 | 1990 | 2021 | 969 | 4 | +| Maritime passenger transport performed in the Exclusive Economic Zone (EEZ) of the countries | mar_tp_pa | dataset | 21.02.2023 | 21.02.2023 | 2005 | 2021 | 1752 | 4 | +| Air passenger transport by reporting country | avia_paoc | dataset | 04.12.2023 | 28.11.2023 | 1993 | 2023-Q3 | 2482969 | 5 | + +See the +[Tutorial](https://ropengov.github.io/eurostat/articles/articles/eurostat_tutorial.html) +and other resources at the [package +homepage](https://ropengov.github.io/eurostat/) for more information and +examples. + +### Recommended packages + +It is recommended to install the `giscoR` package +(). This is another API package +that provides R tools for Eurostat geographic data to support geospatial +analysis and visualization. ### Contribute Contributions are very welcome: - * [Use issue tracker](https://github.com/ropengov/eurostat/issues) for feedback and bug reports. - * [Send pull requests](https://github.com/ropengov/eurostat/) - * [Star us on the Github page](https://github.com/ropengov/eurostat) - * [Join the discussion in Gitter](https://gitter.im/rOpenGov/eurostat) +- [Use issue tracker](https://github.com/ropengov/eurostat/issues) for + feedback and bug reports. +- [Send pull requests](https://github.com/ropengov/eurostat/) +- [Star us on the Github page](https://github.com/ropengov/eurostat/) +- [Join the discussion in + Gitter](https://app.gitter.im/#/room/#rOpenGov_eurostat:gitter.im) ### Acknowledgements -**Kindly cite this work** as follows: [Leo Lahti](https://github.com/antagomir), Przemyslaw Biecek, Markus Kainu and Janne Huovari. Retrieval and analysis of Eurostat open data with the eurostat package. [R Journal 9(1):385-392, 2017](https://journal.r-project.org/archive/2017/RJ-2017-019/index.html). R package version 3.2.93. URL: [http://ropengov.github.io/eurostat](http://ropengov.github.io/eurostat) +**Kindly cite this package** by citing the following R Journal article: -We are greatful to all [contributors](https://github.com/rOpenGov/eurostat/graphs/contributors), including Joona Lehtomäki, Francois Briatte, and Oliver Reiter, and for the [Eurostat](http://ec.europa.eu/eurostat/) open data portal! This project is part of [rOpenGov](http://ropengov.github.io). +[Lahti L.](https://github.com/antagomir), Huovari J., Kainu M., and +Biecek P. (2017). Retrieval and analysis of Eurostat open data with the +eurostat package. [The R Journal 9(1), +pp. 385-392](https://journal.r-project.org/archive/2017/RJ-2017-019/index.html). +doi: [10.32614/RJ-2017-019](https://doi.org/10.32614/RJ-2017-019). +In addition, please provide a citation to the specific software version +used: +Lahti, L., Huovari J., Kainu M., Biecek P., Hernangomez D., Antal D., +and Kantanen P. (2023). eurostat: Tools for Eurostat Open Data +\[Computer software\]. R package version 4.0.0.9003. + + +We are grateful to all +[contributors](https://github.com/ropengov/eurostat/graphs/contributors), +including Daniel Antal, Joona Lehtomäki, Francois Briatte, and Oliver +Reiter, and for the [Eurostat](https://ec.europa.eu/eurostat/) open data +portal! This project is part of [rOpenGov](https://ropengov.org). + +This project has received funding from the European Union under grant No 101095295 (OpenMUSE), the FIN-CLARIAH research infrastructure and the Strategic Research Council's YOUNG program by the Research Council of Finland (decisions 345630, 358720, 367756, 352604). ### Disclaimer This package is in no way officially related to or endorsed by Eurostat. - -[chat-badge]: https://img.shields.io/badge/chat-on%20gitter-46BC99.svg?style=flat-square -[chat]: https://gitter.im/ropengov/eurostat?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge -[build-badge]: https://img.shields.io/travis/ropengov/eurostat.svg?style=flat-square -[build]: https://travis-ci.org/ropengov/eurostat -[version-badge]: https://img.shields.io/npm/v/eurostat.svg?style=flat-square -[package]: https://www.npmjs.com/package/eurostat -[license-badge]: https://img.shields.io/npm/l/eurostat.svg?style=flat-square -[license]: https://github.com/ropengov/eurostat/blob/master/LICENSE -[prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square -[prs]: http://makeapullrequest.com -[donate-badge]: https://img.shields.io/badge/$-support-green.svg?style=flat-square -[donate]: http://kcd.im/donate -[coc-badge]: https://img.shields.io/badge/code%20of-conduct-ff69b4.svg?style=flat-square -[coc]: https://github.com/ropengov/eurostat/blob/master/other/CODE_OF_CONDUCT.md -[implementations-badge]: https://img.shields.io/badge/%F0%9F%92%A1-implementations-8C8E93.svg?style=flat-square -[implementations]: https://github.com/ropengov/eurostat/blob/master/other/IMPLEMENTATIONS.md -[github-watch-badge]: https://img.shields.io/github/watchers/ropengov/eurostat.svg?style=social -[github-watch]: https://github.com/ropengov/eurostat/watchers -[github-star-badge]: https://img.shields.io/github/stars/ropengov/eurostat.svg?style=social -[github-star]: https://github.com/ropengov/eurostat/stargazers -[twitter]: https://twitter.com/intent/tweet?text=Check%20out%20eurostat!%20%E2%9C%A8%20Recognize%20all%20contributors,%20not%20just%20the%20ones%20who%20commit%20code%20%E2%9C%A8%20https://github.com/ropengov/eurostat%20%F0%9F%A4%97 -[twitter-badge]: https://img.shields.io/twitter/url/https/github.com/ropengov/eurostat.svg?style=social -[emojis]: https://github.com/ropengov/eurostat#emoji-key -[eurostat]: https://github.com/ropengov/eurostat +When using data retrieved from Eurostat database in your work, please +indicate that the data source is Eurostat. If your re-use involves some +kind of modification to data or text, please state this clearly to the +end user. See Eurostat policy on [copyright and free re-use of +data](https://ec.europa.eu/eurostat/about/policies/copyright) for more +detailed information and certain exceptions. diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100755 index e32d316c..00000000 --- a/appveyor.yml +++ /dev/null @@ -1,42 +0,0 @@ -# DO NOT CHANGE the "init" and "install" sections below - -# Download script file from GitHub -init: - ps: | - $ErrorActionPreference = "Stop" - Invoke-WebRequest http://raw.github.com/krlmlr/r-appveyor/master/scripts/appveyor-tool.ps1 -OutFile "..\appveyor-tool.ps1" - Import-Module '..\appveyor-tool.ps1' - -install: - ps: Bootstrap - -# Adapt as necessary starting from here - -build_script: - - travis-tool.sh install_deps - -test_script: - - travis-tool.sh run_tests - -on_failure: - - 7z a failure.zip *.Rcheck\* - - appveyor PushArtifact failure.zip - -artifacts: - - path: '*.Rcheck\**\*.log' - name: Logs - - - path: '*.Rcheck\**\*.out' - name: Logs - - - path: '*.Rcheck\**\*.fail' - name: Logs - - - path: '*.Rcheck\**\*.Rout' - name: Logs - - - path: '\*_*.tar.gz' - name: Bits - - - path: '\*_*.zip' - name: Bits diff --git a/cran-comments.md b/cran-comments.md old mode 100755 new mode 100644 index 50c6b450..5eef97f9 --- a/cran-comments.md +++ b/cran-comments.md @@ -1,24 +1,21 @@ -## Test environments -* local OS X install, R 3.3.1 -* ubuntu 12.04 (on travis-ci), R 3.3.1 -* win-builder (devel and release) - ## R CMD check results -0 errors | 0 warnings | 1 note +On R 4.2.2 under aarch64-apple-darwin20 (64-bit), macOS Ventura 13.2.1 -* This is a new release. +0 errors | 0 warnings | 1 note -## Reverse dependencies +* checking for future file timestamps ... NOTE + unable to verify current time + +Seems to be a problem related to worldclockapi.com, that has already been discussed in 2019 on r-package-devel mailing list. -To be checked. +On R 2023-02-21 r83888 ucrt under x86_64-w64-mingw32 (64-bit), Windows Server 2022 x64 (devtools::check_win_devel): ---- +0 errors | 0 warnings | 0 notes -* I have run R CMD check on the NUMBER downstream dependencies. - (Summary at ...). - -* FAILURE SUMMARY +## Downstream dependencies -* All revdep maintainers were notified of the release on RELEASE DATE. +We checked 8 reverse dependencies with revdepcheck, comparing R CMD check results across CRAN and dev versions of this package. + * We saw 0 new problems + * We failed to check 0 packages diff --git a/data-raw/country_list.R b/data-raw/country_list.R index fa1b1835..31efcbb5 100755 --- a/data-raw/country_list.R +++ b/data-raw/country_list.R @@ -1,4 +1,3 @@ - # Code to get countries and their codes for selected country groups. library(rvest) @@ -7,30 +6,44 @@ library(devtools) load_all() country_html <- read_html("http://ec.europa.eu/eurostat/statistics-explained/index.php/Tutorial:Country_codes_and_protocol_order") -c_tables<- country_html %>% +c_tables <- country_html %>% html_table() # Country data.tables with code and name -eu_countries <- c_tables[[2]] %>% - select(code = Code, name = English) - -efta_countries <- c_tables[[3]] %>% - select(code = Code, name = English) - -eu_candidate_countries <- c_tables[[4]] %>% - select(code = Code, name = English) +# Codes, names and protocol order of European Union (EU) Member States +eu_countries <- c_tables[[2]] %>% + select(code = Code, name = English) %>% + mutate(label = eurostat::label_eurostat(code, dic = "geo")) + +# Codes and names of EFTA countries +efta_countries <- c_tables[[3]] %>% + select(code = Code, name = English) %>% + mutate(label = eurostat::label_eurostat(code, dic = "geo")) + +# United Kingdom +united_kingdom <- c_tables[[4]] %>% + select(code = Code, name = English) %>% + mutate(label = eurostat::label_eurostat(code, dic = "geo")) + +# Codes and names of candidate countries +eu_candidate_countries <- c_tables[[5]] %>% + select(code = Code, name = English) %>% + mutate(label = eurostat::label_eurostat(code, dic = "geo")) # Euro area countries ea_country_html <- read_html("http://ec.europa.eu/eurostat/statistics-explained/index.php/Glossary:Euro_area") ea_countries <- ea_country_html %>% - html_table(fill = TRUE) %>% - unlist() %>% - {data_frame(name = grep("^[[:alpha:]]", ., value = TRUE))} %>% - inner_join(eu_countries, .) # Get eu order and codes - + html_table(fill = TRUE) %>% + unlist() %>% + { + tibble(name = grep("^[[:alpha:]]", ., value = TRUE)) + } %>% + inner_join(eu_countries, .) %>% # Get eu order and codes + mutate(label = eurostat::label_eurostat(code, dic = "geo")) + # Eurostat data set with ID tgs00026 -tgs00026 <- get_eurostat("tgs00026", time_format = "raw") +tgs00026 <- get_eurostat("tgs00026", time_format = "raw") print("save datasets") -devtools::use_data(eu_candidate_countries, eu_countries, ea_countries, efta_countries, tgs00026, overwrite = TRUE, internal = FALSE) +usethis::use_data(eu_candidate_countries, eu_countries, ea_countries, efta_countries, tgs00026, overwrite = TRUE, internal = FALSE) diff --git a/data-raw/eurostat_geodata_60_2016.R b/data-raw/eurostat_geodata_60_2016.R new file mode 100644 index 00000000..46f0254f --- /dev/null +++ b/data-raw/eurostat_geodata_60_2016.R @@ -0,0 +1,35 @@ +## code to prepare `eurostat_geodata_60_2016` dataset goes here +library(giscoR) +library(tidyverse) + +# Current names internal) +from_gisco <- gisco_get_nuts( + year = 2016, resolution = 60, + epsg = 4326, update_cache = TRUE, + verbose = TRUE +) + +from_gisco$geo <- from_gisco$NUTS_ID +from_gisco$id <- from_gisco$NUTS_ID + +# End + +eurostat_geodata_60_2016 <- from_gisco +unique(sf::st_is_valid(from_gisco)) + +# Sort by level and alphabetically +eurostat_geodata_60_2016 <- eurostat_geodata_60_2016 %>% + arrange(LEVL_CODE, NUTS_ID) + +# Arrange names in proper order +sfcol <- attr(eurostat_geodata_60_2016, "sf_column") +rest <- c( + "id", "LEVL_CODE", "NUTS_ID", "CNTR_CODE", "NAME_LATN", + "NUTS_NAME", "MOUNT_TYPE", "URBN_TYPE", "COAST_TYPE", + "FID", "geo" +) + +reorder <- intersect(unique(c(rest, sfcol)), names(eurostat_geodata_60_2016)) +eurostat_geodata_60_2016 <- eurostat_geodata_60_2016[, reorder] + +usethis::use_data(eurostat_geodata_60_2016, overwrite = TRUE, compress = "xz") diff --git a/data-raw/nuts_coding.R b/data-raw/nuts_coding.R new file mode 100755 index 00000000..80803208 --- /dev/null +++ b/data-raw/nuts_coding.R @@ -0,0 +1,193 @@ +library(readxl) +library(purrr) +library(dplyr) +library(tidyr) +# This file reads in the NUTS correspondence table published by +# Eurostat --------------------------------------------------- + +tf <- tempfile(fileext = ".xlsx") +download.file( + url = "https://ec.europa.eu/eurostat/documents/345175/629341/NUTS2013-NUTS2016.xlsx", + destfile = tf, mode = "wb" +) + +regional_changes_2016 <- readxl::read_excel(tf, + sheet = "NUTS2013-NUTS2016", + skip = 1, col_names = TRUE +) %>% + select(1:12) %>% + purrr::set_names(., c( + "rowid", "code13", "code16", + "country_name", "nuts1_name", + "nuts2_name", "nuts3_name", + "change", "nuts_level", + "sort_countries", "sort_13", "sort_16" + )) %>% + mutate(name = case_when( + !is.na(nuts1_name) ~ nuts1_name, + !is.na(nuts2_name) ~ nuts2_name, + !is.na(nuts3_name) ~ nuts3_name, + !is.na(country_name) ~ country_name, + TRUE ~ NA_character_ + )) + +nuts1_correspondence <- readxl::read_excel( + tf, + sheet = "Correspondence NUTS-1", + skip = 0, col_names = TRUE +) %>% + purrr::set_names(., c( + "code13", "code16", + "name", + "change", "resolution" + )) %>% + mutate_if(is.factor, as.character) %>% + mutate(nuts_level = 1) %>% + filter(name != "Centre-Est") # appears to be a duplicate and incorrect row, given that FR7 is also marked as recoded to FRK + +warning("FR7 - Centre-Est appears to be an errorneous line and it is removed from the correspondence table.") + +nuts2_correspondence <- readxl::read_excel( + tf, + sheet = "Correspondence NUTS-2", + skip = 0, col_names = TRUE +) %>% + select(1:5) %>% + purrr::set_names(., c( + "code13", "code16", + "name", + "change", "resolution" + )) %>% + filter(is.na(code13) + is.na(code16) < 2) %>% + mutate(nuts_level = 2) + +nuts3_correspondence <- readxl::read_excel( + tf, + sheet = "Correspondence NUTS-3", + skip = 0, col_names = TRUE +) %>% + select(1:5) %>% + purrr::set_names(., c( + "code13", "code16", + "name", + "change", "resolution" + )) %>% + filter(is.na(code13) + is.na(code16) < 2) %>% + mutate(nuts_level = 2) + + +nuts_correspondence <- rbind( + nuts1_correspondence, + nuts2_correspondence +) %>% + rbind(nuts3_correspondence) %>% + select(code13, code16, name, nuts_level, change, resolution) + +nuts_2016_codes <- unique(regional_changes_2016$code16) + +## In these cases, the code13 == code16 ------------------------------ +unchanged_regions <- regions %>% + filter(is.na(change)) %>% + fill(nuts1_name) %>% + fill(nuts2_name) %>% + select(code13, code16, name, nuts_level, change) %>% + mutate(change = "unchanged") + +## In these cases code13 != code16 ---------------------------------- +changed_regions <- regions %>% + filter(!is.na(change)) %>% + fill(nuts1_name) %>% + fill(nuts2_name) %>% + select(code13, code16, name, nuts_level, change) + +nuts_2016_codes <- unique(regional_changes_2016$code16)[!is.na(regional_changes_2016$code16)] +nuts_2013_codes <- unique(regional_changes_2016$code13)[!is.na(regional_changes_2016$code13)] +all_region_codes <- unique(c(nuts_2016_codes, nuts_2013_codes)) + +changed_region_codes <- all_region_codes[!all_region_codes %in% unchanged_regions$code16] +changed_region_codes <- sort(changed_region_codes[!is.na(changed_region_codes)]) + +regions_in_correspondence <- unique(c(nuts_correspondence$code13, nuts_correspondence$code16)) +regions_in_correspondence <- sort(regions_in_correspondence[!is.na(regions_in_correspondence)]) + +if (length( + changed_region_codes[!changed_region_codes %in% regions_in_correspondence] +) > 0) { + message("Problem with the following regional geo labels:") + message(changed_region_codes[!changed_region_codes %in% regions_in_correspondence]) + stop("They cannot be found in the correspondence table") +} + + +## Consistency check ---------------------------------------- +## The name field is inconsistent in two sheets, at least FR7 is not consistent +regions_in_correspondence <- regions_in_correspondence[!is.na(regions_in_correspondence)] + +nuts2013_in_changed <- unique(changed_regions$code13) +nuts2013_in_changed <- nuts2013_in_changed[!is.na(nuts2013_in_changed)] + +nuts2016_in_changed <- unique(changed_regions$code16) +nuts2016_in_changed <- nuts2016_in_changed[!is.na(nuts2016_in_changed)] + +all(nuts2013_in_changed %in% regions_in_correspondence) +all(nuts2016_in_changed %in% regions_in_correspondence) + +nuts2013_in_changed[!nuts2013_in_changed %in% regions_in_correspondence] +nuts2016_in_changed[!nuts2016_in_changed %in% regions_in_correspondence] + +## Consistency II ---------------------------------------------------- + +all_nuts_codes <- unique(c(nuts_2013_codes, nuts_2016_codes)) + +only_in_correspondence <- regions_in_correspondence[regions_in_correspondence %in% all_nuts_codes] + +only_13 <- nuts_correspondence %>% + filter(code13 %in% only_in_correspondence) + +only_16 <- nuts_correspondence %>% + filter(code16 %in% only_in_correspondence) + +only <- full_join(only_13, only_16) # they are unique + + +## Changed regions to be looked up by their NUTS2016 codes ----------- +regional_changes_by_2016 <- nuts_correspondence %>% + mutate(geo = code16) %>% + filter(!is.na(code16)) + +## adding those that have no equivalent in the previous group +## some regions have to be identified by their old and new codes ----- +regional_changes_by_2013 <- nuts_correspondence %>% + mutate(geo = code13) %>% + filter(!is.na(code13)) + +## Region can be found by new or old NUTS code ----------------------- + +all_regional_changes <- regional_changes_by_2016 %>% + full_join(regional_changes_by_2013, + by = c( + "code13", "code16", "name", "nuts_level", + "change", "resolution", "geo" + ) + ) + + +all_regional_changes %>% + add_count(code13, code16, name, nuts_level, change, resolution, geo) %>% + filter(n > 1) + +## Regional changes ------------------------------------------------ + +regional_changes_2016 <- rbind(changed_regions, unchanged_regions) + +discontinued_regions <- changed_regions %>% + filter(change == "discontinued") + + +## ---------------------------------------------------------------- +message("Save changed regions") +usethis::use_data(regional_changes_2016, + nuts_correspondence, + overwrite = TRUE, + internal = FALSE +) diff --git a/data-raw/nuts_correction.R b/data-raw/nuts_correction.R new file mode 100755 index 00000000..c0fac5f5 --- /dev/null +++ b/data-raw/nuts_correction.R @@ -0,0 +1,419 @@ +library(tidyverse) + +## Check for non-unique elements in nuts_correction.R + +check_dat_input <- function(dat) { + incorrect <- FALSE + if (!"geo" %in% names(dat)) correct <- TRUE + incorrect +} + +check_unique_values <- function(df) { + if ("corrected_values" %in% names(df)) { + df <- df %>% + rename(values = corrected_values) + } + + df <- df %>% + select(geo, indicator, time) %>% + add_count(geo, indicator, time) + + if (any(df$n) > 1) { + return(TRUE) + } else { + return(FALSE) + } +} + + +regdata_files <- dir("regdata")[!grepl("rest_of_ceemid", dir("regdata"))] +regdata_files <- regdata_files[grepl(".rds", regdata_files)] +regdata_files <- regdata_files[!grepl("corrected", regdata_files)] +regdata_files + +for (test in regdata_files) { + message("Testing ", test) + readRDS(file.path("regdata", test)) +} + +message("All regional data files read, none was corrupted on disk.") +source(file.path("R", "nuts_coding.R")) + +dat <- eurostat::tgs00026 %>% + check_nuts2013() + +correct_nuts_labelling <- function(dat) { + + ## Check if geo information is present ------------------------------ + if (check_dat_input(dat)) { + stop("There is no 'geo' column in the inserted data. This is an error.") + } + + + if (!"change" %in% names(dat)) { + dat <- check_nuts2013(dat) + } + unchanged_regions <- regional_changes_2016 %>% + filter(change == "unchanged") + + changed_regions <- regional_changes_2016 %>% + filter(change != "unchanged") + + nuts_2016_codes <- unique(regional_changes_2016$code16) + # for easier debugging, this data will be re-assigned in each major + # step as tmp2, tmp3... Debugging is particulary difficult, because + # not only the program code, but the underlying logic may have faults. + + tmp_eu_only <- tmp %>% + filter(change != "not_eu") # leave out non-EU regions. + + # Find those codes that are missing from the correct NUTS2016 codes + missing_2016_codes <- nuts_2016_codes[which(!nuts_2016_codes %in% tmp_eu_only$geo)] + missing_2016_codes <- missing_2016_codes[which(stringr::str_sub(missing_2016_codes, -3, -1) != "ZZZ")] + missing_2016_codes <- missing_2016_codes[which(stringr::str_sub(missing_2016_codes, -2, -1) != "ZZ")] + + # Sort them out by NUTS1 and NUTS2 levels + missing_nuts1_2016 <- missing_2016_codes[which(nchar(missing_2016_codes) == 3)] + missing_nuts2_2016 <- missing_2016_codes[which(nchar(missing_2016_codes) == 4)] + + # Separating labels that need to be corrected into tmp3 ---------------- + + correctly_labelled_unchanged <- tmp %>% + filter(change == "unchanged") + + tmp_changed <- tmp %>% + filter(change != "unchanged") + + correctly_labelled_changed <- tmp_changed %>% + filter(geo %in% changed_regions$code16) + + ## Finding incorrectly labelled NUTS1 geo labels -------------------- + incorrectlly_labelled_nuts1 <- tmp_changed %>% + filter(geo %in% changed_regions$code13) + + incorrectly_labelled_nuts1_2013 <- incorrectlly_labelled_nuts1 %>% + filter(nchar(as.character(geo)) == 3) %>% + select(-change) %>% + left_join(nuts_correspondence %>% + filter(nuts_level == 1) %>% + rename(geo = code13) %>% + filter(!is.na(geo)) %>% + select(geo, code16, change, resolution), + by = "geo" + ) %>% + filter(change != "discontinued") %>% + mutate(problem_code = geo) %>% + mutate(geo = code16) + + + ## NUTS1 labels that are missing and which are found ------------------ + nuts1_missings <- missing_nuts1_2016[which(missing_nuts1_2016 %in% incorrectly_labelled_nuts1_2013$geo)] + + found_nuts1 <- incorrectly_labelled_nuts1_2013 %>% + filter(geo %in% missing_nuts1_2016) + message(length(unique(found_nuts1$geo)), " incorrectly labelled NUTS1 regions could be re-labelled") + + ## Finding incorrectly labelled NUTS2 geo labels -------------------- + + incorrectly_labelled_nuts2_2013 <- incorrectlly_labelled_nuts13 %>% + filter(nchar(as.character(geo)) == 4) %>% + select(-change) %>% + left_join(nuts_correspondence %>% + filter(nuts_level == 2) %>% + rename(geo = code13) %>% + filter(!is.na(geo)) %>% + select(geo, code16, change, resolution), + by = "geo" + ) %>% + filter(change != "discontinued") %>% + mutate(problem_code = geo) %>% + mutate(geo = code16) + + recoded_nuts2_2013 <- incorrectly_labelled_nuts2_2013 %>% + filter(change == "recoded") + + found_nuts2 <- recoded_nuts2_2013 %>% + filter(geo %in% missing_nuts2_2016) + + message(length(unique(found_nuts2$geo)), " incorrectly labelled NUTS2 regions could be re-labelled.") + + ## If there are no corrections to made at all, return the original data frame ------------ + if (length(unique(found_nuts2$geo)) + length(unique(found_nuts1$geo)) == 0) { + message("There is no data found that can be further arranged.\nThe data is returned in its original format.") + return(dat) + } + + ## If there are changes to be made, make them from here ------------------ + join_by <- names(correctly_labelled_unchanged) + join_by <- join_by[which(join_by %in% names(correctly_labelled_changed))] + + join_by2 <- names(correctly_labelled_unchanged) + join_by2 <- join_by2[which(join_by2 %in% names(found_nuts1))] + + ## Add unchanged regions and changed, but correctly labelled ones + so_far_joined <- full_join(correctly_labelled_unchanged, + correctly_labelled_changed, + by = join_by + ) %>% + full_join(found_nuts1, by = join_by2) + + ## Add NUTS1 regions that were recoded, if there are any + if (nrow(found_nuts1) > 0) { + join_by3 <- names(so_far_joined) + join_by3 <- join_by3[which(join_by3 %in% names(found_nuts1))] + + so_far_joined <- so_far_joined %>% + full_join(found_nuts2, by = join_by3) + } + + + ## Add NUTS2 regions that were recoded, if there are any + if (nrow(found_nuts2) > 0) { + join_by4 <- names(so_far_joined) + join_by4 <- join_by3[which(join_by4 %in% names(found_nuts2))] + + so_far_joined <- so_far_joined %>% + full_join(found_nuts2, by = join_by4) + } + + + remaining_eu_data <- tmp %>% + filter(!geo %in% so_far_joined$geo) + + ## The following geo codes will be changed using rules ------------- + used_in_correction <- c( + "FR24", + "FR26", "FR43", + "FR23", "FR25", + "FR22", "FR30", + "FR21", "FR41", "FR42", + "FR51", + "FR52", + "FR53", "FR61", "FR63", + "FR62", "FR81", + "FR7", + "FR82", + "FR83", + "FRA", + "PL11", "PL33", + "PL3", + "PL12", + "IE023", "IE024", "IE025", + "LT00", "LT00A", + "UKM2", + "UKM31", "UKM34", "UKM35", "UKM36", + "UKM24", "UKM32", "UKM33", "UKM37", "UKM38", + "HU102", "HU101" + ) + + correct_with_correspondence <- remaining_eu_data %>% + select(time, country_code, years, indicator, geo, values) + + if (any(correct_with_correspondence$geo %in% so_far_joined$geo)) { + stop("There are overlaps with the already corrected dataset") + } + + if (check_unique_values(correct_with_correspondence)) { + stop("There were joining errors, please check correct_with_correspondence") + } + + ## The data has time and space dimension, so corrections have to be + ## made for each year in the dataset---------------------------- + correspondence_by_year <- function(df, this_time) { + df <- df %>% filter(time == this_time) + + complete_with_missing <- tibble( + geo = used_in_correction[which(!unique(used_in_correction) %in% df$geo)], + country_code = case_when( + substr(geo, 1, 2) == "UK" ~ "GB", + substr(geo, 1, 2) == "EL" ~ "GR", + TRUE ~ substr(geo, 1, 2) + ), + values = NA_real_, + indicator = NA_character_, + time = this_time, + years = as.numeric(substr(as.character(this_time), 1, 4)) + ) + + correct_with_correspondence <- df %>% + full_join(., complete_with_missing, + by = c( + "indicator", "geo", "values", "years", + "time", "country_code" + ) + ) %>% + fill(indicator) %>% + spread(geo, values) %>% + mutate( + FRB = FR24, + FRC = FR26 + FR43, + FRD = FR23 + FR25, + FRE = FR22 + FR30, + FRF = FR21 + FR41 + FR42, + FRG = FR51, + FRH = FR52, + FRI = FR53 + FR61 + FR63, + FRJ = FR62 + FR81, + FRK = FR7, + FRL = FR82, + FRM = FR83, + FRY = FRA, + LT02 = LT00 - LT00A, + UKM7 = UKM2 - UKM24, + UKM8 = UKM31 + UKM34 + UKM35 + UKM36, + UKM9 = UKM24 + UKM32 + UKM33 + UKM37 + UKM38, + PL7 = PL11 + PL33, + PL8 = PL3 - PL33, + PL9 = PL12, + IE05 = IE023 + IE024 + IE025, + HU11 = HU101, + HU12 = HU102 + ) %>% + gather(geo, corrected_values, -one_of("indicator", "country_code", "time", "years")) %>% + filter(!is.na(corrected_values)) %>% + filter(geo %in% c(missing_nuts1_2016, missing_nuts2_2016)) + + correct_with_correspondence + } + + for (t in seq_along(unique(correct_with_correspondence$time))) { + this_time <- unique(correct_with_correspondence$time)[t] + to_correct_by_year <- correct_with_correspondence %>% + filter(time == this_time) + if (t == 1) { + corrected_with_correspondence <- correspondence_by_year(to_correct_by_year, this_time) + } else { + tmp <- correspondence_by_year(to_correct_by_year, + this_time = this_time + ) + if (is.null(tmp)) next + if (!nrow(tmp) == 0) { + corrected_with_correspondence <- full_join( + corrected_with_correspondence, tmp, + by = c( + "time", "country_code", "years", "indicator", + "geo", "corrected_values" + ) + ) + } + } # end of else + } # end of loop + + check_unique_values(corrected_with_correspondence) + + incorrectly_labelled_unknown <- tmp3 %>% + filter(!geo %in% c(changed_regions$code16, changed_regions$code13)) + + if (nrow(incorrectly_labelled_unknown) > 0) { + message("The following labels do not conform the NUTS2016 definition: ", paste( + unique(incorrectly_labelled_unknown$geo), + collapse = "," + )) + warning("Unknown labels found") + } + + check_unique_values(so_far_joined) + + ### If there are duplications, they look like this + dups <- so_far_joined %>% + mutate(change = ifelse(is.na(change), "NA", change)) %>% + select(geo, time, indicator, values, change) %>% + add_count(geo, time, indicator) %>% + filter(n > 1) %>% + spread(change, values) + ## If everything works well, you have two identical values vector, the + ## original Eurostat values and the recoded values. + + names(corrected_with_correspondence) + + corrected_dataset <- so_far_joined %>% + full_join(corrected_with_correspondence, + by = c("geo", "time", "country_code", "years", "indicator") + ) %>% + fill(-one_of(c( + "geo", "time", "country_code", "years", "country", + "indicator", "change", "code16", "resolution", + "problem_code", "corrected_values", "values" + ))) %>% + add_count(geo, time, indicator) + + duplications <- corrected_dataset %>% + filter(n > 1) + + if (any(corrected_dataset$n > 1)) { + message("Duplications occured, probably because of the relabelling.") + } + + corrected_dataset2 <- corrected_dataset %>% + select(-n) %>% + ungroup() %>% + filter(!is.na(change)) %>% + distinct(geo, time, indicator, values, .keep_all = TRUE) %>% + add_count(geo, time, indicator) + + if (any(corrected_dataset2$n > 1)) { + # If the problem was only relabelling, you never end up here. + # You can add here further exception handling code if you want. + corrected_dataset2 <- corrected_dataset2 %>% rowid_to_column() + + duplications <- corrected_dataset2 %>% filter(n > 1) + log_file_name <- paste0("log-", unique(duplications$indicator)[1], "-", Sys.Date(), ".rds") + saveRDS(object = duplications, file = log_file_name) + + kept <- duplications %>% filter(is.na(change)) + not_kept <- duplications %>% filter(!is.na(change)) + + corrected_dataset2 <- corrected_dataset2 %>% + filter(!rowid %in% not_kept$rowid) + + corrected_dataset3 <- corrected_dataset2 %>% + select(-n) %>% + add_count(geo, time, indicator) %>% + filter(n > 1) + nrow(corrected_dataset3) + + corrected_dataset2 <- select(corrected_dataset2, -one_of("n", "rowid")) + warning("The duplications could not be resolved fully, please review manually ", log_file_name, ".") + } else { + message("The duplications were resolved successfully.") + corrected_dataset2 <- select(corrected_dataset2, -one_of("n")) + } + + message("Corrections: ", paste( + c(missing_nuts1_2016, missing_nuts2_2016)[c(missing_nuts1_2016, missing_nuts2_2016) %in% corrected_dataset$geo], + collapse = ", " + )) + + corrected_dataset2 +} + + +check_spread <- function(dat) { + dat %>% + filter(indicator == unique(indicator)[1]) %>% + select(geo, time, indicator, values) %>% + spread(geo, values) +} + +source("fill_forecast.R") +safely_check_spread <- purrr::safely(check_spread) +safely_fill_forecast <- purrr::safely(fill_forecast) +safely_fill_data_source <- purrr::safely(fill_data_source) +i <- 2 +for (i in 1:length(regdata_files)) { + message(i, ":", regdata_files[i]) + + this_data <- readRDS(file.path("regdata", regdata_files[i])) + corrected <- correct_nuts_labelling(this_data) + test_results <- safely_check_spread(corrected) + + if (!is.null(test_results$error)) { + warning("there is a problem with ", i, ": ", regdata_files[i]) + saveRDS(corrected, file.path("corrected", paste0("problems_", regdata_files[i]))) + } else { + message("The data can be spread to wide format, saving...") + saveRDS(corrected, file.path("corrected", paste0("corrected_", regdata_files[i]))) + } + + try_forecast <- safely_fill_data_source(corrected) +} diff --git a/data/ea_countries.rda b/data/ea_countries.rda old mode 100755 new mode 100644 index ea53a63c..76ecea1d Binary files a/data/ea_countries.rda and b/data/ea_countries.rda differ diff --git a/data/efta_countries.rda b/data/efta_countries.rda old mode 100755 new mode 100644 index 84e3c9d0..f4c0124c Binary files a/data/efta_countries.rda and b/data/efta_countries.rda differ diff --git a/data/eu_candidate_countries.rda b/data/eu_candidate_countries.rda old mode 100755 new mode 100644 index 3d5732cb..4c790ec4 Binary files a/data/eu_candidate_countries.rda and b/data/eu_candidate_countries.rda differ diff --git a/data/eu_countries.rda b/data/eu_countries.rda old mode 100755 new mode 100644 index dd30d3f2..b9305db0 Binary files a/data/eu_countries.rda and b/data/eu_countries.rda differ diff --git a/data/eurostat_geodata_60_2016.rda b/data/eurostat_geodata_60_2016.rda old mode 100755 new mode 100644 index e33288f4..0e453269 Binary files a/data/eurostat_geodata_60_2016.rda and b/data/eurostat_geodata_60_2016.rda differ diff --git a/data/tgs00026.rda b/data/tgs00026.rda old mode 100755 new mode 100644 index 26e9f154..3b1cfa40 Binary files a/data/tgs00026.rda and b/data/tgs00026.rda differ diff --git a/docs/LICENSE b/docs/LICENSE deleted file mode 100755 index 34ae01c5..00000000 --- a/docs/LICENSE +++ /dev/null @@ -1,2 +0,0 @@ -YEAR: 2014-2017 -COPYRIGHT HOLDER: Leo Lahti, Janne Huovari, Markus Kainu, Przemyslaw Biecek diff --git a/docs/LICENSE-text.html b/docs/LICENSE-text.html deleted file mode 100755 index 6e43b68d..00000000 --- a/docs/LICENSE-text.html +++ /dev/null @@ -1,146 +0,0 @@ - - - - - - - - -License • eurostat - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - -
- -
-
- - -
YEAR: 2014-2018
-COPYRIGHT HOLDER: Leo Lahti, Janne Huovari, Markus Kainu, Przemyslaw Biecek
-
- -
- -
- - -
- - -
-

Site built with pkgdown.

-
- -
-
- - - - - - diff --git a/docs/LICENSE.html b/docs/LICENSE.html deleted file mode 100755 index 8f52a3e6..00000000 --- a/docs/LICENSE.html +++ /dev/null @@ -1,128 +0,0 @@ - - - - - - - - -License • eurostat - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - -
- -
-
- - -
YEAR: 2014-2018
-COPYRIGHT HOLDER: Leo Lahti, Janne Huovari, Markus Kainu, Przemyslaw Biecek
-
- -
- -
- - -
- - -
-

Site built with pkgdown.

-
- -
-
- - - diff --git a/docs/articles/2017_RJournal_manuscript/2017_RJournal_manuscript.zip b/docs/articles/2017_RJournal_manuscript/2017_RJournal_manuscript.zip deleted file mode 100755 index 0eb1b1dc..00000000 Binary files a/docs/articles/2017_RJournal_manuscript/2017_RJournal_manuscript.zip and /dev/null differ diff --git a/docs/articles/2017_RJournal_manuscript/Proofs.zip b/docs/articles/2017_RJournal_manuscript/Proofs.zip deleted file mode 100755 index 50dd6e56..00000000 Binary files a/docs/articles/2017_RJournal_manuscript/Proofs.zip and /dev/null differ diff --git a/docs/articles/2017_RJournal_manuscript/README.html b/docs/articles/2017_RJournal_manuscript/README.html deleted file mode 100755 index 245d1a7c..00000000 --- a/docs/articles/2017_RJournal_manuscript/README.html +++ /dev/null @@ -1,112 +0,0 @@ - - - - - - - - • eurostat - - - - - - -
-
- - - -
-
- - - - -
-

Source code for the publication: Retrieval and Analysis of Eurostat Open Data with the eurostat Package Leo Lahti, Janne Huovari, Markus Kainu and Przemysław Biecek. R Journal 9(1), 385-392, 2017. https://journal.r-project.org/archive/2017/RJ-2017-019/index.html

-

The source code of the publication is not maintained with updated package versions; instead we provide the original version, which is stored in the compressed file: 2017_RJournal_manuscript.zip

-

For up-to-date examples and tutorials, check the eurostat package page: https://github.com/ropengov/eurostat

-

Contact: Leo Lahti / https://www.iki.fi/Leo.Lahti

-
-
- - - -
- - -
- -
-

Site built with pkgdown.

-
- -
-
- - - diff --git a/docs/articles/2017_RJournal_manuscript/README.md b/docs/articles/2017_RJournal_manuscript/README.md deleted file mode 100755 index fd44bfe8..00000000 --- a/docs/articles/2017_RJournal_manuscript/README.md +++ /dev/null @@ -1,7 +0,0 @@ -Source code for the publication: Retrieval and Analysis of Eurostat Open Data with the eurostat Package Leo Lahti, Janne Huovari, Markus Kainu and Przemysław Biecek. R Journal 9(1), 385-392, 2017. https://journal.r-project.org/archive/2017/RJ-2017-019/index.html - -The source code of the publication is not maintained with updated package versions; instead we provide the original version, which is stored in the compressed file: 2017_RJournal_manuscript.zip - -For up-to-date examples and tutorials, check the eurostat package page: https://github.com/ropengov/eurostat - -Contact: Leo Lahti / https://www.iki.fi/Leo.Lahti diff --git a/docs/articles/blogposts.html b/docs/articles/blogposts.html deleted file mode 100755 index 79e39772..00000000 --- a/docs/articles/blogposts.html +++ /dev/null @@ -1,124 +0,0 @@ - - - - - - - -Blog posts • eurostat - - - - - - - - - -
-
- - - -
-
- - - - - -
- - - -
- - -
- -
-

Site built with pkgdown.

-
- -
-
- - - - - diff --git a/docs/articles/cheatsheet.html b/docs/articles/cheatsheet.html deleted file mode 100755 index 04ac2792..00000000 --- a/docs/articles/cheatsheet.html +++ /dev/null @@ -1,122 +0,0 @@ - - - - - - - -Cheat sheet: eurostat R package • eurostat - - - - - - - - - -
-
- - - -
-
- - - - - -
- - - -
- - -
- -
-

Site built with pkgdown.

-
- -
-
- - - - - diff --git a/docs/articles/cheatsheet/bar.pdf b/docs/articles/cheatsheet/bar.pdf deleted file mode 100755 index 0203c8ca..00000000 Binary files a/docs/articles/cheatsheet/bar.pdf and /dev/null differ diff --git a/docs/articles/cheatsheet/eurostat_cheatsheet.ai b/docs/articles/cheatsheet/eurostat_cheatsheet.ai deleted file mode 100755 index 46b7ade9..00000000 --- a/docs/articles/cheatsheet/eurostat_cheatsheet.ai +++ /dev/null @@ -1,5691 +0,0 @@ -%PDF-1.5 % -1 0 obj <>/OCGs[16 0 R 109 0 R 201 0 R 296 0 R 391 0 R 485 0 R 553 0 R 621 0 R 689 0 R 757 0 R 825 0 R 893 0 R 961 0 R 1029 0 R 1097 0 R 1165 0 R 1233 0 R 1301 0 R 1369 0 R 1437 0 R 1505 0 R 1573 0 R 1641 0 R 1709 0 R 1775 0 R 1829 0 R 1884 0 R 1942 0 R 2000 0 R 2058 0 R 2116 0 R 2175 0 R 2244 0 R 2313 0 R 2382 0 R 2452 0 R 2522 0 R 2592 0 R 2662 0 R 2732 0 R 2802 0 R]>>/Pages 3 0 R/Type/Catalog>> endobj 2 0 obj <>stream - - - - - 2017-03-02T18:21:10+01:00 - Adobe Illustrator CS6 (Macintosh) - 2017-03-13T16:15:16+01:00 - 2017-03-13T16:15:16+01:00 - - - - 256 - 136 - JPEG - /9j/4AAQSkZJRgABAgEASABIAAD/7QAsUGhvdG9zaG9wIDMuMAA4QklNA+0AAAAAABAASAAAAAEA AQBIAAAAAQAB/+4ADkFkb2JlAGTAAAAAAf/bAIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoK DBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxscHx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8f Hx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgAiAEAAwER AAIRAQMRAf/EAaIAAAAHAQEBAQEAAAAAAAAAAAQFAwIGAQAHCAkKCwEAAgIDAQEBAQEAAAAAAAAA AQACAwQFBgcICQoLEAACAQMDAgQCBgcDBAIGAnMBAgMRBAAFIRIxQVEGE2EicYEUMpGhBxWxQiPB UtHhMxZi8CRygvElQzRTkqKyY3PCNUQnk6OzNhdUZHTD0uIIJoMJChgZhJRFRqS0VtNVKBry4/PE 1OT0ZXWFlaW1xdXl9WZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo+Ck5SVlpeYmZ qbnJ2en5KjpKWmp6ipqqusra6voRAAICAQIDBQUEBQYECAMDbQEAAhEDBCESMUEFURNhIgZxgZEy obHwFMHR4SNCFVJicvEzJDRDghaSUyWiY7LCB3PSNeJEgxdUkwgJChgZJjZFGidkdFU38qOzwygp 0+PzhJSktMTU5PRldYWVpbXF1eX1RlZmdoaWprbG1ub2R1dnd4eXp7fH1+f3OEhYaHiImKi4yNjo +DlJWWl5iZmpucnZ6fkqOkpaanqKmqq6ytrq+v/aAAwDAQACEQMRAD8A9K+Y9S1TT7AT6dZ/XZiw UxVeoBB+KiK5O+ZWkwwyTqcuEMMkiBsLSy3853TwsZdC1BJY2ijK+lszSMyMVqfsrx65kT7PiDtk hW/VrGY9xUY/Pty8Xqjy9qdKN1ipuicyBWniPxpWm8z2YAa8XH80eOf5pVofON9JeLbNoV5GhlZG uHUiNUV2XmTx/lWtPor3yEtBERvxInbl15JGY3VFC/8AKwbmbT/rFnoV88kkPqwM0TGIkq5WrAbg 8Vpx61y3+S4idSyQ50d9+n4+CPHJGwK6f8wvQuI7aXRr1J5VJjV14ByIRKUTlQs4J40A64I9lcQ4 hOND9dfLqpz1tRd5y1jznFaaZL5bs+T3StJdRyqpkj+FCilWYUPxNX5Y9n4NMZTGaXLlXI81zTnQ 4Qxf9P8A50f9W9f+RUf/ADVmz/K9m/zvtP6mjxM3cm+n6x59a3Q38N1FcEfGsNpbuobk3QtMpoF4 n51zEy6fSg+gxI85S8v6PvbIzydb+SIk1jzf9YVUivvQoC8htLXlXwC+qB9NcrGDT1uYX/Wl/wAS y45+fyC9tX80hDSK/LUHH/RbXqFFeQMu1Wr0JoPHAMGDvh/ppfqXjl5/IJDca9+cInkEFhygDMIm eGJWKV+EsA5ANOu+Z0dN2fQuW/vP6mozzdyK0LXfzVfV7aPU7CNbJ2ImLIibcT3DV65VqdNoRjJh L1fH9TKE8t7jZAHzH+cpNRYR0PSkcZH/ABPL/wAp2d/OPzP6mHiZu5GaXr35oPc8dUtngtuOz28E Mj8qj9lpEFKV75Vm02hEfQbPmSP0Mozy3um41nzLxJK6hyr8K/U7Qbe59c5ifl8P9D/TS/4ls45e fyCkmtebuEfOO95Nw9Ui1tfh+Bi/Eet8Xx8ANx3yR0+n33j/AKaXl/R7rRxz8/kEHqmt/mLHDGdM hmnmLN6izW0CKEqeNGEpJalKimXYdPoyTxkAeUj+pjKeTolv+IvzlG5sE/5Fxf8ANWZP5Xs7+d9p /Uw8TN3PUdPkuZLC2kulCXLxI06r0EhUFgOvfOZyiImRH6b2c6N1ur5Wl2KuxV2KuxV2KuxV2Kux V2KuxV2KsV84WGqRfXNag1mextLaxKm3iUvR0cyGUKXVCxFE3HTvm00GWB4cRgJSM+Z+Vcr82jLE 7yutmMWfmGR7u15+dmlkLKfqosTGzpxDsu44/GKcXP0d82WTSgRNYK8+O/L7OoaBk3+v7F9n5jnW 3htJPODG8PEkPYliBPCFhV3QSJUMwavL54MmkFmQwen+v3HfnX3JGTpxb+51rruoySiYeczLbhPr Lr+jitYY+TMa0AHJYnoOvtjPTQArwKPL6+p/tCiZ/nfYhY/Nd7cR3FxB5uZIqh4bcWAMiB0kf02B ATkirXZiNtj0yw6GMSAcO/fx7cwL+PuYjKT/ABfYjRfXeqX6Raf51Ilk9K3SL6k+8io4JBPAAu0T kn6PDKfDjihc8Gws/V0sfdY/FsuIyO0/sTrzXZ38PkLULXUdVUXq2F0H1ZpxpqKx3R2nUP6AXYFw PfNJmnCRkYDhjttzcqIIqzZeK3Xl/wA2RwyJe+eJdPljheGFpvO7Ikk0MRDzOy2PqD0VBZl2UspL AVNcdmhXtHufSli/MgQ3nOae5hs/PKMAi/vUbgbEo6qqsWrx4r4iihVFpomv3tzbWth56eW+vljN tBF51knFylHillUHTnpyL0HpgCqgqFIxVPfKvlTy9q9pZ2N1+bGqDXjHOs+m2HmaK8YkVYSCRY4J mMcSI+yKq0NQauWVZZJ+R1w9vxHn7zULkqeUp1OUoZDD6fMR/s0cmQBSPi9gAFU/8p+Q7jyxcXlz P5k1jXm1B4z6Wq3PrxQFfUZvq0YCiNW59PAAdsnDqgsK1P8AN/WrHzNqWiWl3ZSfVpIoLW2khsRK nwiSVmaTWrVnVY45NmhjapBAZVbBPmVHJjWvfnBdXf1W01W9055Ip2F3JGlnbfVx6gVoPUOvLWZV Ql3i5qAaUrXLcGpniNx/X97GcBLmlw8+z0eCWa1gubaZ4OZktI1QxIZZ29KTzIGYK8vqcuPwqKEd xkDtLL/R/wBKP1MfBitbz3fQ6pDZq9sbq1lY3EYurRXeGJEk5LHJ5kDQmnNm5hqLud1YYf5Ty1Xp /wBLH9SPAj5/MojQPzY1TRdRS2s77Tbo3MsEXFXsX5xNTaOOXzJIQx5jg3HffYjKdRq55vqr5Afc zhjEeTK/LP5v6/qGowW0+r6VeJdXNvBGLaLT0+CS4eJz8OtzuxZYvh4KSCy/A26jGDN7TB/cR/6o /VhlzKAvyKXYq7FXYq7FXYq7FXYq7FXYq7FXYq8//MnU/NmmTi9stXs9J0OOGNbma9e3ijEskjIO TzqR8VVAFc3HZ8tJHH++BMr8+W3cXGzDIT6eTErfzprUF3bvq3nTRoLBvTlnkS70xX9CTZZELrxo wWisdjmXlz9n8J4Ini6XxV97CMc17nb4JhP500uCNA35gaejyq/piWbRo1PEyRoRV9x6kXEj2I6j MUanTXvAf6afx/Sz4J9/3IqPzfoS3LW7+fbRpg0sciCbRldTDG3JSvNj+7+09aUXwrXIHU4P5kf9 NkTwS7z9iGHnfy/6U7v+YdgIo5ljMnraLRSyE8JAZBR24vTft3yR1On29Ef9NkRwT7/uS+8856sb qSXSfOujNYcpBFNNd6WrlraNXuC3EFQYxJybf4VO+ZWLPoDEccfV5cVfewlDLex+5n1hqOs6f5X+ u+YJI7y9hSYyMqlkZC6hQRbxOTsf2UOavW+FxnwhUNm/FxV6ubE0/NPVNQt1uIvKEV3qXFPq8bjU o42SZEl/3ouNKi4A1anwkEhVryZRmC2pP5XggvdVm1nUNM1XTraxuIhcrbal5iuqli5AFrNZ2/qR mZFDLH+wd/gNGVZnAnkSWMa5DJrPpWC/WBEY9X+ETSV/3kdOTnlbn4TGSo8AwxVQfVPy8tNOuLxz rq25u/UkH1fXWuEnHqN8I9M3CxDiwAH7odO+6qYi+8pLrOnxNcayt9qVpBFCjxaqsTRGN0jaesYh glPqmrScH5AV3XFUy07ydpei331yzuL52kjjtvRur25uolSIfCQk8knx7bv9o+OTh1QXifni+mt/ Ot7FFqZtnvJIrRLJ9Rltyq3EfATpGuuWy8fVU/CkSSEqRx+LmBPmVHJILnzNqP1+VrrXY5L0mJob JdT4ETKnplVhbzNwZlclXVtncOCrVByKU10jyp+YOtRWqPa6u0FxKeV891dyW6cmWNZC6eZWk4xl QzhQ52PHfFWcQfk15xis0txrtkUKxrcwSrrU8TfV3cxFFfVl4KUK80GzGtag0xVSk/I3zQ6SKPMa RvJOsvqibX2YKgIUf8dhasK9RQbdMVTXTPyo8x6frEd2utpJaCWGWWOSbWpXCwvFIyR+rqciASFH BqCKcQyuOQJCvToP7iP/AFR+rDLmUBfkUuxV2KuxV2KuxV2KuxV2KuxV2KuxVgn5wJet5QvTZQ3t xcI1s4i05LmW4KrL8ZWO0utPmai1NBMK+B6ZM/Sjq8GuvMHm0xwWNtpPmhktPUkmZ9N1v940TOSQ 7a8C0RU8VRnNSDQfEFyCU48v+a2t7WBNZ8u+dL5IaSWsGn2mpW0kcyzFqzC41G69VSTQKZH2U8lA 2xVMh5t8n3saLJ5T/Mi2ZnEIk5amrETu7NKzRXTcuBqN6mmyggUxVl7eX7IB0i8u+c5IU4rHH+lR WT43l9QPNqPqDiyhaSOuz9OPIhVG6T5N0nUp7fTrjQ/NGl29t6lwt7dazMULyem8kMhh1GeSSpPH 4lI+FqGm5VZ/60Fu4kmkWKJWlBeRgoFXUCpPiTTLZcvkxD53trH8x0tOEk+qyX8DsrKdRueEiSIF 5b+ZY6/Ep4NyWh/YNapUydqHljVS4ZtFm1TU/qkCy6hey/W/jThLEYmk8wpJHNBLJMK8vhP2WNKs qnfkzRtMTULqz1jyXEml3scaXc11DYyyzsrMCZ5/0pdu/wBpCKxkbN05UxVl2oaJ+W4tNCsW8jw3 lhGk628CDTClh9ZWN5VlSS5QfvT8LNHz3U9iCVWT2nmPSrHTCunaU0UUUkYWyheyiJ+scXkkRWnR aRmUmSpBqGoGPVVT0vznJq+oLZHRb2xCkt9YuJLF0YAH4lFvc3D0/wBZQdxt1pOCCwzzhb3K+Y41 uNLvJIrhbdre6ttU11YmZRJ6Ykgs7Sa1Qcqhwz9KVFOIYT5lRySzRmurqW01DQ/L15dXF6I7y5i1 PWNfhgt2E6ShFjubBk4NKrr9gAov8rUyKU3tPzh80ssYbye0EKtKrmJdZkCx268pWUHR4VNOiitG OwNdsVTew/MPznfXBsYPLNuNR5sI1lu76O3aMLIQzXDabxRy0JBQjaq71OKp7+k/zBNjK36G01dQ CRmK2/SEjRmRufNTJ9WU0UBaHhvU+GKsiaVVQCRlR2FOPL9ojoK0r92EK3B/cR/6o/VhlzKAvyKX Yq7FXYq7FXYq7FXYq7FXYq7FXYqxP8w/Ocfk7Q7jXJPqwSJreI/XJJ4Yf30vD4pLeC7deux9OnjT Jn6UdWGaF+fd5rarNpuhxXlm1zFaG7tn1aaISO7K9HGkhSFVa1+zXZitQTBLHZ/O15JNdS/4JmET qrTAzeZI6vM1ZAkY0dqFXVqsANvckZnjtLMABY2/oj9TUcMUZqXmV47+6nsvK11c2unEBbmW58xQ yERcIzxjj0udW37q5BAY9Byw/wAp5qr00f6Mf1L4EfwUXpX5h6hp13d3dn5XuAJ3MEAmbzCxeQyA rzik0jjCpWp5Ly4kUyjNq55IiMqoeQDKOMRNhGn86fNq7v5SCrGzLMP9zpJ49TEBoh5LRlNf4Dlm MzejXTco4WpTlcIaEEHe5i7Ghy2XL5MQkOpeS9I8zamb3zT5Z0i8v7WJIoBcBbz9y0jkfvpIEZe5 4cCK9965jy4ujJN/L/lPyzo9xdT6Xo1rpl5cMWvZLVFjMrPR2YuoVnBPj3xhInnzVOgmy9d/8pvD Jq4ps3Xb/KbwxVZIWSaAAkB3IYVJqODHv7jFULf/APHUs/8AjHN/xKLJw6oLCNf/AC9v/MGv2+pa hB5Zu7KOBYIHvtLluL/0PjLRev8AWkWg5nolN22GCfMqOSA1/wAg3OhaCLTyxoGgTwzGBdTsYdJU 8pROHW4KvqFoOEaoCBzZ+QBrTpFKR2X5d6tqN20Oo+TNBghN3JI01zosPplSV9aQsuqzsWlotJCt fhNUO2KquheQPNupyzy3vl7y3oLVhlUXWi83d4mkW3Alt9Ufk0PAEH4SFYUp0VVlcP5bXErW1rrN r5av9ISWSa9sY9Jktw0jGT99GHuriNWKTEPyRuVTVqUxVPLb8ufy7sGtls/L+nWklvP9csxFBHGy ToF/ex8QKMOC9PAYQrJIP7iP/VH6sMuZQF+RS7FXYq7FXYq7FXYq7FXYq7FXYq7FWE/mrf6zY+XJ pdHuTZ3ry20S3KxW07IskpUsqXc1vFyWtRVj/qnJn6UdWCadF+fTWtvC2qarFdJdI09zPpeicZYU AMsZjhuQkauJBxILEFH+M8kGQSnvlfy/+ewtbfUdQ842j3M0XKbS9S0qIiGR6sYz9SuIPsAr+2+4 +1Q0xVl0Fp+ZCLF9Z1bR5CFk9cR6fcxVetY+Ba8l4rx2YEMe9e2KqOj6r5gudQ1Wym8waHdTqW/R tvZwSevElGAN0hu358WZK8QvQ/zDiqqeWNQ126vmivte0fU/q6SLeW+mQvHIk3qUWvK5ueIVdiDv X8FUXrt/Z6dp8moX0y29lZubi6nfZY4op43d29lUE5bLl8mIda/ppp52mltp3kWF4ZoI3hUReo5R WV2uORIryII9qZSbZ8II518FxvtYS4SV7BI42Co6tKK1ZkpRqcajk9PHKpEg3X4+bHhyHlwn4m/9 z+n9gmHVPUIAtnHpkCdDw5xkhTuoY1ADbkH5VyyMwWrxT/NNfD9f480cCrKWWhUioIGxFMk3A2h7 71f3XoFVmq/pM6kqG9J+JYArUV67jFUj0nXW1i6SRrO5tWtJLm1L3MQhWcx+ifXgAeXlC3KitXeh 7ZLFIEWO5ZCiwXU9A8sHXry/ns9Ml1ZpqQXs9tYtNDUxJ8Je4hZj+/J+MHftX4Sz5lA5JNcflv5T i8u6Pqqpp/qgPLX6howiZxdJGXUK3EHi4U8JDuATRtjFKdXXkXyHPZX8cWjaRbyyzW8RuBaWMzBU S3ZF43FxKlADxUFNh0HSqqQeYfL3k6OypHa6PZ3K8ofUFlpkkkquiO68Z7gxhC8zu4Xj8Rr81UTq PlnynJqVnpltpWkxIP3QCWenO0kK3LFoD6l0T6a158VWgYAjpTFUfbeXdD0TzXapZvZx32laja2t nOtrpcc8dvdKUmhUpLE6+qpI+GEPQmgNScIV7LB/cR/6o/VhlzKAvyKXYq7FXYq7FXYq7FXYq7FX Yq7FXYqkPmjSZ9VtmtYI45H5QycZjGFojkk/vIbkV8Pgr7jJn6UdUBLp3nZTYR2ciW1rbRwQyxxz w0cLwDkq1k1Duw+BgKAUpXaCWF3Mlnd3jX97dWMdzO7290HktmZyEERb49MDMypI2x2pQbhszv5N z/zD3tXjQ71B7WwuNSnuRLp6x3BFqJ45LSWruArULaYQzMhNV5Hrx6dAezs4/hPK/gvjQ70boOmv qN7P+j5LK4vvqyr6qSWpcKkqAEuNNTl6ahfbYAjvlebR5cQucSAyjkjLkWU+QvKeoaHLcPd29vB6 qAf6OYCSajdvRtbT+OYzNNtbs7e+sXsrkFre6kMMyqzISkk8asAykMpoeoNctly+TEL7HSm0+7mh sp5PRKxOy3Ly3JFXf4UaSSqKANl6DsMgK6tkSOqNMeo9GeKUfDyQxlARUV35yf5Xbww+g9CyuPmP j+wIJrd7cxyPblUHEUhfmEB4A0YKsigceg+Gg3plcsETuP1fL5cr8t22xPrv8u/zr9PvatbWsKza VdyelGAIreXeH0yqNwAorCoA4seXGvhtlfARyJ26H8W4k9PLGaG3l0923u+Hu2RYa8c2/wBaiSKQ yMAsb+otPSb9oonf/JyyN9VjZG6R6Jo82lXKwywxQtNPdzj0TEQwkaGjN6UFoOW1N1Y+LHLRVmkC IiAByCCufKOoXN01wltbNFLIJQzm35fagYH4rSU1pG37XWm9fiEZ8yyHJR1zQGsfJtnFeJawx2K8 J2YwGJDLdRMtKWfGhpvSNd+tftCWLDLJLhiLkUSkALKFW50P0bs/WrEBZ1lerQgqIkgjcsDaVBDL 8+m4/ZyP5Pz7ek7sfGj3sd1W20O7NFuNMcxsZGWR7ZaDhCvVrB6V4MPu67Ul/Jmo/mFHjw72RXHk bULzUrbUIbSymtyySpccrbkFMzS1Stix3Vh0YfR1zClEg0ebaCmV/wCUdUm1171YbdrU6hbXoq1v zAhoHehs2fnQbfveX+WvTEKzOD+4j/1R+rDLmUBfkUuxV2KuxV2KuxV2KuxV2KuxV2KuxVhH5r3M Vv5auHkufqYaS2Rbr6ybNY3aQhHaZbzS2Cq1CQs4ZugBJyZ+lHV4Jdea9YjtrSN/MNzPCkJKXP6V aH1ZJZGKuSvmaD4RyQ/Fy9mAZVEEonTvNFxcQMh1a6eIIq2d3FqttCiWsauLlp0j8xOZyIEZvU+2 vFiKHdDxFVFPONzNptwsuuKQ0iS/WY9URVjkYyEQmf8AxT8LMAJFBkWqoy/s/C8RWkXZ+abiO7M5 1phDOIhLYrqVZWE0LSGSP/nZ/Sg5ceUfAUUMhFQtQ2VU4/MfmBkkWXWrlQYzqVItTVC1vIojeUO3 mh5PTpup5rGtK/aouBX0hc0MUBBqPXShrWv+kRd6n9eWy5fJiEJdQeV/LxubmeODSrBvTd7kD0I/ VkkbkTIgUBmPGu++QjIjkieMS5pg7RQBpUmmiRBycypJJHRepYutR8I7MPHJcYPMfoYeER9JPx3+ /f7VGw1kXtpBdWZhvrWQVju4fV4OBQErxjlHXl+0en3Po8x+Pgt5B0ifmPso/ehFn06+lmkS3S4l hcpKbWWYyI4KqV2SMCjxmoqNx41yVg7X8x/a3R1OaIqhXvv7wO8omzv9PF9b6crvHeqTMba4kZ5v TZHAf4ix4kqQN+xyuXPna+IZ7kV8v0Iq/wD+OpZ/8Y5v+JRYYdUF435v0z8xn1vVP0XZ6sNOvJYS jWbTNQRRx0kRx5hsBEHY78II6iobpXBPmVHJANoX5qoZ7n6tqUUNzBweCa5u5OLseLvR/Mhiioy+ onpVPD4VNQcilUXyx+Zd/esZoNbs7J3UrGk11U273JLxTE6+CsyllcSRbCNeI5g8MPEVpLJPKX5q vZ84NN123uQhe4c3lyJJj6gVVib/ABE7xlEctSR2UnkeI25HjNVaKZV5d8ifmNPcSj9JXmmwQm3L /pOTU5DM0M0zUieHXJ5AODj1A/wMaUqvwiKU30T8rfPGnalBd3HmsXUEUyzSQs+uOSgZCyD19YnQ gqhUc0alehFVJCvT4P7iP/VH6sMuZQF+RS7FXYq7FXYq7FXYq7FXYq7FXYq7FWKfmJa6hdeXr630 +KeW6kWJIxasVlXm5X1AVutPaiV5GkwNBtvkz9KOryG48l/mASNQh0jVPUhtUge2nnuHeaaWJ4ZH hH+InVfR5K45Ub4fhevxZBKGsfLH5kPqn1O6s9bsPryCD9I+recIFlUR+q6r5juKcGKluNWKhtgf ixVmS/lH5vitpo5/NUDAx/A7Sa6rrIrk1eX9MeoyhXcU5Dr8wVUZcflX5ruboTy6/a8ZmQ3iRnWk VqRCE+iq6sEhZkZjyoTyo3UA4qpt+UfmoWUcEXmKP66pDTTyS66/qBJHKAj9LB6FJOLgu1foWirK PPmsyaR5Rv8AVrX1HltFaeAwQG8css8ZTjCHi9TftzHzy2XL5MQ8pufzV/MtvXt4ReX7ej6tpIPL E0ETlZGqWFzeJs0UbNHyKE1G1SFypknPlj86NavLmeyv9K8wX1zHHH8dtpENjHzG8p4XU0snEoyu gYA0DdaGiqZp+ZuiXOlSeZLby/5kk1azVI006TSY49RozunCIGMq4VC7ng5AB3+I0xVdafnILjWL jTIvL/mhJonlQTyWFukMnoo5YrIVofjQJ/sgelaKvS47OZ1WUXs4LqN+NuTTrSojI7+OKrZbIpNF PJcSTupKLzEYADUJ+wifyDJw6oL5z/OvSp7Pzvau+sWVnHewWtzFLcWHl95Y3E0yik19Nb3PFKhu Sxv7HltgnzKjkxKy0hdPMeuNqmk3LTlrm/1GXT/LLNHLcS8QyvHfxpGfgcx8JH5Uc02C5FLLLn8y fPdhoV3pVp5sliudMvCsmrNbeWVWG2r6ccJjbUYo+BKngxjUnoB0oqyDzP8AmR5v0u4NjL5nSW0R LCSbVNPTQllQzWqeolby/CVmek6fuD8LkLUcWCqL0bzb5t9ZJ9b/ADQ0bTryMux0q7h0yK3liRmE jcUuXuWUcXo4mQfCKqfixVPtNtvNZ17R4m/NSHUZbYqdW0k2mnL9boqtKI/RVJEB9RQNzQFd6/aI V6hB/cR/6o/VhlzKAvyKXYq7FXYq7FXYq7FXYq7FXYq7FXYqwj81dF07WNANpqFlLfwC4tZVghSW Rw6Skq9IZbdqL1ryp4g5M/SjqxH/AJVD5E0q60XV7XRJb+21Fks5LXUVudRlhXUGDTO/rXHGFeAZ XPFt2PWpyCWTxflT5Gh1C9s18r6MLC7g5RRrpyqpKFaLO3MpJRzyUBBT5jFWL6p5e8sS/UdRufJG nXN9qlxPFqUraEruSkqRl6mesfPkzBiW5LXw3VTS08p6DrXna807zH5V06/+pwbao+k+mr/Z4otx LPPySjsOFPwGKsqh/K38toITBD5X0uKEzR3JjS0hVfWi5COSgX7Seo3E9q4qmtjp9nbRJZW8Kw2q +uiwoAFAZhXb3rlsuXyYjm+edT/KmHyvd2dhqP5j+WdFns4mlsIL7SdLglMVw8qOQJWQ8XUBGddz x6jrlTJGN5R0Sz0W80S1/MzyvHoImAurGbTdGaKS6R45WF0iGNeSiCWgUIwWh6ryxVPNO/JXzDea RFc6b5m0S3FzF6kGpaVoVm0d3HN8atOJmuI5k+NmQoF+2SS21FU+svyQ07nfy61Z+X9bubueWSO7 udGjSdEkctxkeORRKVX4VIVCOtWOKsvttC1/TbRrLQ5tL062jEK2yfUZXX4PgfmkdxB/upURaHal TUbYq3ptr53inibXdR068t/iqljZT2rcyBw3lurqtKNXpWvTJw6oKUeaNW1eWFLOz0W0v9Kmg+q3 GoXU80EkUsjmB0jiNjdRSduNZKM3w0puRPmVHJ5ZH+Vuqy6XE9vo2nWcsP1gS36CxlZ4pCVdGkPl 4pwAaQMAi078iTSKVTVPyzDMtm9lYixaa7lsbR47DnEknF5VijfReJ+rv6nFS5AH2mOyhVE6v+X2 vG7e8i03TmgivLS7WwljtIovUjRTIzsuieojtw9P+8b4GqCKAYqjdE/Ka2vbqOXU7OHT4LS1isx9 WsLG7F2qO4MdyraZHx4qkZIR+Nfh348mVT7TPyo0LSfMEfmBNTuvUgkeaVf0RYQ81MouCHmhsY5B 8YqxDCvzqSQr1KD+4j/1R+rDLmUBfkUuxV2KuxV2KuxV2KuxV2KuxV2KuxVjXnXTb3UbBrazTnN6 lu9BDBcfCshJPC4aNPprUdsmfpR1Q15o+pzaD5WgSEiexvLGa8Q29qxVIlPqEqz8Iv8AWiLMP2Rk Ep/dPFbagt5cSpDarC0bSyemi82dSB6jEN26dMlCEpGgLKCQObzrV9OM0WmR2s0K/Vb25ecGDTHo slxEyt8Uy8A9Kjjua7/EFBs/L5P5svkUcY72SaXpGqR/mHqGqSW4SwngaOOQW1sgLD0qH6wsjTuW 4/tKOnsMpZMwxVCQ/wC9C/603/EhlsuXyYhAQBdTvriW7sbm0e3RUiSaRVJHKSsiehLItH99/EZU yYv+Yt1Lov1D9HFofrJnaarM1SoQA7sd/jOaPtnW5MHBwGrv9DZjiDzSG2/MXULGwR7uJ72SWSRV b6xLDxVFQ0oh3+3lnZOryZsZMzZt03bHaZ0kogRvivqzbyXrKeY9JmvnhltminaEItzM4PFEatSy /wA+bcG2zszXHU4zMjhqVfYP1sgNhBT7U/b/AHfL/wA14XYqbRLFJwUuVqho7s+5592LeGTh1QUo vdDj13yhPpEk3oJdvIpl9KC4A43BcViuY5omFV/aX5UO+CfMqOSQD8ntLhmubj9KSD1IXj4/UdIC RpIGDhKWQYBq1YFiD32JrFKRL+VOjDT0tpdWmmso3Z7eGXT9DcLVGjBAawWlVkYnapr161x/FkZU AnamUaB+Vnkq00aOG80611fmzy+teWdkrD1AxZONtBbw8f3j9E35Gta5kBDL7Oz0zT4mgs4YbWNn eZ44lVAXkctI5ApVmdqse5xVbrDp+i71eQ5G3lotd9kP9cVRMH9xH/qj9WSlzKAvyKXYq7FXYq7F XYq7FXYq7FXYq7FXYqxH8ybvWrTy7eXOjSXEWoReg0bWgJlp6vxAKtlqpYEdvq7V9uuTP0o6sQWw /PC906O707VWEUkFs1sXvbKOSX1Ed5JHEugtwILovHgtQK/CdsglbrvlD859Qt5Lb9IxXNushmhW 5uLAhw3pn03RtGmC8P3iowJPck12sxZZ4zcSQfJEog7FQu/If5kehqCW+m6a8ryrFp1xJdWhkjgK mKp/3EcaRqFYKyuTuKmgGXjX5x/HL5lh4Ue4ImTSPz7GoQlL1hagQrJ6epadwHERpIeL6FzNTzf7 Q26cTQZiNiMGhfnY/wAf6XaNlFBCbyw4uKPIhZxoxZW5lYmoKen8VS+Ks7vtRg0uxutRuRJJBYw3 VxMIkMkrJCObcEUVZiF2A6nLZcvkxCjY6tIZZp9VWCwMscf1cC45q8VZCrVdYaNvutDTxOUmQHNt hjlL6QT7mHfmvd2lyulNbTJMqm4DGNw4B/deBOcz7QyB4K/pf71ujjlH6gR73n2of8c61/4zT/8A EYsu7B/upf1v0B432r+vH7j+h6h+Tv8Ayi93sf8Ae2T/AJMxZv4uT7N/4vL+ufuiyrVfMejaXKkN 9OYZHUOq8ZGqtaVqobwzKxaXJkFxFvUYdLkyC4i/k1a6nY6koubKT1YCyqHIZdxzrswBwHFKEiJC jTVmwyxnhkKKlo9yrWtI7iH07eWYXUfV0Yysy8iGHH4TXcZVPmWscmp5pNS02aRT6fpsGdD0KoCa VHj13HXKL4olkkskqtbsBIrOJFVVqORCqR7mnbKDtHZmInqGWxxenbRotAqrQCh/lPvmXEUGt5F5 g8g6E/mLWbq60W21CTUDNdGaSzS4KvHKiKCRp18pJEzUDty7qrblKMMiZSvoXL1EoGMOEUQN/Nme i+SPKuieXGu7DQ7HTtTk0+l1cW1tDBKzegQwZkhtj1J29NP9VegyHEZfB/cR/wCqP1ZKXMoC/Ipd irsVdirsVdirsVdirsVdirsVdirCfzTiWTQSrapdaR+/tSLqynktpSfVNIy8cVwxVv2l40PiMmfp R1YFp9lpUfmvSrKbzzrmuiVxwgub+7syZJ2ilQFbS3jWVVieoWRwvxFTQdIJZBoekeUfMeo6jo1j q2svBYgBpk13WfXLBiDzErLxozlfhkYGgqNhiqdS655V8jLdaTHqFxc6m0YvVttTuru4JjVAhpcS rckAJCWKirE1NN8VVI/zGNxrWnaRaW9rNd6naJd26m4uErztzPSptSvGg2YkH/JB2xVMvJfnFPM1 vcyrFHH9XYL+6eWQGpZd/Vht2U1Q7UxVMriytL6KaxvYUuLO6S5hubeQBkkikoroynYqymhGWy5f JiGA/mQ981xD9bt44OBZYBFIZeUQZuDtVI+LEdV3p4nNbreQek9nvqn8P0sOuv8Ajn2//GWb/iMW c12tyh/nf71s7b+uPuQOof8AHOtf+M0//EYs2PYP91L+t+gPmHtX9eP3H9D0v8pLu0g8sXInmjiL XkhUSOqk/uoulc6LHCUhsLbfZ7LCOA8RA9Z+6KE/MmeCbVLV4XSRPQpyjYMK827jN/2XEiBsVu+h dizjLGSDfq/QnnkL/jhR/wDGX+L5ha/++PucHtb+++AR+laNpUFpdX4WO2+uyyyapIFRBMY2KLJN JQP8EaBQeXTNdk5l18RaV3ssI9YWsqT2p+JDC4kVqVpuvh4ZjTAILMRMZAHZLLKZFvbbUQrNBE5I ZAoVmFQA1VY9tqb/ACzGxmjZcyVgGPV6GrmS3jkU/C6hhUb0K18czwbcB57r2uafc6rfwyRafObJ Z7cpexQTOXaWNgqGe5s+K0Ql035HieS8aNOWEQo/zt2uE7JHcy61eGTyVFJCkccL6arRRwBFiVTB VVjEbzRhAPshZGFOjEb5FsTiD+4j/wBUfqyUuZQF+RS7FXYq7FXYq7FXYq7FXYq7FXYq7FWM+eFv 205hYis5kt9v9KPw+oeX+8f73p4/D47ZM/Sjqw3ST5lPmfSS60ti8Pq1/TgNPq8PLZx6PWv958P8 3fIJTHyjpmp6hqmrQao80NuGLQPbTavbyVEhA+O4KJSnaI0+jFVLzroes6VeQ3WlSG5tZ4vQ9K7n 1eeVZQAOSi2eUklK9lI61xVX09NdbzxoUjoRZfUU+sGmpGj/AFRqisn7j7f+/fj8fixVNvy8e8dN RNxHJGGkVkSQ3xpyLkcTfBSfg414Cla+2Kskh/3oX/Wm/wCJDLZcvkxDFPPWg6jqcj3AiZbazi5r JEPWeRVUswES0fkDsFUNXam+2YWfCZ07Xs3Xx05kSLtj13+X+qDTFkPPhDzmYLHycqypsI1YvX4O lK5qtZ2TLKBUgKv7aZa/tGOeQIFUEPqn5b6rFpiu7Nwt2klf04/VchwgAWONmcn4OwzK7O0MtPAx JuzbyXbPZstXKJiQOG+a25/LLV7XTV9RmYRSMx9OP1WPq8EACIzMd132zp+ztfHTxIIuy6eXs3kM QOOPM9/kjG/L/VLOwjEvNgkgU+lGJDWV1RfhRmagJ3NKAbnYZlT7XiZXwl7D2d/wDAccvUTK9vcP 1My8t6Pc6Vpq204+ISVDfDvXkf2S3jmtz5xlmZAVs5GtzjLPiApt7AXPl+UiOeaQpdwLBBJx5LPK VY+mzxxMwpUF+m9DucxMgsloxy4SD3KWn+V49Nt71Ak1wzQstY2WP1Q4aqIOX2u3xEDplMcVXfVu nnJI25JFbWOlazrl3ptnHe295ZObq7Nxay29qgkYxpEhkVI5j8DH1IeSniat0yMsFtkdURtXRNRo GqzvZOWnto5ZKzxqIucQRSwMrCU7Fl4j0+XUdq0ugBHpu4chfVlMVlZxSSSxQRxyStyldUUMzeLE Dc5IklaUtXAGkXoGwFvLQf7A4EoiD+4j/wBUfqyUuZQF+RS7FXYq7FXYq7FXYq7FXYq7FXYq7FWB efr/APMW01eJ/LFk11ZfVazUtIris3NwFDtqWnMDTiePpkU/bBOSEyBSKSI67+dSrIDpDO4aOVCl jFT0mZVeAh9cQeuvItyVjHRdiS2x4/ILSkdf/O6OBZDpMkzF6OiadCrBY2ox4tryj94GUp8RpRqj pjx+QWl0eufnhIV46QY1hKi4EtlDWYDmXaIrrnw1CAKrD7TLU8eRV4/ILTK7PzXrVyQT5P1+2Q0+ KeXTgdygHwpeuejlj7Ke9AXj8gtNzeadZjuZIl8pa7JFH0uFlsODgEcuIN3zqASRVRWlAcePyC0s Tzfq7JIIvJXmAS27UVeWloZFk5fGrPfBSBw3BPIVG2PGVpF2nmTWLiV0byzrNsqpG4ed9PAYyKGK jhcyGqE8W7V6Vx4vILSDuvOevQTeknk3zBN8ThXRtM4sEFagm72qNxyp4fa2x4vILTf+M9c/d18m eYRzRnb4tLPEjYIeN63xNtTtvuQA1Hi8gtLo/OGusBy8na/GSNgX0s0PMrRuN6abDljxeQWmTWXq 3FnBcSpPaSzRpI9rM0ZkiZlBMbmMyJyUmh4sRXoTjxeQWlb6spZSzu/E1AJ2rjxrSFGiWq14S3CA ktxSeVVqxqaKrADc4mfktN/oaD/louv+kmb/AJqwcXktLF0GzRmZJblWb7RFxKCaePxY8XktL/0N B/y0XX/STN/zVjxeS0x258teeSkv1XXbZJCR6BmhvZFH7wk8lS8iJ/d0A+Lr448XktIAeVPzSeOk 3mLSqmgZDY6jJGQVo6sramOQr0/EeDxeS0zu0SeO1hS4ZXnSNVldFKozgAMVUliAT0FTkSUquKux V2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV 2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2 KuxV2KuxV2KuxV2KuxV2KuxV2KuxV2KuxV//2Q== - - - - - - Adobe PDF library 10.01 - - - application/pdf - - - survminerCheatsheet - - - - - 1 - True - False - - 388.055556 - 299.861111 - Millimeters - - - - - Helvetica - Helvetica - Regular - TrueType - 12.0d1e3 - False - Helvetica.dfont - - - Helvetica-Bold - Helvetica - Bold - TrueType - 12.0d1e3 - False - Helvetica.dfont - - - Monaco - Monaco - Regular - TrueType - 7.0d1e1 - False - Monaco.dfont - - - AdobePiStd - Adobe Pi Std - Regular - Open Type - Version 1.004;PS 001.005;Core 1.0.38;makeotf.lib1.6.5960 - False - AdobePiStd.otf - - - SourceSansPro-Light - Source Sans Pro - Light - Open Type - Version 1.050;PS Version 1.000;hotconv 1.0.70;makeotf.lib2.5.5900 - False - SourceSansPro-Light.ttf - - - SourceSansPro-LightIt - Source Sans Pro - Light Italic - Open Type - Version 1.050;PS Version 1.000;hotconv 1.0.70;makeotf.lib2.5.5900 - False - SourceSansPro-LightItalic.ttf - - - SourceSansPro-Regular - Source Sans Pro - Regular - Open Type - Version 1.050;PS Version 1.000;hotconv 1.0.70;makeotf.lib2.5.5900 - False - SourceSansPro-Regular.ttf - - - SourceSansPro-It - Source Sans Pro - Italic - Open Type - Version 1.050;PS Version 1.000;hotconv 1.0.70;makeotf.lib2.5.5900 - False - SourceSansPro-Italic.ttf - - - SourceSansPro-Semibold - Source Sans Pro - Semibold - Open Type - Version 1.050;PS Version 1.000;hotconv 1.0.70;makeotf.lib2.5.5900 - False - SourceSansPro-Semibold.ttf - - - SourceSansPro-Bold - Source Sans Pro - Bold - Open Type - Version 1.050;PS Version 1.000;hotconv 1.0.70;makeotf.lib2.5.5900 - False - SourceSansPro-Bold.ttf - - - SourceSansPro-BlackIt - Source Sans Pro - Black Italic - Open Type - Version 1.050;PS Version 1.000;hotconv 1.0.70;makeotf.lib2.5.5900 - False - SourceSansPro-BlackItalic.ttf - - - - - - Cyan - Magenta - Yellow - Black - - - - - - Domyślna grupa próbek - 0 - - - - - - xmp.did:0280117407206811822AAA118BD76B7E - uuid:c9680241-c321-ed4e-8b0b-7f09debbb603 - xmp.did:F77F11740720681183D1B44C57A11AD1 - proof:pdf - - xmp.iid:0180117407206811822AAA118BD76B7E - xmp.did:0180117407206811822AAA118BD76B7E - xmp.did:F77F11740720681183D1B44C57A11AD1 - proof:pdf - - - - - saved - xmp.iid:F77F11740720681183D1B44C57A11AD1 - 2017-02-28T22:11:44+01:00 - Adobe Illustrator CS6 (Macintosh) - / - - - saved - xmp.iid:0280117407206811822AAA118BD76B7E - 2017-03-02T18:21:08+01:00 - Adobe Illustrator CS6 (Macintosh) - / - - - - - - Document - - - - - - - - - - - - - - - - - - - - - - - - - endstream endobj 3 0 obj <> endobj 18 0 obj <>/Resources<>/Font<>/ProcSet[/PDF/Text]/Properties<>/XObject<>>>/Thumb 2815 0 R/TrimBox[0.0 0.0 1100.0 850.0]/Type/Page>> endobj 2804 0 obj <>stream -HW[~l^֢Fr4/Mڢ+qJLr~g.$W][B*g8;3+W}_EѷF/߾lE/W+U$9/LV7Qv5[ N6Qث:zf}DB3%dLid`щUO10%ᆳM7|?GH,I$SR& Pd%)SM$ & LD 2:R" -56L"@;2K0,`-L,:r҄u9QÚ n]ykܹ,+Dond cB:| ,0qܕr"O30+KRI -[5VdX+e<cX9p"v\y)QWVRXpG<5B}69K﫲]_ran_7fkVkF3"e\ٱ,rI >r= D qq=A_DduHS OZD S,M9ñ'+p왼SHdifjQe_wP͈Iޥiɐv(!B[۬.O:{d,2 GJyP QrPDy QL0y"G*hV{ ^}"oO䢣)aUݶMח-6ҭZIG^-\gR @8wfœ]@UsULJYg˻LXr,wչp*$Zq*a@wo#~bVԔ1Iӎr{ی}AI>BPRNPJR_khTGC< ЧtG?KSXHXbhO@'=4[ی?S@ Sf\Ig4!TQ8#(7ѨzA (1$h44f%{;r5j6e_M(TS7f' Z |,cA&iT4n8ݮ憽m/{*BPNMޅ2ݾ#u<* <ozbYҘad s kuDŽ7nvZ&SG]Ǻi=R^U7-uٱrF8qxjW/Xɺݧu`Suvww͞}dmT浹cqmVK~9ĝ[hr[PW~ÑvuTkrCb%>.?D=pu_P; - M4w 0,H684fuyY!V3+YB8FkVPg 7zwٖ"p0m޳?-YWS8J2 * B|ߪ[{ɶcFG=w=LA_0=ۦ r(.2OX)fWuUv5$K~=+II$Rҍ - -܈hn<-qq!.DWӓ?B]iL~YaSٹcbv2a,1D/ݓ!f@K&F!rKTq>{GDY9QtIXfHD^dɎd=Fa]zAiiΆF^jr >M8V ޯAAr;/}^!=*L c&{Ҹ!7~}O.۪{kbVr|ms{g(,u`K$`GGݾtyAflwT؉tJ;$Mm3 bR* -F#̑ $:U=JsMy 3z2*Gnjt\#%DlةR;J=;U6TxEr9~YGN6YGW=j/J3*E+f3Myh*L)5T@F6epp-;ҹ;qy?֫m# X( 2÷EI\4w1 PZaC*I%q>ogfI()ΰIܙ{2RZpkEx?~3:P&*l.t.x[4 -klv;tm/xŹ#hCF|,^Ѐ_^Ԝ 0f(mӣGd -q7'=1cA;eG[ٹ73c2@_qs\(e Fֿ耮4| -ة eZ##+m{hFm\n&²WvM0y\GQ,Iec d@ay.DdP3uu|c޴pvAUwWdz0*\?ah[]6>f;fz:>~=Wd914cCGw&hF•¨:#r8.@hջ1C$ƹmqMDr ]{.#rPygw#O$TC㞩ŋ$M5s|Ӧ蹸^gWo߈{ =c "ww'֡;"Y~h4G j8$Wg&4 q$'70$`)o\\. -z8_յl*7l.^iT1jtKC -?_)M*a*n=7Y\\2O7(Td>^y]g_5֕i8^{7kp8(%^Z#V䰔ނrTf]M< -d <7<{ruV #~xCny<)jි#jfHҝX(lRŕZ:śsԏ gz6ʓ%,Έr]+oǩ^f`o/S=] އ댎2z?+[Z_"v %rm[ -8xkz 6;wq*K_s&``V~X&9jkgzC5k\` XcVvfYïk6'm $Ldry&6[2O5E<1x(|I V NVP\17׺85B,we+?'`B[X\ O; ~4"H]€+ӳF/:ұ'=B -` FȻKe+Vq>zleSx/i_TOG/BDg"ͻq^-q#G_A,x~T9$\!{Ȗ%9zx%y&dC6`͐Sϯڽߢ_]cG~ O&}r?%XWe|ǍDܼ\_vw{}gYzVwjasxc;2rdY,1#X8SUBi챢<<^?l8tRglCj/bj6ZWۗ \ߟ>Ilek -qCFwBqf>h;q ؘ.|h}Lch0E<5W\*K|9Dlpۗp:? U`.H?m (J'LrCۛ1޿}??_?C?!yI|eJ5|Oϖޭ2"ugV Q?~n/pF֨5!b6b_Ym,6s{b);tAqT954߄EX3Ct~j2;P͔s:5f-j0%:= (G -6LCϋ^zagjv\<@I:BW檊MnB%D}p@j'@ Bȉ \ҩE*@,-!lPq2#T~'.q%B` XZqU=NaSa+?J[AC]A - ;|UCu_DZ~+'G&uj({lf)” A `0o HZ "Y405RƱ2%x 8 MXqioj<6[-9V^/zj+p6DX v/1 rK!\mhF;$$sƇ#-&j"®\^7>9($Š+0ct*Ʊ.%Ypۦ! \@8l -^-#63]`ǟT`if"w.Ko2x)uN7Ηi]/=~-ӘF8]t pɁoĴ'9%RltJ^,:R# Q!D^v ` hG_ 2|8-.#z荘s6d`:O*NhhgjEƬ~>sH>Sy"ۉʋ\cMEԽ,nȀYs6eaSV1Xadu-P -Dgޗ(!7Rx`f^`X`Mhl,И> 5[eW"!3M%tq3ba6 6 -f0Em4%jaV g! ЂOKhF ?A*V>]_mK0r Jia_F)}afEK/vC8:+"yXf3>IfN ˍaz6$luM*Om^oyݓfG՘G.)4:Ǥ\O^Ε`r?*WVDϯ?pUF?HAd&upVUӧO{kMHw]j* XNL-\@]߼?uKС 5_)ΝՀ@rN0/`'MCy#2ERݏϧP*dJV~{SkWWK/AP$+.tK3LdtVG#%'"Ne=`B$ XQvv^}c{]CPUV\e$ k8|DZP2 -DCbM7 @|rڜmb !Wn0[: ˳55_N,uD6Ck - qK^gVNV8zy['֮sJkH nӖ&_?vmȐ:.Գn 4aЯ(xO CE=@F$$AFTV*$~oo˘Ү":7w>$m{EpKGH!7jty} -sSp V|x n =_z,4jo ]\r<-W'Ez,3LpnfQn۔o܄5f vnmo&d7aI&s&"ɳJu\!PNdRz$/}˞ -4o7쩐%Diٕ5%-]x\,1 *vAE@eX -U.\j)^0nA#v~a\ N:=o|1R ܆$p&Avۘe}xCЕ&w9θ6q/qOlHkׄut5ٟޱ&;O mt#CFdh2Z0y72ko8F!mat]ؓ2t 8A¯!$Li@~qұY Ku7x1ګ>M(8Ɏ=2ntKy&H6p".?dn -m~kuFUGHaF !Ga"mC:V :@N(Um]!,Bv.YfVYV}mK){CM͊~ʬWXWtEZZqۅ OLjM'+;T`,pnqEL^MH -?0)#uZccA)#?=.`{TAkǸ nB+$vKw$ݑ2$1,#鎤!;^#B(ݑtG skwN#Hb+bWU.WcGIKR}ǽl,u3saAWl-Pq/%CU=alv+Тz6lmhހww ~/_\ƿ1A`}ɾ#zE M>c*h:} ŴV' 5@`"RTܶQJQYR|*NN[w\5FYlй <"T0 _ݯqwS -SH⎍9X;QO]5"&X)5x -:ZecOd}z^GdQ旗H4ڰisسNţ("s'˒^Ul@nuK|J'oT9ܣ>4[oE$[xFcKyȢˣ0w-3$s^$K>+O[V &Mjr<%069N_2cHY6lIV(b1GM~| aMTDA?'=Z_reXa@IKIOI}G yj]HLjijOR{íʃc5>9_F 4p,&\_@ G+ɶ3vD|W~]]'s$I-9Y,5O/4oO#u -@Xܹᧈ(5Z}ZfYֶe{a|N:Qkڨ Se^Y9]nDCٹq&c.9nR)XE*7kXL3hb\3fFP>QJSZŨ$MmUiMf9')5 ?8<9kQTٗ&PNU'v/"xMn D& -'P@0[?OZyyNOcz,$dSsNRZFc#栥R{ީMS=U$, -u3?Gxf<*[gJ̼"4ĀeFpzI(yA-Y0v5U%݊EyDJmQ^_## -{էU]ځ8*&a,S3ן[ Z~14""mQ즖?˕#rtYYF;ELVPb0 :4bi0K8qWGҥጰYv .tWUp~]7YO^r}"S݌Bf0X3mڈ۩@+2-qzpn'u9$3G5QTTlKwZK"<θ{" ٩D=DdU&% (@&Uf[0 c^QPF R9,iC%yCoKyVL4cTws1*5L̢pij28FQ⠂82 -g V\jA55>ݝKQSZ'ϛL|x=n~՛Gϙ[bG͚Wc^ [}:SRaB}ƝHCEDv}j!͓SR91\-+!Hzю"+}Oے{,8O*^E;hJ^LɹK!FI趝8^;-{Z2glݞDPPR֣{2a)"ʈO]L'RDJn0$vLqý# ֘r7eIO_~}?vO )ۄPRvݱkt,Ã،gͅvV**zMN[>VVz=LN:A3(v+!CbxϘHHh4n%F1Eo-*ʼN:-djSm$"9Ȗlw2b*y/ۈץ? ).-=.uPkg#?E -=,9k}Ǣ( -MZ~bzӟ-Yd~ODI4?hRijypїLd@IJUNH>a{: -^UgR12 -X[O{g϶e aw/sę%pfMF:X3nbשeSNM^%(@URsfu#yYcpՙƕYxgjc9q7*XTgv杏7_Q-4(G:un O8kI(8U˔WMyJEf*X.]X9VoR܊2`<|X’?$p.mGKCk -os( WIHe_ϛ띱_=c&W'Mh}lv_ h< תzGJvV`?~ ꔻ^f']LXL$zYAޟT*ShTǹ#v ϔG֙S<[ʼn3Sy–.6O5bS)Q(%B] -'*3c#sD/M}o;(upA7ZLmX!Xa?υ7[Vr(QGw@}_.FU%͆(wXwFӏZí#y!L崔}p[vk)_-Y6pSF =7^ #ʬ$-4-vfV&S -1KlpʊӍuL2ԟ@At0 8q3nKć .od^,dE.S{3􂊪*51V\[\F3oVidH+;ܻawrϞLS_H='HjLRBnOEKdJI|BX< -\\ - bW3LQH1Ҵa3(Z~D'TĺqSB.E1ר\,|[۴<@^ ~s KM3} -d~5d3d! Y@^Z]W|~dp,Ϋ~!k$󯇧DH@nמsSaa u -mksfTѫk4t{sjKg3"y|uUׁ(2f;^ _& -KHwv8g(ě׭KzmjuPѿ K&7;qkk~>S+Ӹ.ע68MsRp ڶ\/IA>V°GaXy^+pfi{r׸M4Ffo  -DҁJ6|͏4n"z庾*egwƃ5A&T-ӯ+5l yB+5= ?qdA' op8?pP;B#I#8"R#5UKP+|~j*ZTj..[yBd|E؃w|_ >ɇ.0)MԖ~_smFih>)UR+ie0)Ê֞7.LΠHC<ő%:SK" -CS8KFM>_)BSdؕ&%ߠSQ[$.ejiǽ+ tgW+]eDϭCaqx9..Sք$B,3|7*[664_oZu˛^?tYHx,pDpDB?h#m86` -:>2,j>mP#I#xv\q4*J[vrw!UfHi,v'B|~15A?ݴe $wBakR?*ME&XdH(@_w/i;Z0￟*nV{&uJTÌԐiI_dG&وhߺSF96kf<>^a%^2!tmrF^#8Ә˦Cxh(|l[[͊>!j&,=5wt -_U)RԤ@UR)e]ur}#'0 ~a&L¹ltLM9E`a9=bJg7ʊI.Aɧax|OIsp)OE^MAc*~hx>!U'E+ ռȎuU3'\j5`7KJo}nn3 EfgG9,s':̲sUd*CBL6˶Ǖ4p6-]Vr2cpnj2cn{E\2g/g윮r yZap%_@yڴKO98|5=e$dbg؜LUizVd5$zLȉ|9ҝ(;Eju9ϸeyݴ)ſ]ŝ6<-?XxqɦƖurycwyLvT70OlsHRՈzOr6N*1bq9iM=E4R[klZVٲd[MT %Ae楀|(]vVRg>jZݓ*fv^*܏(Ulmҋ:5{,7"~z"/D"+]3X״`~丌P3@tqkGj=faw5.V-{ O E -χ"8+gs85qK5Q"μ@(GTי!ZW$>o)U8|i%k2_2єxN#4KJhN_.Ct)UɬG.;X,Bc5LE5V Z?}"'j1+{If;hxDZ)21S- -YWX)7  XY7 E ҜCWj%z#8akxJhcj %Ep@H%H!*Ny.X8 +K&!z7,yOi'=c[3:~x!cy=!.SG&c:߇ ^?vXDHZאSք1_Y6%V{ '$0)BJsKom$~y]"fWؚ;ýP$4wPk+p};c={lT4xW:F.QY'^G"k 2H;SUmUﳝcotw,ձD͡L ?Pjؿd}a*+ e.]bJEKGkU*M>*h.G3/Q݈xuh`yB s#gWg<GPӣINx9GeY7gJ̟ݖ؜2(RI%_qY|F!NHȨjoZ}J Wq' ~4Pˠ;kuAbC3-9C`9|_wÑ5պ 4|`wfu*Z|` 02'j6-Y,Oi96ɴP8{ڭF婴q B) 5<!o/VϺ -QFzR8Kh۲U.B3zEv^x,WT oJ,yYr=˕Gk|#>ȦF,7d74PZ?[=إ>v7nkS1G\<ͦKL^ą -NFQs/ɀCs68iq^#2ʬ58 Έ]Q{s4A]ue\J[ L,$sǬ2ZTyoVFq$-J]Ш>΀׫x%hel_aOK18'7".?ZǦw0grw,Cd)g{kP8dcL3;̤SErwUpu/JFM_-B??;WUo 9m|fMz@ZJ@f_<}?u!%x<'Osס&Z5ٷP>O]Pb'zG ;㓣5Ej}ٍϥ4)f =#y322`r]"+LiqǛlm(‰*MzZPv*gjwA}r-%jFO:"_rt2^r -ʵG4};QSTBevFm -}ȇ'yd'#~u^06gg_Dx`>ksk{r-$ ?>k!:j='z\TN`K 'u"N/jyQͻpi 0'5kk<"ឃb}c - -_$%i$J[1\&&< :x:2Qԑ-$I"1Q%][5tMi;qAex 0e67ጅ(3C^ƫ]!Wn*:ef^D96W^FVdrNg7fW]xn.ߠ?;j¿B 3Z)=GI:W?֣tU^` -43|ccȤ7j6nk -Y^ mY9=̒z+oi3Ǜf-Zv gXdGXgQSu}PixTqu4*f?Ҷ_:ʻנV7)Fx]5]76MkvN_U'{YZlTv.ݮ\9#gP|vBv;l:[JR_kzbQr@C\ ๭jzkE -/Y׻ i>WYOtӇϷ2lTL5n<ʾ5ϰAEmEP׸WNBkʿInn,DYF&u~Nwdsߑ0)dv[nqVB{mUzT3(}ҏ_ -;KDmbK2N-rgG~wN{An2Y_!cnETGGE!?4l]A5R<CyD -DH. UvWbM%L `G X4NhTPkE/sBYu"hC3"#ISg*rDO/_oiNlJw]@5ʨ+BJQVuIfte[<[֭U 5r=J?J2|Ue+ӣǓm%Wb읫Wz#XZ-3s0̞2f$X[$9|KĀC[A`M^47dZx:n9q$49nʃ\Z&^3\#{DW2-wBى'jWvzhB# ab*Mf$-tĴuhF6Ŋ8|"=ɚ(Uz vj #x!;n s`a[4$r -=B4v:KnGJ~hҚ>+./QW:JB-wL_4D -jֱ*C!il.-A% +)X%;en*)rRKh,2Ա -!>b Z2&w~ h9) ?d|X"@棔 rڤrր*~ :yEi%|+dhhq0'];2(;0^`وe`RI&H&d)Axgw;| Z[?[.)l4VE32]o_ҽ ѕ;|ylJL`x='%2a-h܃S0\cT"Ә>m'1 )v5 -eaB?okGEzPd @R{sD1­>R a#I)2]ث'-'E~]LhI GJLp!n"Fu (``!&:QIJ%.gP2Y6,T[ pC j2DH1Lp֍o]vE&V'cَ&=f3T=fFƄ'ů7 O2t(- FzvP`4vyv vӚbwL,r;.`HCi#YO(n(FgNH"= -5\L֨d5ö=JͥZtnW)׭Uzieky[៭6@ުkfa\$9n zHt@VELtdeFkL - -J\m;L u\Xk((# vhs%]QL~{h?Ym.t~FO1k|Gwb0V\x3cS8apYaz!jLul6EW5bXLIl!k0 @F\+?x`}G#vUv}%/jxș-<#_g2k>b}Բ{U=Fh - 7F+~'M|n*vg̩AS@3v#'^?vѱk3uzptBe(!m^;rȿ |3$<|ғY}n%PvFM?8't.(㺜Ȕf#c,O^3c$Hq/XJPpQX=G[4Núbg$ I!D`>;ڳVa=f=ګ] @7-6M+g{gՀLEXjzM$uviIN^Mu9#"z/{\+TV?"KuA e@HJI稑) +]#!;EqXURٓ_zYnu.Un=O/?.W(q@9~F(žJ_v{|*NkQ?]mcm>? 6m{n5=|<.3#-QtZ'X[ٛSdGtD˟P^ M%꾳e;(gw%ݽv<_<ׄϘFHfͺ3sKRVp⾳ \*k?>pA.׊O͂-+# ϷKP'.QIÿ#I멿NX*^^;BIkWLF7uK(M`VGqԵ&,Hl*'@SWT<.#]ώej5'ɹ`ͩa)7 _!OX^c|!! d#-6D-';Z"PC&S#ms_]W,ZhG1"߼2O_Q5D_Tn 1#ro3+Zn@ tC,׫WUW})1jLwO$bV,-ÄGۉhĉ#G YU?rӻ~b -6ͪ:v3o%Ɏ^/~DpfWO886zBE@nM1lx5%j -~Ox}N%gPꔙ*!Փ1#>M9i!"~ZV?䎥WGFӃo;İi{qyGoLJz4QB81%xOQYl5Pm4Jm4DTl3${2$[\2Ez5kYI}>l3g}9IcژNo@\Q ҼtvV=]KL+oysrLՌ9r\:+$p|}Y`oaox_4:{x.W{,"UeX5|$I9F>]0T̷Lc6hK&zR̉ܬ접ɫ=ʟn|UizVg|i#՟KjjbȚA N ^7 v`<ޞo?}}N6:VIkIgz jʱ}9~Ϲy68Wuz&Ԇܻ\jծ7$l]^K fX 5PcM["b窼ƈF5M6U]+?--*.0la3Rc|zɱѲr6Ֆ -RլZ3gRJmE0wӚ{mjx8jWlJZ1fNZvBw&=1.Y_r/^7]fm<#F;mA۲ⰽ68s&EqB f0b\w,y3;;i O$(axc4'{V wYՑƔt"ptq,\,],wXZmW$ǭHvU1DkȦ666?طFf#?8||iWCGC+vV#9m%6!$x,u8  -$']{ ,-Qs -[QT&_MOn[5!RKtDtQE5FլЕ% -eOV"%p4dhXqH)jn6"w5F@fi9Q+[E~O-?򿲖A{U7JWi%9PIJ -`%_Qǿ*/t8NI槽lIh -d OpxIJb$jJ\EgUx+>u#@Qq8q,` 1SN rzw͝YG%f*A*F -OUzf AOtpvG0>qӊʂh=-w 0\cJ&M}Կx~qHKZk?Ϥ!U Esѯќ9s^e.gH]PB-C* ÆߎÄcYbƗDM#f&ۚҖXfe{8{pqvjh]Zu"+^ҍ`Ǥ"ݲ8pM*4fA5dC6ڍC)9@z0je5FC 薨CΨ͵k@oh='`tՅ1Lk*%g!P -}_q" 4ZSB[ --N01p@Y-`_\npm)gޱd6a:!~pZKWtl G -"5whŶa#,-VjǕv {D%B &mM3Vn(![v}Hr.wI){I7.ZUX-[<6W]uܫ[Zq@Lxes-V} Ϳr|*odmrv}+0RJ骊WSl%F7LWJ-BRv*kƲT3;\ϛ/>,2Ȼh]6/QdGi9^qjɎ$Wԏ!FDYY-Bgzk$OD=c#^4 fsuǁ6aR4 |I׽3j#.dSPSvcf 2mڲ^ğpω> ~s1셀7% Ңk <1y?HE`J.rˉ.ƫ!"pso,6ʀog)VXn0GWUgf#:a!Z 2k&ɅneRG.QX$ -s>\1!W1M7̙q7a%6 96 &A -"VW=!j& -.UFR|X[?FPbF3. $x =V4ڤ.ŮdQzd'hY@Pft EXug,ZQ=uvv|@${4})ǥkJ0~YuaR*pq=SW=qCȥ,"H)47I5VNAO{ -!4|o}~7MV𿃄Z -<֣m3! f蝳 Kwra\=) -⌋4z$ 7 a -.)^}H00-w@Bl<A&7 H ^A]ёQx{cįzCcSKU -1ŵ6LBESi0Ž`sc+)q8w-:7[ڽ SNh!> ϴR/)E˗N_o1#-vg3}N;'!ƞA3Y9D4供>|Ғ$m*83? w*3J3O{$ /?qf#:uDm70(q)(%aTRRF*Lk7O!p9_W,lb5T[]i=mY(^rLH9'V.kMK~F{ \zu[[J'pDDhD.EZvaiJ*Z -3,H4X7R4.4)&:J.%% Hcnɧu@9{Ɂ]Jk:Ro'@@"rI>Ұݝuztc9%}8Չ!ai6.>;fllE%PXPfVU֖-Um[[lg+x4$,'D8o"4(Ro3w" Nֶւ]"F5ʖfhE^ -{"զL1:VǀX%$}/x" ^yRSRZ7pUSJi - $v$wPrϰ${VhFL[ަ(`2C۩R<zs&ṅU Q=nXp -ѵl~^ň)&JB:Ȱ%cÈÅgtj?ajr:eL|t+$YIUnv\X֗ Z%w!Y`MOU{4-@_\/)&:ui#*6Z2ޟSnFn 5)+C$(Gc\<0@Șܘ?#I# hş3#J4i3 P.&?8@3uցQy_ҁe{*̅ 6ZJ/Nxf~~ ve񜏳S0.]2v>Q8'. /"J5]J,ԂE?nqY$#;%ݸ;bXZs={~xp,fM7TRAwFP!}1;g$αQXO&bSʾ.IƇIm2Ҵ!w`N\"c'^Vcjab7:RK+Goy/H}>n/)^*RlG6Q{yw.z5I˸7mF0]W#II 2OfTqJU:Z]an志l˥o+Sf /BȚĴ1Y ȼi\4q>r1skWEs uˏn/n$܀5) m$tew#EK -nsI0XbA> -/@A[esAs@!(:// PC%DI~U1>j|5*K#qߴ㔶b·i=ǽ^kccŠIɸѪt#ɪ0dq`h[=Jb.k*dɔT2 1#h{nEȕ>(r,׫v}Ц9.dŒN?=W֨>҄ %wčҳ<_<% oqώ.3BZl ;[·^دoqB.*ЊlZ"8k}HL2[2U ]Ga9$څDS/a4*r3]|= -C.n*>5;Qоמ_kԗ.R_޼itI2uHےOSPԕ\r=T60-µ :X38$Ӗ^O6gaIU U#;Uu -Iz&&sYw~y>J2`EjUN* -H%+޲o΄ /̑X\vfId"c2:JƸOn9vMu7KthlJ=: * -sZ2>,4 L*vQ5;0)<@d}}1Ԡ WRPTAua´7 -rl7ljQ#7ŽWq{#VC3yxhIdpV!#r BQVx -f ]E/ܞ|cq~51S媋̸v}"ۘFTG(ױ 5&x0QZYs3+;+VsϦ]Um?Dw}-izK- -jZ(6x 7 <'XSgTGXRj'WSzB^'fWRd@`);kn@TX%㮓=$]`VGL -NXO uc]xz" (w%YJEN€ c$3nXv8l9MZ6ZHxݸ6{Ki`RݦƤf|vK_UMBš/b6ov%mv.ph P8rW.$5T?yŌ<]Zb|;|jZ W(& -Zow%E[i|>V z &It޴wֻ%2 pnm/pD HY2 Yis}{!(9=i(nZ[(bYU+:e# ]JUH'nF09Gp4p!ɦʸ5Q*VW -]ådsi12-qm-!LA&$(Zf5b}'`'I & 04ڞ}I}M FvuؙnRRQ_1ڣqӟ{}@VB&935zCohZ97@AyVvsD -Eա,pR$5*0b>p%14Kn}k`>czmZV7{:0lzk#U$WîRCr *˪,GOG=_.ZJ==z OaXשO&Gs;nʷÆLQ)(bXeĐVznjy,-}aBੁ͚^"l[ѫ ֥jAw0X/4̢pH~WB<]8YIόբ؛"JpHVvyDB6j][Q>Ji*B~l-/;Ϳ!Ϳ|mxfpu౶xr{ OUTʞONxkx$o鞾CwT[ȋ2M!#ޅ2rƎ<.}5*GC8X"sN=9v u,iyВ*Rߑz w5P5H-YcSi@Xx\9Q3^2;Pf~~QC -OP̂ھ8 La.v[kMj Cm^N4%if{૧+j8SDuq.+kj@Ϥ>#^q^`yWW幍 |nOϖSX^yOޚ%"kTÎn;͹r"Qw#" ,~ٴmxnQȩ s00!ܑ2v2g\JQ(KTOVGyX95sd2njs]9%? =BXJևcO}hUK ]EpX\F482ˏ]zqH*}6ϗ3o ΋S|eؖˌa84g}fUڶ=#e$dd9+tLqjGi'(Eur`&Gv?aΦ CLHn^-H-vO|?6!i3j_{ߛOf`5e @@N6:T477efa EZKg][q ɪY˝-{p{KN!0pL)YT-TO9'Pp[[lkllaS'S9JЈ4"Vcd7Wcϣ,XK >Zн:Z5\ӺJ]德))25U.&UaqV۱ꢉD Y#=X1p_ntdʁ4J,C{ʾ.Dɞ(¯wb.Ѝݵ3Hl`IJ 3C=eVowc釱yחۿnLHLxSh4R=!GX1Y֩~eqjMk{5yNp^b0W!e\q޾)9FL0@7&I.ܳ=j0П?|cvޒF=[ Iy׹ɘ`vLOU?TPS9靳LfF-p兓B`dC9nĜBLj+E|QkH~|Ek~\YCsjyb5g#N%৉E\k)6mjU=v^1Qf-Co?o=; -2sʯ: 7@oLVÀDbܙ |5}W5pW8~e4Cxr D.qRrcxi2rh؀hN CQ~xܛy(n#hTpE36@`L9$` .}"l-ʷվ.HaC~L#!) n0*0e 7@#@ƃ EM8,oyCٻ CC= C0楣듡Xh^h2SL89z jn87I5f!ӗϞn*Z뫸[[洇`ŤEIraOqJ1j8/.2Klq.Xzk*n`snjY#aw_KTuVu93;cfgVJXlGmbZs&u:Ču[@~<gdn*ѫ(/{ BVTuН@]3h3yj]u&Uh`BI<4\I츤g ;xCiZ%b/NJ™F%„1F/Ã)?r -0ib΋9?cw2Jzl/~wI+CBpk]ڌNQBmKCSډFJu7h0 (wQNy>ߕ2!F-}ڊ្6^3F2]k=Kyc~<$Ϻyԛ൥}*uS&UeؑF7 -qϥcXnI`UMW,rDđRˠ12w=}۫pܨ.Gn&@[ dx!_?P;q0^(,2Ce2n#aCN]eĝxn~)9"A-X8>qi[Vl8 QB,GL`fχ6&j/2>OciO44|};)^`Ԇ=_v:&GwV899HGw  '?y6S}4F~4WhMI0_/X: -{A -.Y=&Z^v Ap֖ !.x3e UhuIv](IIs6J& Kຜjz;.`CǫaM=%B;xn0ȡ-s6ypα]sh1μ}!-EozgSRRUժ+.S1I-%tla%qFkZWOQ Yϕ `juok9]:= -K嬨G J4lJ?L6bp:̏!f5r? '&=4Kq#~vb­λ ~+BM֓q\bhZ4y4N|tz2>* -އvüyZ֦#RqgLqh+|դ&}Iɚ4 -γʸ*liA5>v( 5' %a̮zJzwJ{ef#7ǹP0}~ `̥N?$KInݸie(rLr̛\;( jE)f j@Pz;[߼SK kd|܍ۂ5^7[xIG\y1|Knkm?6qmu++5Gle׭ F|;MF B}-\q'"_&)jun/JVOpFom(V8x9 Q6idzkKQד'KS> -Z?? ml.(VYS3eqTܽX/.stmmp6ze>]?m?PcE, -Q28vT-N*w_s;un1簅W*59{U"y9Ĥ/)`[ɍtDzt`tX^,K,,T%Y spvտ9J\%(H>>}y[ilUaJmiw<8 yDJf4dBUJ3kxvuHS'}$q -z Z] -s5۳9ż ܪP; -=Ľֻ"gpvz{8P9*-)5hd>ʘr,g|jrK}+=ͻZ1|E=1cϭ!jKWU3nx9X!D4?EEx]KU[kv3wz{Z0೙h}UghGS{[Sȧ=D]k+lL%WS/gG;Yzo]e鎌ұXmW>0\pg-r%^3gήq5W /[1xjV-KjPKV[ -0uScl -IH3M8RXD^JfƜ`>7KbA,pl\l~Kτ?a-:N8aD&Ab4]M7#Ӛ+AM]j&K$j.AX/sӐFlxToJ0>kwXa.]PN; m?etiAWjȵ+˦ΩPk#uA #BUI-ݛyuڝBDIՎfZh5s89$XA9Vi~=|F@TQA4%'lF3fڢ5'͟ꫭ$t^j&DOqR@'q>9ݧKEOεx,v$ v~Շ~Pܧ-,.[2K4]6̘{xfMuz]U?"9WuD$C\TCK^Wm&uQ !>PbI@~Ts3ƀ>q*MvdP7N ;SVTcqg$7Xor &ΛD]m&1|+xغ[#} ^.^"|~Ap J>#dĸcR(Z#]qwgεuhY,ͣyD۲iS\hj`[e%w-\׌@emH ys3E=;w\c+2wm])}9k/ZdhBǽl8TWpl';p!u07$+1u:F]]k6ՑVYܦP)Wg!;rf3o6Jၐ-J‚كȤO~J3w\2p/if![you#9LO̓))aY֑+$]UUiQqw1KS[D@~ukg)kЎجTZekWI؏ 1[ -D](!()kšL +w,-a7JDzvg!x8)[iN\wtiE75 -PxXfޔ ep9~=r嫍Üs[_Sֲb5ޯZ\VTP*}jFo9\>k6Z XG`η]^~+d u.7}"ª:,VW&qm Ѵex>%)RqCYIqra)&!Vl@V`jprVoxG9C} ;o3W>~X\\l0T;GQ[pF9a_;66)?OCuf\iϋq1Ay1t Om3WX?IL:seس5BQ&ըJh55R^юw)j!$eK nկJl̓5cGɓL,I{==fHlC)g!={&;oVg&"_e\r.6_t.֝=Hg9?S'^j0wWS@bމ.ʑԙ֙'k #m}0U{ϽSA,z05{C5 c@y j6FBxz$XۊLL"+ߪb7Hk 76Q(t1ߗZElKOl#06^t+!W:{NDJbS3VVeP-GXtUo3߀!hm0GZ|EO(b]N{St&mܣ7gyoJϜ4OӠصN%֭P鈁5% Ng`ϋZ"jz\!wN.X)˺ddΌF CqAiy̌[)H&fZN@M*až@.ԃH۔5:&2+f@RεHr+^|eynVqݞSi٦JbQ֚')i.@f>tx{LEM|MzDA]n=TPw{:ZՔNIArĖFA,HV~]N̐ͪQ̱H`Z[3R1d5Th^de`47YR]u޹]sDT=cBM!O%gmKVA~M$u-B**J(jh]+^F0#簗T]RNXVJ1 @ei=yuyO4Χڏ&XohIB;з3ˌYUWV;=XXb<)& )z\h$l4gI>aG- -ҳ A@t3Ѻ,R"؈CLH -+tY_TBA&@e,Q ŸԴ*7MGȲVwՍrr]e4,ل --2O-,Į44Wvim(y8Lhhr_UJ8+נ5'c&QDGHS0iTDUxT9J.,vEJSeZ`+^dZp<+Ȧd>?ARaALC7 uogx_ag]e5-Z'z9!e-,VPOl,O_ͤEmBS@>-yMcvDHȃ)2xJP*-y1s (?Ap^Μ~9zܧ ?vÇpB$[uJWzWpM5ǂ>:z舖#.m0㡎ZaR "7,18G38"a+osHO|984eYC?~G6> -Op `V5>,9ow/F&{ܑ'{Ъmfqr,@K GVn؟^"68 87{ύ^tᛱA fc)] -:~NCoɪ]J yWwjx>Oqe=ZFRn*&,=q a{HGmDCbVz!AOx(w<59\ޥIy>/]/[:E[*T:Fm!do_[ -\cX.qyeF>'ѳ&У?Y\VV^s/~{;t7#L<$#`I"y ~v^=6!*ĜJeVZQ6"&jMuMv_y3QuEid- +upkrՔOt)CkGL#]oQfi}͋3agӂ&;ĿH!K#DJ&ǐH4'𱟟)/st8E- #*TtE5$QHKA8c yoTH{g㿗_H%R[BSM U v*Iv 9u_7ԥ5& sk=L|D**ْ))Qh2~ ǟLUO΢ Ir6ukV)ɷ_V`画[qsgPa.#f*Ⲫu0a$R_ j(b^vٱ/OpA""*#flV=zN[ܭ_[`8@BSėxI0tں(;ez#I=*lsUZ++|5ȬcҴJ1L\nꨵ#yG8HқudNZ(N)TѿjK}kW-7vRi$" -EChW8д#|@ye]5tЩb -K,Д}0BBhRi'{!xh訄`)\ ->k9-F$|?^=1JTǶ?\. >5::nA JQ(?TA(vj:_c|N/,gT_U.̵ce;Z0mwXZUgXvN(bfŀN7`,wn2=⩩1dyZD߳ȱGMKۧ旙KU -fGjԔ]/Գ -9fs=yӻG'C&WG63$M:HI͏%e8CM2տ0VHa7WUozs՛d\ZxׅL cdy ^CF}TǣϣV|TT5c+-%hbs8^H5Ii_LHbղF0]v GP"p5Tdje?Iun*YѤIN6$"]a1~BHwv -GK~f{ MJI@sRRr-QJMT&HRhUMxOF~1W*׼aQr!g/'k&IR}?tW<@Ĩʷ/*{&Ja=K\]ZUyQPkSJϛRT4(^7L|MŴ3xAܬ5FjK|wzlޓ.? -,t! -ڥUo75'F :wne_jk/OԹ4Y -rw>mhgԫ# iЙ\:7ݷx eKg$x *3~:"~zϡ!HFRh|Y^_ijlEnW708OA1d;<-Uix$HUn#E@Q =c3 5;i Kfbۊ:E9r7@;4w}D9"5Qپ=}ٓc bMUiXxؔsֲ ]U"MfGjˡ_RHͅ[#~ttҡ 7g/H -ޯ$ ݺȓѐƫ{lː[[-lW<+ Ȁ51V2[bI'\ra1|n Y #HPs_WcG|^P}-KL8eĬxTcJ#71j,yw-V?s)LU$qzEؗw "+&$Qez` pwN rKkXи  -ly̯~ms#φϡǸK3|]9߳3bм -4JH8y^7T"-u}>A mマ%%%AW{Dԙ`f)PIj%7~2thM@c|=gpzҚO+l -[ r򎬀[3PoXc8tʉaޣ[7hĉw+Os4;W_؅߯IJH=c";{X\mۂ/^3u*(;fgAn`tBLMB/~jF&D~~@ݦь$ 5,+1ّddnNETv,Nj R֎oB"1y'j.#Yl^@{ LPZ&چpo@fbSNZ@Ve,f;jv Q7>c ΅!gc8UY! -d)xߘCt3D[%b+0dȂ\w}5ώic@3l^̌V``3HUBb"E>i83ǧrP\@M4HXqڙ a5fR ,4}|6;'d8-|vdrM8Q*2j{^n|oXfOwm`y"-rT k2+GƖ;` S**oa],$EzmKj4~YhzTh7Oiʨm_P% -YRas+0`u1hqZjrYb%LQWYr fD4Db gf9)Q)bpϵ!fzȭf~Dc3z*~nOfZ8T %r_LOWZ^3QI03{˱{ߊ4Cԏ_ 20 aCC8S:[SOk0yq~KcޙO!'է*bu5P=]>ީӜG-N"I sU4q#.ENial8 p8k_CۙF_뤺MQr9usw}3Z?c ^ǎ}f %-w~YB05s:!IJ$DU&.`z,}G%3q -tY>8#QQ#{r* p)SoJ0ſ1x B}";8y=`Ml/rl.kOq)Nnӝ*Bサ D#QΑy~+oxq }z; 7#{8ig7KYV -kVWتg9S"d~H C˲B)[,lc{_\W - 6墳e7:D SŢUKԍ_#|⾌٪0:]9U)!tFnO-R{L<}`?bL00N*y`[s>REo ɽ:ӤԆ6=gĹ'ڮ)m5S^uG % $Sh}Ccf,ZGL=BXb+lT)TU郵V9[9&gJEdߗO%)łҏL+Hہ,gɺL$E1Eƒw"sSd}uN`v35piF)͈ &q7givCf dNZy}gևˆK'>}ǩOA\,‹|eT1EķyW!c쥡G? Ecپ$rjߠڣa#PǣG k(?MMd1dSg9H -+nbbu-$y w#l{lLɪ1R MLg`;JE,"kw4M.FMddw 4xRY{WmzG~4T+ OOV10I[+<쩰OEH!Is8є﹊B9&s[D8$@dZ"jbU<΄I_Jw9dO(}kC7 1mM{JL;dZY.fRFzm -.1j[jn ^EkmSe Ҹ+9vx2xy5^>Qt^Գ&^`2ԧmld|/R9Tq&VZ -<%V-&35N@:5+. +J'FvH^ TrlzWlUYZb_fؐ.+c(`% \0%t~xnZ9@z-ʪױ]گ3m|fOLHpA_ICmm&.,hJa&Bp:@3Аws>M[hHS@]q"񞂊]߂xǁ 8*|<=MY tuCOے4Hk]u㋮\7=f!}ts&/Wj㶊3uSqEɫypr$ǒFVۦӋuStF>#w2=ͣN9Mژb^Tԯ+@RH6p'HmG{nt_-ɱ8p?xw'?`'-q8^IhVH 8So%[7דSvK:ӞdNvBaJ= +a!>}|= !ACʼoҏ;bHХӉ+r!Z7$g,؜[H1&1 Shy@8E$\۟,sm<&?#J5Ipr,92;*eHQZyHTESllwhԕe:x/DJkͬhoO=or)EZsɳ-zqϏJ֢?CM'|5k?voxgm/>wWy|iRO6Yѐxf$}{PgWΉR N֤s)A 8\Ol!C1gRx\\6NRogy>>Cgw& gfEϦ7|.%t%_#+ ^<2z[mINYN\εдPѱ(kL]]5)R~Kt_Х]cEgT&Ǚ&E:ȯ݊Xzb4`=kZnкgūӼy~,{%aNY:JU؏gwk\EdyJb1Gd;OwGůtkiJvg~zbH g$,͒ -V^ - $Uo,X~䫮>su'n ƛ țQzE -Qo='/ \O^8]B[S%+-lZ[O6toh kjp~ cnW6fz,3GC3p6YVia6wx\yg0v Gߑҫbicᄵ`֧1q&'m7XTk=W76|}HD4|nLbݬZ)nYmVK2d ţfVF̣ɉs3ڛ]4N`-V+Y vֶ&+);Zn3cSs2REZ2Tf̲tfI_@+4vyHLy5(\Oo9h2&2F -,SÅGw>@NBE@=a!CΒ PH7Vqo َp'|g^~X"Kzij}]S!VqZ?(N!5-ʰa‰w*vV ZFɣGr+B(*/%u|-_?\t?J~|>4N׌T|:qH$AxW֨ TFSYr$3lB$Wfg)[\lbGj}DG b^ -r#"10cdB1&5 K^9i'7쾓e2EKJJ F8Ðbpad*߻c{}qE:$GUN,S-+ɵ-5DE+ MBzsq,5zJ)-ݠ~Dk,rF/tgHŶ4)02Z#\iPu35lx\B`AGLW,3=۰z\5žE^qh3j,iztAL?kAh? 8 !DPf-$YcCWCU:eZ#[j-)jXENuHP.ÉkY]0a@ .2WEqt:@ IKB" o!%09yz"}v<t[DoNt~+?WUQ_.4`D)~n^?(;B_qY WVF&(捼o}#y'#S?񗥊cJbB.EfqtM1qW.=B[tUBƩ4uA͞jlD1m>p͛Ge\6tUp5κA#oI i?o^UIzhxxhowW᦭.CL -n9hUF zL ř{mxҁܫ;pM|#l~`!+,z.Iyɾ~X8zQ:e\tOiIZD}G$'-Jna;OwJ 6\toRFk}ROi*YH|\E(LǑ(珣)Vd-OT񧒍=ksBkƌlO@1BmK -ԓcp:pÃ,cCD޸D(Cw>yE{V0* Mxo{ޛބo$ў"g.>z(F,,1Y3t{[ײjoEVftA tfқjYA72wtS,>BwoF+9k#xϲ.(ƛzZ̪Ap1-2uD1/9՝](|@OCsđ/JGBfl* 鞐r('yԨ5ȝR\5\}(DSbMr-j e Bv4w~mBsr jgȻv=9( Ub:׻ceB2yhp],{Ӛ4E=G sTdQs߹y:16>j49B'/ mec}HO(@o.l kȥ[JZ}p' -C;=`l fte#P> A>*.ݏ괢HMj% MOdgvNiꋉʥES=Q5qd׀A  -jcC~8'!52X]gfDp^ZS { ל{gbɡÄBri(\wfp4&ay<4/7W[89}+sflXLѣ Oڤu0o1GA}a's9A$4V!Y7ѡێp&_œP翯Z`hJ'}QXpY>C"K#h*h}#wk+rqUE;Ӓ +uR}_9:.˪#i 6vw|TBA@}嚲RVʆzlPM.+h U4_@雅8X'fZr ^ʼp(=P5щ:\G!Q&z -k {(Ogk&.r5DOt)bQ ?X t $t\'-ȧ@ 3hf'Aޕ 쏰H|s}p^MuyACU'=;Rfik*c#ZV뛚N -G\1oR7!6w ƮVhZacg{歹1 J*4xvr9ij=|9s(3k _ 4k\.IC6m|€0|6f`6As Qˌk)yu@2s dG& ?z/6~s -SZN%)2HG;F"yS_x\oM)&bك–430TFM!%+lQ*"vI(Ǽ%Λf|z ([u3h7E;ȃ8".rf*%-քI\\ɮ~"ȼ;;g pX10KKgTf]KgPAE:;Ȅ^]O]J,zX&TQԃ%q\+Z?AyQ,؊l?liFLR$nj͸Qף[/~X{@ ۣ`^qw޽I|\X횋S$es[wVt;/gcfdϏyYC. 6P?s΍'%i"720+fW#OvWI?Ń)xԸsV0p++--cF Sc}//b;dyJR$ \У -Գ{ZY],{~#j:5}_.XY٫ s%!b_ݟߩ?"guԉ|9+7#neE⪄ SI^~Q*4 ;7e\0YSq*1iRذt =h`\_ıp,y*3kʦHڙ~ifgSb.#Tâ>IFgk#;cY[QIĖ3W4WZWƎ$8# gfUb _GEY)帨A*-jFT\l.GN H<=uxbqg}myDB˜X3,11J84ˤ~kȉ%U  %b}k3vOW,0;Z5m/%tυ`f9Jd5tSKxG5E3БlivK)SGߢͳN-N43 9|v5}tKQ!Ezr\XI5`I8X 9x6x;1>zPg ϻ~",sVH[kiLI|FKk29Ws]56@ٻ۫s75qGG]4"W7GdRV꣱Nr#HYj RdΦKT腬hdH@y!?mIQj%""}69~5B-ݻ7x/|eD@c⥏W㸴kNY*X%jA:GGhStR m 3zV*Hz/YJ h8yՒ%Gn>.0y0"deggƲ6 foP@ 黇:x\0tz>e-C讚z-)I H$nyT4oף֖nnoűS ?{n:SL÷:I?ꦎL9f ;cly48DtI0$K Yi+~˺)NB Q[#<_D9y1]+,GSb]v9j<9HQteNJcQ(^'4_k?5ʨ&p5ɖe_*^-nTAlE;JS?§[ga3XzmK:·P >2Q(pjBy)ffM2/8(TI;7)FBtBf XרGlƺqz|. /K -FɺiϿ%\$]~hjhD^r!+BvV%͌OD>~|s.;)@vz~iRy{^xoF<ㅐ8^oע?ɲjUXԧXYbr^NvW8#j,5C*T5n~Q9v &abnIYvK$h&%XVԸ}:qPNֹ-b< -cY=->Q$]<~fg0-+q&{h:@TԪeaf~=v_%$i<3P+S/8?,r@tfVW&W'I8f?n #lj@#O#H yT.UrsV3cԘ,zvvV^6κ@7S(yWO7fŚ#j(:V>M4@zq^F:??o_Kٲ宆4Ƚ{/:ΙspxրT+w{';]䳗pHB5;B|XɊ?SUPߛY$Ŝ26X=CChlŒʼl[a]0hgG$BP~HQ۟3rg -C5qNxȞ7r9C~8Us&AMf,@E݁r=0%ZL4`{j|h -" >ZaB_襓Pe?M(ݘ-';'4ϕ[r9m]&)?W-BJwYi;3?d^W#Bb-E.BOY'&tD84B= 5VώDlxvQ)xr:KvW"޸x[ǫ3G0~7UJJujyegCASG}d/G ܻBB;#Rwm̷54_/Vzq=%;c"ǃeр}?%F\ qjRCTEF63hMB-[}lXB.T>+J"l1YsYlV>='Ϛ\օC0Q_W!,zs . W[A!ؗ*MHzLr}i U FxE^$cl9RlA?_n*'E - %X ]k/VMgrLV{AZ6cP+pgU8_Ϟf0+T"B+w,&/cU'tFcW%Bjb=d~=YD٭>нC̢?x&ۣ dTdjR![9YOdݒ/0ĪmwHg B瘳}|^U~ϭ)_1v詷d 1slԂeϪFbY9{ƹX_5@Zzg X+ Y,8d ^]ύeANKJp(bi뼪W[~k=Şw2:!rO;7+,vYSgYcײiAG"ssà mInιAuv[ -1{ 1??1Wハywx!gDܾwDXY jߏ+p"nqk+\Օɰu|&(V NNk 5 #( aϸ]H]#đ 'DWǤzE,\]Ԃ>X6C1H"&l ?܈Psؙ)p$h>r\ t>[)oZJiGU` jQ|ԽtJF3HXJžkTBPr :D{2\+ˏZWSR,A}/߰@*9 !u8`|dKvaf$WBLKF-:mFa§ -FD - Ae -y)=V8j BP dަfΫ- P+ -tL'}Q4zOK.wK^7lY(}LXf%”`Έa\>]7C;7#P\.;h,+z%dmaqJw2)W~'~!rZktnUR]eߦUx(BJ:9 -GCzj_}C|rQ2.V"9WGXiS86Ǥf!sb5=.ty<5)R&E`k*̩rj@/f-Am(<=˧CĕdXâCJ;h;rD߽Otڎ8<&q| :{ fħ[anx6(+YȞI#a aB+Dq)4CҘϗ_d_s~܄,~op|PK~W.kcԢf?Ԝ [</ͱqO{ۆ00$R#3o %:Yʆ,|Db̃zp-!܈YJV,BW@NHw4R)t6ƹ!0p^5ڟòyqdGai?>Ç=8x& =vV(lF WH;% ubMf`B>-S8ݸ49(\a.w'ώ,&'& oy^_0zV 7!cK]b.?ZAGĔpmحS|0Bd7W{jvcJw,.ty\BY< )ٵ|.糧9?VuGiW{|5^IoY[u+nF0˰f ~Q~(\5܂$odC@Mqvqm@/E' ;Y%Sۘ鼔 _ByAFǣY1r${ -~)# -hc7DZOa]6$I+)s C4Y|1vHMYWbi,HA:(d·Hȴ!(Q$:,Fy'PKzG/nR_nݻ_r ݱ#f)~;xu~ Uu=C'B o6Q6bs֣>Bp7lWF_tg[̲cN`̾oonu%^ _s[ ٞ>r"myf3xc$u4"ieQ?8t#Hh~R\R3B{OABczl&uū%c3fdJqĤ"*o%pxiy4SFYæbaǁOqh]<6=(3Uż#z@pĭIܮ9'T(y7ݾMD HEۊ;^Cm1:ٿZܚ!NIru}+gY mkg Q~֑PꞘfή.UZ΅ -[dS3YGbvxjy01Bљ}DGt9&?@~,SЫ1$;}VK܅~eA㇝X^hp#=nzZeɘ#`$v .VA3 5,;oϺŏ5!XdMlTR RBA\ݚtQHҥzjݧqy9:=XE}v\&kd!a4 wЌYa,NE\x3f#b-۽zK t4H9;y$gI@OV7|mG"C;vnw^X6};^|O>\,U՚:d3T]]-cd)VYXNE+fi2,$ -"hЍN9=?*l-m{9lZ4W|y"_^iL3ӢiW9:y -) LNڀĹK}wӽOZTHУkOZ-;>[W OZn,}zJߙ2zZ?~@7O4k,; -hK#;2 VTt3ZHFVM ٯHjَGcMkXUYA8SU: Hp|ѥWb`o5Dkox8 r߄[,x;c՟(*#Q*rxزx'{'N @;:+dcft4sl4)U!̱l`8KNQt%QFj:sZBЅPb(ہ*<;Rؿ}v`[%zڃ[XeZ{-,ik v}k;+9@TXv|-qydS6e5RC^9+0)tIg`PKLPYL{Ti=a($5YUER%lL1%tVݰ$QﵯZ8=j+;1&^lQڷ?okŁ2V]k~slʲ\)0|::dTㆰ(Oq)EcveZ7_"sCޫy!99,;qtw EK,(ڎDC}5`>y^0*7,1U)ܠZV֑^6J p~(ck%/ m =Dojˑa[ l˖=e#RS@An2h}h |{dfi;ީguk6=1ڲ0.Ə[20(w[?~) ʟ8+̂̀P< zC۾fjLih:rz!>R*`bh 4Od@>T7Ovtkӝ4 -ẑVls*ㅱ"#'[%?S g]N7۩mze6U[␑70 ;%K,,ˠO/-XԪk9[ַP_k_q4 Dfqߞdq4c<|&Ck {0\142aWW[d%#KD+N+U-CLY6thSB$ظ -M݆DIFɎп9GN;VLJKXOZb6䰭^Se ɦ[lHį!-fFŴv$ANM4 -[6t$o@;90Gl it~O.4Ȝ2cN¬ US^Bg|pYTk5n*?N,n=Y+I΢Е>Ϣ EZcH}els©Yj< 9;&-B"_46Pjhwtom?Kȷ=iBiti%Nb`rUl -><`vyC,G>JVi$gxNVr(0Ls"yDx:I.2#]W|ҀNҍP^^)D=uU]F:.e>vA"7|ܧ~ 3cZ tʼ{4Mxdv`0FhY?H /dVDY /|Ձ %[]ʓ$ɿb&%$k^J8ZRܽW!oDjN?Q8V.=q?>cX3 q@j'p,S!gjIށИX?k.j5'7TSm1>l]SS׸1([& Si]A[13K4.-> A(k]ߨzϢꇑw4_E 鿪 8HYɨ8V&w5Y!%/"iiy ^Uȹ~Ieʕ};%S gf>dd!Vt{oXy8_'V膪1`q\"'ЊUR8ViZ.@)$zi+Ey0?%&\ I8{pnH5M v4噮#v{f333gsw +98n@iWL0gw:N8ݦYos֕أaA K4 7:v&!'CNilj Z -؞?4fO)< - JK9;TlH /WW?myq _kQ@XHV+Ee4Z ݉N|wЉ?B?|U{?VO_֞mp.1mo -Kk=B[42p7(3liq-z OYd}7K nr`hnΤ,G*7CG}\q`,۶F$ʉqvs)/LmlnX{0'|^_GJ>ǔ~םΰb x=?n/d&@@$XB1n4YpfU'u Ž~ňL(JC -p7Gy~ӏ0}ؾ/Ϟ w{h#=&|ii1C39Ӕc+H~}eۦ+-W *L5b,"f -KEط>>+HkBw?4"~#gC(woFH<[!ƮA8iN&q -N֪uߚ"=(j}RJGJtI ()VMscy{9ɾfo6{ٿͮȸ(;tە&58tl>h wGH;=}VI_P 5g`( *x)e$@锱Fpʽh4!Q_E:Q+29D{n@js5,Hm,m9m:m(1ZήuȓἼ3qigd(IsX:nT͑Р8?BYwg)ݙc㝼?+(CPo`k:]mJO_jQwŕ]rWH-܈ڏ -eQ G^z !xD!KzpOI4s2l5+nX39kTBt3 q|&k?|?>͑`2tMV¥+ 7_8ޟQ8ƞnc̓?Y@([|6gCxL)2`5 J5%MgZ0VpRɷN|n2]V`~\!ǍHX -+yWᯯµM W2բ0Z)SEݓ{H]0Xօ3,κ~Y;r'F(H%O'd恡n悬 ICJސ^qz .u@l2|۫Ok/nccLh&z ^˲SS]55կ^jsjdBRe(1[m#^~%q@t+M|7v`u'v8%$ ,āwx[7B+HSx\&qbχݤBtFD6Dy;1H X4{S^Ɨ`ȍ3!oݳ;TJC^e;H( @QOg?hut@%z]a!4t^'Ƿ GHOb WqkTy{MzdUTjw4N+,\[=]c*]`wͧ5ijG -FFдk8\yl5ܙfuĝ$H,5O -Wz;ou7y+~4Jh*m?4nP^N!8Nkn'u:Ӊ -J|@>iZYf=G(&ݟ%*L9X: HaS.]f̃llB i=N5ӹ-~S@ aGJJ3vh%5}(&!x%םkFyE=FF͂ZrC`'2 "tyLUYqF= >.,u+eߣKErn+Mu~X+\gIFxkZ}N;v|),t$66[Kk/caԣzkʦ lWgQGsjɫ*džY-o$aPq5ћ#!r5,&?e&hTJRRȻQt'#ӝ#ĘOZT\`!ſ=.am~ M3e~G½2eoi7 C(xR 2MApBGrю{[1 bhj=h?" -%(;t׿<+}D]9]ɐU2j@MSfl{ 疳 -̀Q U D[ϐ(GEfJ0I %\ej:I5j<¥,)"4&̣iK0<4{C>c`qس[`.!sѮHA 7 d+sOz\Jƚs%zqY0\R4ffB@Sf1׫{ a!@蝷&Ġv{i |p곒=᮰먜(T F89ŮcO7FjY)sAq0ϫ֕yTr O#dPGP=ϪQ) *9znXy쇦맑޹hr?v).|b$AvLs'+ -F64BUE {ă RoWw8Cߨ%-1(-nBGfHӰƧDQhʫcd @Y\x#(a6Y>;\i-2Ǹ-[ VAgGLhb7kRk31AkT_$ -@EӪem-azlG" s1=@iFߡW'P5 B1<#І1C,o=fF|1_F>$M٦xu6syfgXZ̸g+r̠9FU/;3;347;ݙpqKa-{{mq\8>fHgN ZzQz]z %K-zg; Y pB F_lVn|4WRĬ'bEK$ZrJ<(5cl"]Mbsd,Cˣxd~8ۣ}}s6X3ׇId7lW.`'7)ʍh潻n L'?vLyX|+z\w`vN8u{Eď*۽=J}GMh^ X=-WKAA>fCO;NFWNM+uu:&u1MW ɖYgzsJuRd^ꟹwY]c.=lMtR=?:IW6z -}ce(۰63CW  jDW ~g!dd9 -e %{I\B:ۚ,b6%M)[E#yVOy؝@P.,{E x0KҢ$bI1$ -2,I푌EJu-HCiu~̝,ْ[0Ie4i9yᠲ}i # ^ˉixnʷ[ vSlu;y.y.-σ"\ߢdw#ؚ#mi9bBX +}|S^dÅ ,>~ uB[NmjՒ,Gn. 9@&U϶HA?H0IC\@m>)7TJm./ڝ,o` /x6o5MznX%8.#9U;q2-#46gA$x#2j*CjLR'=d>{^5&ʶƬდ'BV2ſ)As4EUqb -XlH/&m,[GKȂٻsbV!65Y<mU0:% gedtRU=j)kW BS5Lq7)&^h&'3lN>]EcqY/>SֵҚ>mX vf&ZV9E躏f>Ĥ#Ci{bcO -*uJ$Eax~m_.KUn8j u3+ra`Zf+egGlCk,DRD)L$JVJw,Ň|I,tXqhDLrM8W̾6_7 ?#B+ehv(CQ -T?OIox/:$}ߣH!t86w]xT8&B" 㦍S"AkH:C)+|Tl`eXY80_O --A5"t_'AM2l͵B,CR W󠎣YeAAAMjKήz'n@#)J(7GZk`) ׸MHw6dlZ z"y4#Iö*`Rwq!FγtVN pg=e툇e\6 {ݚk̫T2ѾWr p=FZ҉'1GNVy\tzb 6-cऻRrfm,6NzQjȱԖTg>ca8T,mpP',L5TЬwWqDf-S57Tj 3/TGqgq>> ^訰 P{)Novj#܍quiIr~SԝLBi&eeQc[/b#d"ϥ, U,C%jK#qgxyS(+LG%KNW76,$h]mc(g#ywÝFyV ic r4 -lR yo:?{}.ͧ_;^̏\Ȭs{EMRT8t.IB!/lN=MJ ;H`eJ (ZJ Y5$9~EM.`u$OX {ܗbD"hT(H1(^GB{Yzfҋ?s3Z(2mbp9^zqSd 36mqb!8|BCL|?}^`vϖ%k5n`^)3O[!n #Eyge.p9 ibe8p#{)=*iSror)ony?^PZs8d$= ^FaEᜪ0DŽTQz퐸:DfOCrQz%ljdT[u"9{EZ,*(L=7MnmTmN; U`r=Khv/ taR8A3;ypr17$dFڬ!& 4(햝\'SG sװ4i(FE>Nm2nmQv7vP8 B^9 /`Hw^ 햚l~]]&e^|8jTwC4C-dZϯn -JUrV*]plKWLISr8bZVhM`=>L4^"ܕФ( Bb(0Em<g~0|u..CYNS0 nU`Kj޳ kX|n! wԹHkQF`(Xi%]bow<}yD a>.b޻,gr|PH96#9zTFgԛroP M'тx<.qօ<+ 6ޖjm }ӫ/6Mh]6W\4sL)[k=mt`{%r`~bpv1V#KgsvoLJ%tPk K?I{ ;@DùW}l$UFupwvmeC 5%a ^*H| ڰl٬$s͚ߖMFEC>Rh8|'I[d9iA'/8~e>WUY>={sZ.Rh}#H/Z5xhsTq%rBdۙĺ+GȊ -65-4ح[zQe_> y_q2s ȁzRHhfkZ*Tu*9wSiekN&k$aJ!>qm @rE FTfG=!9bZbz94L],iWdLebӮ;V׌j˷) A+=[C"H{YQ \\"'`a|VBkJ/ A1/jkVZMsيgΣYJԆ&6=禭^;bY_+zvok*e\ gOUȏ=aаaFT;eomRv͈4 6/vs2C3J!Y`U $9o@C sӼh+$O+jzX_gJ^$|?%\>= xf^,E' ^`X)%yhg.N}OV̼ǘya 9ͫM[> W+Iώgd Av*MlLDfYK1,\4oU;1s0j<}TMh6:ns R|?9 _-96*}Dx/*+s1І{K' #x:U3 3mLd)۸/ [vo$ 陮77Z'<-.~(Ҿ'?ٮ*]!F55`-Ix]X|ZFbo:GadEr5ʉn4p3<`cNw=pgΘ wRaJcPkoqx*HY̝r -T^C!V^sL<;`)ܽ_sE;7* TWF&=+>?ÖM$*I\55s<Rc:m&T9_gB cc<<*^$zˇ8kyZ]nC2I2cGrGGK Fy%n;lMI9gV(Y!],xOcvԠr+tW:}*6~ jQۑ]W6/u+?n˃I 3;YGrrۺ/񄶟7M*JE#Qq)$ޟ5OQzuS^By6zUe^tb?W4rC =L#nwSHSJ S՟?'5Bd&X&oikjŽ(/B4֮5Ğm*іXQDs]]'q2zRG{RwΟy4,-{b9`{jQ@dgf>@B=73$eI诞qaD9ۆs}(5$챚nc<W>_s9$Gj>_slx|te:SOMPכHUU~./?/)s>oDZ;]iaA6G ٺm7ceq5N0h8MN\գd 閖îY~g-?lOݎJN5ryI5Hv9W=d (yy/d1+u3uXRF =[a疔Sɟ+%R~y=ŁrXx@|ռd}A)LI*#=Vfd1pw!@z)LT69#*仅b Z\AM9u2, -ky^Bu8*r~K}%-4Feį]ؿGaTx2uDlYKYNbڅVW{{Ԗl@(Q[C^lVYBROl-y?N]JUhVB.a%ЉrföuO *Hqr^:&}%$8uaYsi9) Vfа,i\ULJ+ 'ʟFVj 7{T66?& RVomgn=ߞ`M RQdZu2!ێ*rSNS!ZTU¿,oi&*0|!?h $Ox$!ͷ8Ts^ -VxT;]Wݾ5r<>#ZFQ3/9'/{?z@*vag<cx&q5斎qi/N7ZW8É$vbu>޹~"٫[&L=<&P~X}ْ:nsuhw+_~|QקUWZ(;~ G{L?v}Z,/ f={fz^.{uxum8dzjQ=RL1lւAPˏ|TPY f [z"T܄9!/&XLxqg/+^zz-qŭt5WI=SskpX-\/ӨXwoMqA+weppT',JˠN%[{4Rz%-ABT]W{DaⵓRC<ԆIl!ƘCC:}s0[Z K.䞎"A>O[&S@1`p7nZL#ĥt)wrmB/;(8qLaHp.ne+?#F_tXl*ej%ӘjEjhϼȿ!_$>x'>Vhhe qbʒy#*$C4$HBv)gM/lε~c?ۛ ⱼ:fP-[7yܶ:Wۙ -Kt[[et kxMR!ѽ=Oj{,Y|+we̲RN.俦8fZ,q~N t(|,wiO䪊/HUmKV:/dTK(iQ 풺oA`?UΒ٫AVL4GޝSTV)0?/ל} cS?O}6zxdb|GJ$WVxe,d(.K(GlA#i(*vXMWk^,澊aO.l S>}>2vUZ#:T-cEl˾pg)N%:d*!as: 6s8fU9w`qP &8qMd#ë@tYV%TĪKzm -uE5h -ߩ'{?rny`)䪲E9uΏ+BvSKgBAfl)N ƒ9¤phH{M~L΁\l,!wX㉍CiIm^BҲBDVsZU޲.mB>{U({KW>߬\;_;5_c,>n. u *jG*-{F=0$yX~QShE㳐˜hcY-v299sD?Nƣ@d6fWQϘxSw/C^j~뺳^3?tY?ӕ%(}mUOқJf{m7/ݭe^[wz]vm}V5T_HouP4\A -s&F,ILDlf)4f,nLyV,Zhr[/pl4FNI&6~:~5ݩˍ$I(-Q -pUW?|(=~$CCh^:ieU¤Y[bUgV(OʇznNrWŹpq:>BYYIEHFzH.zǥWkUC# sSQ"= -Ljݷ'hZԗiGv1w7 -8ЫA9G#.p}QQ ?gP'N޹9H(qŦq4Z:OW8SĪXvV}^=9OmkvŪ bOTgxP5%lA*])6c',uisgV# -M59(ǭFygYq,Qq#KgvWWn|{rOИvW:xwMi2Ok 0m#I7R`ZbAgT=KTL4%d0c.)iν}ij4n/kΌf4{v00,ty`k<y#4 -܃ <ɘ=;6&s ^K^}5k*KK1p43(&Mu4q: {@lOc`*:0mGrc21-e纷t6RŅ}I8t*ԧodI٘p쩹樴7r!dƝTl%h$MLYߍ -~TTzP^Ɩ2$rf}e8&g8Y\GE HI{ͽ@+u-pX;7 CށuŽb k0#װղp-%4Cr35G2#hxmj Nd{h\1>]\YO* TϘF؉/[]T|UЏ\s{֘aQb{2)Jآuj})X$Ⱥ+n_p*! ̠pzžh"j")${HP_#Pp#nz;7^6fH,TQԒȀ+ilPWWܻ$wVi78?}Q:c`i4y1s{V\#V.9אR1P <ޒZU;fLm1Z)3Ǫs:=Dh47jI[)m3%\Aη0p'HU w8ߋq_Ρ::I2R\) -aQV߇_;*BRDFG=$E,Rs rRz*<]= -o~(ރ?O̟=tSzs_c)Ly~kG{&\<ZѴPfTp -=Fߝ~:| iX!{"R@#v^`C5X]y!ՄÖg#[6neцYc+'`̀I yZϻw!&ٓD#[˚r,2[W&m{bNV2Op{N<{fߝPe'-,&c-߁[3ۏ[ݧ5{?ZD%( U:(vrND'S !5#.Uaodvu:6OI-Qr䛦p8콜$UƖj^fOw0^VW`Y+S9't7/[[*! +eYP fӘ\ALKa-NX!4AQ(}{jlL6Q_vgcöXQ1El_@b|`<δvMmi85TJ2w)OKH=IHc2P#wđ6R_"V I9li6R7JJ VYf1aQ˗d:#GJRv K1r؅XzD-;aHckRp.0O*-;o3N,I7\0²CDԙOlz4k]@8d]4 ;f wyvE E絹:Bsp%ഥgYI~ 71{uK0"")=Ef+zSM,4E`wLsf)Wks\^c˦o'B%aslo 'Z;hF8әiO™c7x -V&/3Gg[Ǣ{Nf :_X^5&FX]9j@qזU`Z =bv'jT43,QEy33v]3;|lImFMbf -1ڋ0~p|E:umŢ99y`{Vo~z%66w68gF)mVZZhf]F@p;eH>=d;[&;hͼSe/Xv'-׃eҫu*`D⡖` M,#A8d^GKթ%t싍F#u)6|֒@Bs7XzjSܓԑf&~jq -aȬ04hͨZ]?;?D1_v'DEpbz}UjԖ"J$NɈY>@VOڐ -[zLQ:dp?x׉g6w;dQMV;!5]l6,tYpJFiuՙQ?{qq~0D?T__vzɄXF8#=~gruUn_l"TU L0ϞٙYXaI}$^YkǝRjxj0ydg'Ҳїa!:d|ϩg(e:gޕрUW%sVs[[= qOqpc(Jup#4RDhDqޞAczEӅƻE hrEH(!nh+aUD )~DG o'rC_}vwظĭ&8 3ܔJTfw|2k"v_8=C I%.G<+S}MZ-.WjgPIDn|Djh'.D] G^Ú=7'qbUpLBǯpLJ($Pnm HkgY^\+\ ٱ7ۺr"F=8ZܧșD& d6 R-l "D.VkwlxZ8J'wq}KKfqw\]5גBS ȸS[pϢ*- 0&1  p mWKN[[OH1B؇UʞW{HކnaW@E٬ʩcTܕAf _Lə vc(qŨ3ݨJ\S{Uq!2SXBmM[6tPA `s_DS6v}wLQK$jϮ?9yrF0d6Q|Rz@Imp_Tǽ-nz)1Vhܐ(JcV ->lʸZhF.Lksr7%k/x36hTu~ *w3fDt4au ͯ .IM-)ꮆ溴#ns*/|kEʡ#͑O[5R׈ SUs&,.gϧglbrz6XT1μQbpkX~vSakO|܃ɮOM;tܶ/*XQ;lK(;E=Xȁ8G<>I,h0D=o]^?&yhZ:n͞O`rA{ HΕl^[*a3|~ @b>j6?l=dneWpjS&O2 ˃|ʨyrN);}[j W6]/}\Jo>R }rhtz_*uӨ -z i;XFkY#VK;+X A:=no!lEVՊ^*ex8qTL_Θ{ ,?:Du{SND U?$Rt=u]Ԃ';<2x7:JM -G=ZZ6L$G-NTOВ|uC:MΛM=JvEK{Mpt\tMɉn&"Ӂ>чoQ~!R!T\U3O=ru^8~O:dx'\~zbkXcaTl_CZw5h`t6"#pξ>]铯)@Ȗ>3e1=vsHgЌW}͏g$<r8lup]GIS|g`Aw<2 -Y5a0m(J="yu%q9Drkh.Fg[1:Ą Hvx -a2\U ލ`x:䡻r9t^C$5-K/@kE:5=q0WΚT@&c"EvylyM J෰ q nt$pf7qփWl -ۗ1̓o7O8IL@#IP#Hv՝#ݫ S?HNCbG]?P "Ώ :;Y1'wd]OT,wXGPɞ}y@m1`wZq]"g4>C0ْ*]DI*Ҁ^qetWY|f8l3HctNc5q.s*?xFߨ ۭ2-$BuRe(gꢵSeOrԏֳ="i9?oº>wOQ69$me{!Xerfi%|VgWbYXanw \ }Ej֏4Bh=;iЯ+. ׂ%<ي-a0Q/ @%ܭ v>/)!Ջ>4>pf -ĉ,.E U..y)P6Wdt,xYM3 jg) Dx:S|o05Z׆(@1ryƹ"cjjP0k:.vzSx}-må9nTmI/Dժ\>exp:4*FTƕ&mfӮFzfVjni 58[eޜo{Nn%b:V9[mKJZGtUAQsl3KߢQ>|eڞչkIMo{z&eO鐬9%H,6ge,9#0&fb"9M-+x'O$N"}Ir>L 4+yU q" Y@-qbQ\y9wsCyc[`+ȒPq -\á-4‘3V>㖄[K)Puu_@@wֿٯ$In#iXEE;3fdh(eATbŗe§7)Q--DF8tRiDpN;k|7: 93Je<-0_K%Agdnwj礸zz?M._Dr^cP㼱>ݽI>bmI}B3Tr"K!!/*ڶ*wC]#Ң4OJήZ KOaѫJo[;.n'5 86V';w]~^X;o mU&WMGŐD4=WA 1فĐ>mz:Hga9:+JRohÉg.1E_՞шq>rb:( S.CCZ/2tDn -Ń~."?kAh!rxѾ`8KCa=Vjw7K|xk -HT_E^ }OKсV&)7h}8XtYڷz;͇?`Ơ !Z -ȄÞ=ͻ`u~Z0o_ p}*0"4pݿhb҆P`uw=id\$w(:&"p#^pHF[bfؿ ~Ҥ"tv)Cx4>&ޅ%R{3Y&u,qzWgV$=lonG*.X׭=&@h&!uV:%OLIhZ􄑍&)DRM]]NF v6zR|fk@xϺ TSw:QSL\v!I:SuZn{`!i۽"5H9~޺-um-~=w~z0=xzu%5R[XY -d':ǯb"%amQmҮ毶#Zww;^3>|o2u_GqJEQpz$UG<"cy(^>m3f"ۓ<Y5]wxϹ'˪NqM4YN`uG=cͥUTPa *TRb:A#'甸I#[!6aV`Mn {AJL?kUʺ5 cI*^'>MնwM_ȷִcw)?Ӯ~,R*f2t !n,ãrRv!] 6dnE|꽹_n!! -pW*! 5$kl0L팋7Aq[ʞۼV9_o&Wjf=vc)z_.T%hnr tb~x3LSe}we˜HZ"[jq;Z@؝}GC&W j*qi۸7vq^֒Vxtjd Jn=F^h斢Y*V$ާZ?=1>82 h#.:8ポ$ν^[zM~¤yS2ϥi8o=M"M/9i.Tr2-oղo%&|!1%!T(vڧUTNދc3 ]zQz$LVBfI#6\|q3LHyN[\:׏p)m; TWFԦ1>D!;–hyWl*y_D"Gc ĆqWe=8ɇFć]`s+T7ޫ LsvFl -ۨ$"$& -\^q/̋*TKHA>pؕ沎63ZjV& |@+3?CeMK~u@чxgl]x'w) u?K>W]1IrW@PHτGfPkҿV11 '{E&o9k ^ZSG$Iq~g ]qR}=_uLp}/[9u#Ӕ#YTXͮxY/KyyX= ^k?D@VY8sSfm]&YGQW69Gz4DiEа ޟ ' ۀ$Wfܝ0qDJKw)e#b)m]9-$(Bkb"%vD ֤͏K5K 9?"By$YO?++I/V\pn@~+uu2(L0G~ l/ ,/P>,@mƚ׊p- 9!q"~dF]*=85+̇ŝx|^:)Xj`\l)Օa-wR }P J ˫<*j3K>i[BAv~Wآ^pC";}oIa>Dϋ6n/jЊ^ʒMPZw R!E!܆r~UJ<Ú.]bo7@##;Ӕ ^o+JH$\U,ɦu^x -I\;?/ Vf5 |U(%Ixz}Gik{?p'/ihV ֶ}(!m&Zq~'|:n3?L4k:r)we~|LCE/ozFhO+¿,_Q*u0ZaϪM=#&7$TȌ5T)0MXPWf9Z# qts -]6C7?ct2V -/W?VeFF|7.QشclGV~O~kZIRQyi}H7a2vvIUvx˛UjL!ռ0a J}Tq<&LSVzaBQ\-h֝J -:,G6pB ׈xTީCL<4]gMG)e5羇ݯGtG8n62;fROl{ }%X2 ֤æf=UhKr`6cJqŠOk@B3r8wBEJ3+EMܖYNymk݁ђfF --JB~-`G5K-'?<@^FQ\Bgr4\$䐢1x+$-4*8 xNk,I`le8yBudsdP[m$$7/QQshEoEUA,4 ܃&ګ7!p%72 >tQa B'O|Q:`CR'J7 ?:cn񸑹C bA[ްIkM(>D+ei{/pfըXUE%҃*@cUSxIpֺfρ7 -Woc.kԈKd֏d|Omۏ*W)R)}8]'O,p(ҵMv? -wSVe|sxKiNuk y&+}a; Pۇn1 Qi,*!*|җ> @9MUٖ8d+g-1u6پCPKQܧnv{{bC[=)Kyt(RѷqJ_{>RfjkE))Iq5 Oz u5}t,y6Gc>?ϢZQa1Ǝq8Whf/wWD;s= ݿgqP"^W[)nI|fi~Mh*n ox`o޿IrS4A95f~]C̻rO>]-Қ F%GD4m{iM>=Lh:I#6#8STYPi[e=Z=˂9YP|~eN?E6ՐF9QblǂWK>mKHҡa%E*Yq|1lڽ;Bڷ+Ɉ#A+-S((7zƈwlά=qsd4E{ Ĝd4k[->tHnr6 %ѓrq3=շYz^:)5VgOf$I. y`f:LE-uE%dD rLr|QV*C,d 4b2%KV`2"6Vw_>jNJ^7ŠX,Sox"P -JIvU}qnow?ƫ,^s=0G>"s{<ڵ^,mb3ਸZ PwkFg124*>H˽UlbY8a=)`TL}뗮7vk*–ʛvBWʃekMAbPoa'=|jǝ}j {Cʽكd%&8ogu1v"e@}%ZJCɆİȯ4خ"k -)Ϲ8բO{ԫ`hq$x{6;GzTB1ɮ !eIP$B E{$b8vKѢuԌMs+iiY[{wWTśWYЄ@ŒwgnXR^=d"y}cEǒlBz86Bc}(BM?k.|׃5~7ǿ\?0Rt~HN#iŤs|}toy-sh0TeewNji2SEx@  @y )A˥'LJP&9Wm-=q.>3} !}Il[l,T~8)+koe1\6!zJIQRfȥer,nqڿH\/O;>dfm֢mT1{)䙌fu.XLY7Qfx晻Ь5In~uO~ -qœip>hOxꂛ]3޶%CI2pW| &:[7#gtAfH6M;1vKphkI -)ͭODsiCf;f`G?vr!းKqۼ?J"Ϟ`\P_j:s;QGaugz ^Q@O[{k/TIض PK1|-L,MViş{qO׋QJkHjȂfXdO-ys}e۫r|1nf W7n0 -h"P*}kR= U ~?j rak2l| --p+nlqe cAM"z<㑇&?B-2,xyZrkN>ͻ -6dy=T#~ - -']߱J = -о%L=Mqg? EIhl|gev_{Z#3X1;V^ -v%aKA{ cP#XuJc8 h}@V?o>R)5[Jk(}}c~H?yp|J/M&I" {ooW<+`g| J<&jW 5 a_^G Kym妀pQDLZJWDڳul#]'~HlێRdQlR| 8EE:)_|D6(ddVK]\P1!1Q..4-M! -ɀ>*6~&=BF2/R*>}{f' ?2 -/"12ekLi'E3 r=3ܸuTkow?~%,n\59ܽ%T'*ݗ(䢼,O֯͑͝F1=*3f2Iyۼ1s:j"eӆdO̴K[/ל2OQj x৲?3V+2Q6UvLM.ԘW+7~Ơ^i5b%~(N0?~lsXRΞ3Tw9?UM]Q98w#(,;h*::!*1Ʃh\.N*,j.. tSVB7mt:«cɊ̳̌Z[(amu[3JPVjӑb`V'9N1:~5_}3sc+ qcH|y %=">`7SBYE4[%•6\e5$s(,<=p#2Ms'8WKe80X(*.Y8o6.@R.r$?jtڟ(İ"w~qD#n?Ymzss|9 QjJQc}7Bsxwg45ڒtB<\)G+5 -ۡRdzF CK6ߝ3Fy[{nSwCѻѻڌl[ӣ!U9-_gD2Q?WÌiXy>< "2E-'|iL%3vc2ͺD^51ⓝ<\7_o pT 'IBQ@E?rVJb?ƗZ(׎-u8=!t{דn, wBկ"=R*Q qA81C#V*6{nW>N6@H,5|@`idTZmM_r^l&bK|+#Sтpj, zٿz M|B9?=k?nBH@Ev6YJ{ۤfG6Fv @c̀?2.^IYg1ELxQ>S;c|y~%f.۱qS=8˯-9L PRn[$?tjo6zUuṛ >TDZ %Q8^V -Rx[3sH=]Y;kw~1d~!yC\㐲3miY ~D]ې=izsVhe YPHŝ s(gÍX?ӀqjM&(n PX|'ǒZ}nRQTo(0_G #5{[|7۪[S1U;j(tkK6rzz{ -&OQfwñF+dw _CHIPIS20'G@ó"vU&9C}ˎPPAe=GtK ZM{ڮMnZ$Q.HqkD#aΗ tɢ՜imc}?[E^e`L^BAgqgPqdk S qS^VL3oAidYf~uyZ$ b̤Q('ϣoIܫ ;][s+[1rK}1zo BGH?z S$h)䋠"G$,EdZms1JçhVk -L/!:CCy["!kyuȰDCoyKg;\YU2G&<=VREʩRT\{fI %3+Lj%8>ǛXcT[},xrɾۮmбXVc}k2.ƽA=47f4$"dz& #8+,C \ ;C -hO+S +ʎh/H%2덙7f3f^՚U5Hn{[_tk \W<+fIPRByy{?FZٯ8Vl .@7vutLݓ\'0= 8͈KDw5xK gI#Bo.EGws+bVҽeri̒H!)X2c}ծ=0RFJRUkL<w|sY6)frw'׽>g|?DSED4Z`Ho :|;l rby\>zl03#uEX^ǜ{|cD(^YMO5l(ă0oy)zmi5-DGr -:fmT@svl@oc99 9#ҌJ<\j9?/mSۤvrp'<}D}ZDcZ@\;ϫR1ƻEJD^xBY c^[Hv sdOxUO;qQ_ U<yv7s }b]/2r>G MnLv}?ҾE-Hz_we%NGNLxj.eAXk$=TwTU‹OwF - BL 8OUoTWc}~=Zn7<8b྘|Xw&"e澢}5_|P O.0 p@X!֚u7mPMB§riBHfHۙ:- KTaMW*IʽSћuZ3nL{&:<3 œA 4MN]3&vZ -靹D [D,`m93\C/{໴u UÛۢ`-l{YAHM,}mJk?x=@>l38iTzOZVǤ"6;-yeZ`>$ Q wܴ@=%+` M#Hsiy8pu=xjWv(N1*ͽ lKv9}?}-Vv`-ȩ*2m^Fi.LH k՝@ ޜ[T 췢Iߧbe/5bSVdc-bSF)>R%^& -$RVꏛBΗӂߕ(g` J'U㎒Plfױ^HHP:M(JXb>5C%&â\Uo zJj4r0M]cq~ Ë)VTvC*Kϸt?4rZJ^BhV z0|6 StBn^kۥX^5، -1oUr@r&n?朧Z$$[I+G\b{]>b8ES< 3Ah쨿Btz%Pȝ+ 5b#-y(nA%ȸ*G?>c%4ź Zhp%DӞkZCkW)tv.f̕._y+pw>sY'ZrIwd'W}OSҩ8.Ȝc Fw,$hIzmH*$f{}=filԑ-u{x#|Qj2!>r_W^^jиU\8^fc} y'U6WVp|9&+!QgQ@fe -ZD"~M5"R}ޣ7P5hTfHg^cXPZrjxXbTّ7dM'"v=_-Lq O/"ɱtC)dp߬Y[ m+>--Fj;&Fu7<0-, -F;?G.05t,z%']OMiZyx3#8(k#iWľӻbyg2"\oQ°*Y#vJo4[f GHz! W15f ?O>5s7MD Jk\c*h.R0pZ ZbJBQIIď`\)V釸 P2dݭ֢ i|i'}4 '\/?չ삅D|U3!г-Ix[7KlNKd)HYF[,uoKwQRq('y9b{)<ީ gPtGNr G\,-/8`m#`OZ'˕KfX+2|aH| y͛a5ڶa $5&^9M6oCin'4U߼f4:Rh]v~{`p$EgϻrbC]ל'lZ3i|loj@ﮝoW:!EJ+)&fTP2Dxܮi.-qRZH[ -m˪~*'D[IpkL|,Wu.H%rns^=3ft(aՖkŒˮ,xͥ*.x4DTS}2() -`̠]3g@8Ex~Џhc>?I@q`d!XdO4MĝG%1/$*ɩZGdvǽl z_7l U7_eɑ:\=@&{z X2us2" Kfr왱~uڏW#р 9iPH#Ka0υywx[.@SkQ͛JA4`Sj):-VuB518 -1v/%vwzZ3FQ@ -bz?}X o9F^5u^n#azb5$&X<-Sx3z_+o>q@' n$冲Ɍw3VVğ7jfۆyVj}7ʻQ9Ɵ{]U_<G$rx0ER^a46 tOOVo^ KN(| 7a>VlmJYXtM0)s'ؠYTz i+9Grxhi됇e -DTg_:s4K!XL|*Mdk0}'`#;HPʠ"Bqʒܞ{='e-SW̫+'w&k!5 _`\8SmyB$011`\cQ 3[瞿ʾv)lZc6r^;r -btܗٜ@tVRO2]8үVPļn(Z,HIDn=&~CX1RIHu\fTK0ْO:zK]Ys;H v +zlG| ;|P6Xarru{ n#yL}ڼ.Ӈ-v+הc-\x}CG]$QUQ&gwjj2LJ8))Jmqla;.ʜ҈f!# X訐Y T Oxi"]0qf 1|6߅7 z3@?b^:oW! -+$|ǐ3 -'ܝJ|/uzHΨnXLk2.mYEVzBU%ؽȣ\M'f[슖uLusRQsɈ - -S cwWkW#_} %kwzh|nh Yb GsU\75#TqMO5]P5Ξ |~0%xm+Az m[i4Ӝ\X,g4)kʻ -~/O͠9TMf3 y"pX -30ԱdEJim,aĖdzeT !ޠ>^`J4@YDUr?mqApiG{B;e!cu7tŕ7ѳo.Ek+KPƀRcE^9/DY֮c8nb*셣ec/Eg[}3aOa qe6ͬtk0kVmk(v}4N?ǘ0V[i;:ݓp4Js#6`{:ƩEa3ȳֹ_HOkEO^_EAhRè?~Gvek>p+H@g== ''$c[ՋF{(So%>W%>ę.w4%} R bw85wI6XmE4Wb%x DD -^!r>TQ$>mm{6 n0a:G==a"2_CCWͥXovY|Z5oުO̓'7{sr~ٰ7-+}|/`(M],sIec5y;uIոZ٪\VxWS^r;.u_D᠃;wWLh.A츅Nj4N|+L*Kف[akOTJǹ K!6db08!wd3))UgȤ^1_ǓXns\~K'|KN0nǐ~0fˆ@+l -ia;vBPBuCH\Nq:'5լ#׭Q\+jLK^'.˾ߞ O>&ixyi~Sdٌ*5ɹoܝSMRM:LHRvdxy{meGfӨU=*8afHF[\g1n n:i߽w~f]ݲT_{6r -|i )S+!,RکSryL‘InxʹRui`c`4 -ߙ[ԸQt|n$kcr:R[K]6j UtD5zshٖ:kDjyu1M7vi%4@hjqQLYք׻3b*:rNQ9]Ꙛ-Yn0(!l_r!Lћ%p2@dg K/ +*]?:'9nibN8gAoKBZ]<@: ; gCDK т'hDCH23]YBI:R2чmd֔O.e~9٤w<&ԫ>V&K~$r{1>(Z~ ԯNC3xUq8 ey$ȤM"oq9upr/+=yrEYWXZ (~ MK^ Ā0ha Y."(HE13ZY&eY7#*d={la_n|>:ׂ$ a6epf{u. !Wɩ:fBɧY/z-!ѐ9zcRPx[$яYPRi) hO<{m(ZjWܿ7K[z8gj[Zͬ9 J?)ڹU*d lӻbƼjs*FRU55ǟN*atSI!J OÜg>D.7 5* -JAPdW$i]{u2l:.̰%.=يMJ_t;8]+Bc8KM&-71 \?67'rgٍsMb!LCo!ao)XΠyrՌBfMd)l|Z !#S(c[&|}t -`Ú衆Ӧ YM4sImRƀv^1(/+YQQxQScas0|r,|Hҗ-7zXziE&2%m,`ߴth;[DhWw7 GA!6r}4&n5t>-8qLjDHC{6|Ï\bੰvhJeyRB˟́v&Å( \H2H9+6;ZJsv.IP?byy/A]U@DK8PJ7(>Zpo9z·MȵL>k'ζn+p2e t ϣpܦofL7=GYIU&q-;9S6ߛa\ E B`_No;ZFzԞx/"f5H2R7wڈr1I{S}@#oSyB#碣lfYxy{`8O LR%25bWHi0L޽LowD}*ܲq'?TʐMQTAAY: mFh?9t$3n+zx)]uZ밟38F-4$ѭ~x]H,Qz}r6_3*{K[W0YDPGj#(cmFķ]tC\"@"MYB- -dC]\B&;abW 吿2וEQ% *F(wX*ѽaPRd\W>GޣR*QNnk{] 8d>hCh5p1N5کyhnjӾ @Tf|YET܌uuUȪN.;ѽNv_qfͨU0*[R&FS-1̜e|]X2eEҵ`X{",,{Xv=)*zD% OzJr9_M5WW4jmqM-8=iP=g0mi'|N6A V4.6Լډ,.P5հvvGJp;i3Qԑ~;(jKQR)"|Orw-\hL,tAYXv""Ll(٠(2kmY#YJCEb/Va΄֪vdMHKhv_ w}>|QƜ-)֞'_ZR օC:ANeH2Ie:rU2eX CcRreƻ&0JEZX,VCD'_#qɟ-DjF9X E1*ا -j15WU*v,}G>4F;8=dM(i[weN4RP[`="ɿSœ1o'I fz=ˌ7LKtѭ!")`O+LWxM%5]eQ&6ǀPw{k`W^у;͔4P+ -} lxŲ{ʰ\5:\|[N4*ݺ5c@D8mBܭ_&8.#nVb[op<~QXpp2!|bCIfF1> -kv G7MtteDtBHlˡk{GfЛF1խ$Z#9T}FurQ%qj1 !]ҟgN{vAܷ{,>ߧ2t~n dn1hWN @xyƳ֝ -M.G]p|o6Σ[>ѯճwxqn=kl~6P ^4a~¦/yޛIg1<"'ڶXZFs%ؿ$/"Ik]rsa!yF5Jk|Pڮ2*N*KTJ贠YznKOt1ʥT3kDz_Vr%[R2M'/m=Z9X(פ1qay-h-zl^u$ 5g֕jyvhlb]^"?ϯVj$X&;eaH^wSwxCO cSM)J_%R\MȨf VfpbqRLlJH^kBJ=2gD8w:¨!>#x *5 -ԥn rAT%?{T!v̾bQ:Fw@h0ܱ+.^w$OW@,ɜX}map -t U/BjlkT[8Pu0c[Û=ף@iKhDҲ k[PA^ 8|7Jmvܹ&e6 .1KϐbyHÕThr·B {UjЃ&K ݁`(| @bXBs.6+BnPӄfRXPYK4TPk\PTڰ}*8䲍LﶂgjzhƧ.-߭3Ⱦ~!axJLm$⑫B{Tz~ڽ{a"K ւF3KT(#{qJ S 2퀆sJ<[I("TΣo_-(a0QiWƮ˚ڹqTqtJeӐ}}/iO1DLDx~5Ѳ-KiCZg> e~*#$7痼/(7XH|BR'pKdۧg伭 b"$Q!AR4jj 0'_4^Bz%4kqĄѯ1!Aj"95.u+.R(LdFZWuWhיn #:lmXXeב*ˎȁWH_l<֓eIrK_{<}ye-~k/x mq'qцͤR6Q5o%Ȯ;&[E3Qqs?nD36ZbI&Lp=pJ^K\ TzRJ!8SR쟸YhQV2CIhxz ?aOXR}ЧP]VV6b҂2}He= M!UWx̻eekl:v HF2Xh(db |$U&jSF@qhwDsDQRO26Jաm '-ؙTZ&@̞!(zOB㞕Bӏ`qVFD#yDD>7,g6~ -yM"}}MS!E4tlH@F$”J\.b:y9>Yسh}Jk,^XLFx#@ͫNRV0㠌0Hs.R1(2~Ps;)[bj?u4R)́tī&ؾ0WjPe`y%LeIܽoaN|(JbvQe۸\Y% S^X9eo -N+V|].?&r6)b6z4s\d_{C )zsXN('Ѿ_]_&G+ OULݩ'OBdRNLNJkf 3mCɾ?5['saNqZ"σlDI,\,M~?c{"8D#eg=8Н¬` ȵ$R?^488'bRPaãqBjc]:o0@iϼ<OKZpJL4CXn%WFcN%g^ZPg>T[A~dΦ${1[Zƒzx\?.=t0eAg8O5%ظrqS̻-moeX 6EeWdsv{^э*Sya?ڡZ$mU Squ>"lRۤ+L&I1t9o9{m!#C]}M]^ƨ^ۇln5G )Zϫ[oNпH@2u (ʈ"ך(ݧKaNMMIgVCa\Y_e]e{j&ηr'P&C?K8aU6un;n* ҳ5|gko2,|ecl8'ךCț7t3-9VV$E}<_NƊ !.z]1 0edjqN;HVc)(P]C@NisJB%`(dB!1m4vf)lnû򪸿U>߃~ZuTWлQ mh?шFK@wtMÔl\ɗk6 >h>J!!}ydJvo+ Ia =! -MS"顙87 -,o=VNG -IIH+6(,%g%ʷTߍDyO) 1-^ud6VrgnityOi/Ha(\LYVt&P?ۿ}J^~)]-jd3dp))G*JwϨ.pRԃ$Q▪ -*%.]v,eb`v~Hoɉ!0q;URzՄõ XiN$Ƴ1r>w 6njxj5ݧ1wl -t~-?įxY}$',T,&Rϝ>1lz9~4i8SFmU验,2;Әx<'{d(WR{ɓ0>RՃY0-O&Ųg?v~/ί}Q>܎\:N)C|}#M~@Ua?WIIJ}d̩hLI3M3ZFfd_<;QU R;>E/ge7%$FqYw!$ -/O;Ï))Q4N?H㓞lą TJdPkuᓧ3.GݨVb2"y^@R*)1VTGms --cKCBcS rp7:T4kyMW>iHԯmēɚ -#y&B3O}gLT^7َc]{y`t}" 82)wNwKR94Og#-HE k_=&<+/ۗ_^Q͓M}c Yuzke僊ڰ| -XRڙ?)܅[R3)[M /W8b4vV8;F ܹstR|r'0e K0( yUp^}!h[8fLOU-oќwkySx,|+|VaDŽ닇&WܰQoSE%+-},kǏon N0~e ,׊s1HPۿy}WgWskzܘ1tQ, +{PؔV qT|3>B{n _x `YWd.^!g#gh? Wp,@ӕ! ÛYN"fgZwg[5IX3 Ab6L߈uq_JсVA^lF(@woeű鵲t_hٰ̡y3F9ZY:<1J5gphNRhC[]_`.n ?焯8i,p'>8t~Enz)6g5]ZpFţ>^n`|b/vt]Qm{D̶J ТaJ83ʹ_N1vk ŝ@xÿ_jہ,c6Tk;Wg}`xIsGTtQ\QŽ'Cusq!@.xS/8;X8y~ -!Nr. ;Ii@ b|mϕlg]m1JgVBW%븕~%4-l]']0%Tdֶ;!;g 0lu7@n2X{UԕP$?zZBLexV>\J&n w)u_W[ -(ڠ-{ZRrtû#m4WYB7g(㱷mel-}B /Vd5Z;wz!/օ~ޅ- TioO֫K\WÒE '%29*b,Ǡ :AN>%vKIft4!lf:G!č\"[@F_57gyܞT GXCNM+LdoC qGk;c{ W lS@6%pg>@oKy-,^ua D8Vk9%>omJ,8hv =e`Gy4G 4U=Sf(wM>эPCҦA b;~N@іP -c58@wupj/q=;&R-)hؽ-Uͅ%X֣M -å#\?\!Vqi5?{)JyBjUB%6"4i^!A/i[K~Bך]"@ dW EB@%i}0y!|9 *] 23yw9*xM!lyl?獪(}T)ry^'WY*,@&@8z` r9 R :H -~`ޕ=*e7Ξw8,,%͋")oT"_}8ky&a%_εO ;硨clFGς?N͛2V2ٛ? Զ-=Wa4Tb_as5GdTZunR-gڐ/,yx oL_R}0W6۾#.ᤊj\[\=N5J"3 TJ"ĠR›PdFc9+nvv{(lWJ*ӝONԔa~."H^{ -kŤw+ )Y'&MrK94 ~A$K=\RckH~wK07$Gz뷱@;{JR"qr6ȆXC%jTRPC|'㙇|^'-t}Umu EZe){ہS\u7dԹ(]_UY^pc0 WKE],zlVLԂ0LZ3ꨙUNB*Z1@VZ%jvӳHΩZ%+b,Xx9@[*#^ %|6Rlzu`-y*I\Wg| @I~vV]lQspN \{}C3]kLo~&blf=hiCA17״@(kò`Г#G\up.7; MZ]ܓyufxe KK-gK]&@fv_ޖg _=uvfgVgDŅMR3o.aF -iQ"lQpSME\Bf>:cdVzR -WBeϵysAg@0b:`OGr}ïOQY3!^9ބ=p0,<:b"ij1LW/PP}KacXI)ar@#zafbY_!ti3!RQx]6WfX?'hANᾸ -ODOco~~u2L2JRۖ]ķoGmkDu?7!2N_#wЩatR tGimk_{HCBo$ *\LJ=Jrf -<iqnh -1ԇ/I̮ܷsE!3q\jZ1a|OV-U#^UP\)x^j%cxhv#;02{q=U 4[ߜlUq4qk2 }" zdLWqVTw2xꄚ1`4*$Y|H٬V \)\-'Lj9/S?LJAQ/;gT/XZ[rm@ -U\Z Q wۗkc Vo>g;she'L}GzPOJ̑"傄zN]ZSq6r^ gS2rH6O -9%MF.3UdXm8SLcg]ZՏ 'YHR Ies'ezzs䗜J~:N茶iaW0g傱 9IFw -G\U}}kŢIP *9926 J7D5=L33ixkȦGt])^JTͿ˙(7ɃןC+ՕՓyϖ}d9&CWnRd>uϧ!vfA&g\as@!Vz{]S**Oc?T]jzM( /' -5i=A ]0fzؘFD9/n5Ƣ=9+]IPǺ(AF=kPڢ~;t)K> >Zs|-Cd4 tupw.%, RJֵ^)3 >u~tvդp6. s)bRG*`vʡ=uuG3j>J+KU]Æ&bSxbz[82#'Q -~/K$p݄/zgj_q[g= H>4P)GwXBwE:lP>)vWk~Ua)gPdGSw&Ԯ`d\Hb@j&#u:)/|Mxa.ɾ̄{|gfv<+ɞ҉ƴf %Ӵf깈sOK𩏐OJpHpm>]NkcCMr҉PZUDͅ8p[TEuaz15[^ ,4T>T֮m"̴rxƐQطu.X耵6+`q^O[PΜtD;xq;7U隇Ƹ=ogH0v[ސv g}hy;[1Nd {^s&ַ#Il{Eި7/YXAjݩr犈 Ӈd"وE6l>݆{.݅ʜKyU[K(l태9/hʀ|,n\iEhEjUG"`0PmpG':sq9`(|Ve>Hưe%ڎٷ<ж+l"T^d!k6A8̀e2#T ײ-'kB37{uJ"l.zLQȍC.z hE70qdHΉ.,V?(NqM4{dn%ƞCgCZmtPq*`F(\/sH4Q[ 3z2Y=t &utgYz@|fm, -ãƜ?$/ i0u_z(3l)/=~6zb^-h?JӀtm)n׶jc> SM6;0Vi?J(1ͧ ^}-E㈊tVR'mU!neּ6>{}zZ{dӒ֬J~2.bIS"Z=I'3 $ *8x =OkF +8J8Woğٯ,mڀ}$\@O*K餏vj -'َN ~t\"@r:JCUޟXnˈx<-[ -=) v,$R7|]X2 v=S,b7%@&j]3C{[ʸD\ 儗ܧ10tBUzӯHD@21t <~T|Wjse D~o07,]Z8#- l-iPOYn=o^oLLǎLP&.B);P0Ia(olIh'?{TQ½ -z^t(r.ujg(nTsõ鯒or~%RF}#R'qa/BD_{j4b.J;k중Ȝb-a3Ӏ9.˻mY~}k;i*Y(iopox,!^ ~zɦFMXs^GF nCDo sx;TCg_sq },V)vzǹ~ne.g"xilCBfx# ^LsW6ӵV{[S>ѼӪxBs0kxAs4{=2{S~)kZ()&S-iQ) }Lƺ%4^ Cr}:&=| ,XW4u]mZQ9\뮎\=i@wVgLXӓ+_Pi4 *7=nﴴ;{tD?(u(A/f6 -CDGT@08`)‘N&K@UPq3vZXPlvipjF;w;)g"| MYB- SV&Z2WZe m -.kӿr('b[b}qK#)lgv᫪F_p>~f}Q:?^g+:dر@y*V`1}lDc`Jcg:GF}yy"xҞmw^wasL|`YC -(\h`ώtЩܳf Y]2Gv~.c$Chr2WZ̎ܩ4&&/>xOe|KS t"9[ FqwN$.g4iBq,pd3Hb.CVIbsv)JkޣNd}Vx}=B ڢ~ ?W~(ҳa6J&EN_Y!hGk1]ߒH bH5ؚ7U`rܠ\L{(e7|<2M\ǁU /6H$lD;yz_4U\@ %4iۍD$nvGGp= 9AsأDED@7>t_ߚGEd}z[Һ_i=hiǝ\.g,6(EmL1\U"WF1qҘ -mY2 W>z8tE]ZYHB=ҙݩ=|FO7a Fe\5[@=抖+bYQI G1BC#Z *jo"b8;0BM;EcS -L}uߍ^ҩ7zm|)Nafg#M`9.b{?$;v},#K>ey蔧.c^UOF8hG4`> ӣ}r^j 5NLs%@^﨡%KG0~=wWkav6nԜtCO *y@/[<ėF^:7QBӇ6jK:(XBJJՀcu]mpb7%kqȕ0w^op>vY=V6:n}_gz+tpa$Ƴw}hzAki3TMUGW`>8N͒TJ:JD gARRg4BP`lF^IٚxQ-J#rdNj?" - Q;l:cڈ!4 +r6X`[]Y>n[`q\lQ*hL)ХQkfBu^5ՈW$ft4*f7M~ NeEffRD>_IJ)pQ\L-:V=[D'샃oME:a( Sm&kaf?g{yXfϿ7dz$>۽dN&c9FX:T` 4[Y:+3'QZ~P9!jef=ْ ˷`ףK(~rD)SFNX!~P rfdՖďQC9)X|G@E&Ǫ}I߹q'3rG- R0cj〉2v+iAa'7trAIc):-_5uQeb %H d:!)wqvMHJi^"㮄^!(o%JҖC<c1XWw]+V3?r B#9Vñad~RÖM%kO'_+gOz14R"7lN)߶WrEqs\ -7GECqe8ӎV^'q^A@6WtzaHm;a|îdݔ 6!is=_mm5Ec~a[\wwu"JʫҨy^m`Vʝh p+<ƈQ?p&Mc0ZsJ^7FH.\;|m*DA+LVh{ ӥh8>{om*\]i4Ǩ7y7 Lo#LJͳdY$'j =/e - ?7uYj>׼0 qd#I;e ap{~KFVPI&M" ei>q}> ð~~>:omAΕKDMTY&nG5ɵbgZ$&F! p2agM ԙsDxEF'$t[+EIOfSldq8%qIX[N~eUÃk!ݶX۱bCm<wB=,,r-Eiu_r嗳gzv0qڽӋ?/} 04/f)D̤C)qɠ,Р!>:;Su^ۍE?17=s:hJ< |Sr'84 8`ͦq#lA~Z+FNFEfu/3rī^·tF<7~{=䍗,/F뙢cf;z}2tdžHrɐY|]o0{u!!x짙/\/P/oc8;?MQz5b.P :DѝNˮwq:-#ɔ:cFۺ@g馆55φႮ^b,_̓T!R C 5FɈ9f{s:0~Q{[։^dzjliz߽=#xbv~I IkR'4U'G(ʢ80m>C"Vwm='(9ZWDSuXooKV`+/ 4bw$]'u߂:h+Ac]=mЍK$G֣w?:'D6"e,2I|٢pZ%GB9o^p]]<OYZ>\kɅtϽa!t({PJM93]e/YM٪x)YCq3S?~vvOSz@|&:f,\=8N˥3CLC%gZJ̨XQ8Q}E ,ݨ;Wd㮹23x040{oOCj=h9Ʃv={,'lfA\,}>\ v>?|7W<;.1J0XB,5Q1.{0JZ8[`eGb:>a+*4@(q11DD=dPԤgmEO 6w-.|rw7`D־n;P:e:z'SFsޜt=& Fn8Ez?'٬&vaȼ.]hFj}MjP`O>0**;@;Ia.* q2}o%QAid(s66@_ tPxe>Q/D_O>!s.7Eaٺ\nɯzZDMF/Lɮo'Nb>'v!Q]6~gz -y,!aw7N4ߞ4ATYv<#9ӻs<[sӳ?hѫqtw+9K;x/e7룪ǜ;iJ/1G_8vp֞}DбgdGF0eу=;ӫez#<З%1ٲlm?Eк6)աQ- kےcb8&*ȵ8a9|qw9VVKlE~-=oSN կcP6L^%Zz!esނJӎ7hG-܍nLzvcw?WE -yvɦzEJ.bƗ81k/aFYqWe~ 5,Ka ϔM2A -^lhoC<:i=N<;4OC4uXKD,XDht%~1ُEgTAG xc(m8C=8;^'!H\4]}]PoUsLi%9 N:: -A4ZDLZྌ@Ji$cs.5{5۾!B3'1jW`lI7m`t@y/uôZQ N \d؎4=1qƌI\˨I CT( Bf0ʕzY|hNj[t -"!k"_?[4;$z2=f#Z};6 |m7XB6 -]oW;E7U:xRص82IQT!(u|R]ؕmҴ=AIl,;2}"{{ -34dKT})zwo^> -S k? 4sHM0ؗ6^oIH}Vi^.s^S1e (-n8y}_.hC3k5g6vV[O4CPˀ˸㧝![Zzz=#œ~0=].x']ǻ&n]F8٬%v%MVC\keWz"Ӽx̾lSqϺ Y/B¶ &՟S:kڋE@ n—=MȄ5! ӘtHބ=B5iOxyӖy}=+D7,jT6xWϮq-t^]zL1[̪N=_ec,}KIX$&oelZ6^uEU:;SSS(%*nDMR Z3]z$*l`ս_:,GfvKkaCHT򐼢X''X >[3ȵΜ%JRWHޛm5b CXȫ;N(Nxd&A0c'z.O@H,fr -9Idi;VcF"`% =Z Gt4DNr@nFv!^IkmhaX<y_O?Cn?ԂY4E>r3 -n H!)~R6w?qm>FeD^@~M>ymFm=]4ӤOU/Gpe4u>Eo<5`QC88 ڹd=P$SY6Ln)tyui&#GtPx!\*vdz] /ɯTOY4&b*v  8]%{lnz -W 8U -ߋdOWKv:*{ *ʖN%Iʈ$Ir=LᛋKb&G'|ÿ$Z}(?ww7=ϩ Fu)cc<ً`Wtv6m`%jN& ©dbgZJdZyGB26G~$(KWFۮ * J[{Z5  ˡ3r-^po]k"RK0c3L\kU1i#9PlO Dbp&KsC`fȶy/{l]hlDPʡ,Us* j'I}䈷z(-}Ug' "kqQ!MLVv<#9/j 1r&ׁb_ U7"զP)'M -ƹzޫL&=jT&"GNhRE}FXTf8DJR .|ct>[mXb`${7 1P'_41)[q$֛htꬶk^_pP6E!nCkjL-C!H^7:D;qz#rѺ(ePU|׶zr}GE] YMUQ d:8:<S(h2,}UUt3ᦤYRnA;P,s H/AQ-N14ce,k0YޏsձJ6dSӛC -xwfV=B8FWw Zʤ1^[@~L6u5Cx`bE õD;TI!C'X圆 8&ywS3l+Sr H%/HHGt[G)M> >b -UT0Dމf얳&7j?znڎ[6boLtqLǵ\vGK"% \tN<el0 ۭwf 4+v YKeː><͌P܅)n%iܹPRy_PXαmX/@gI6ߩ,/VJʵr7 C?ozm_.T]N&0xMzyIxN'00OWgƳm ,vNZq;ƫ6BbLIV2y_|qt-}QKw ڊ6g%lB};ܖ (+㈘Aq(3}ol@U. CPL Oz!ĵhp6Y}q68ˣH9L XHa$9xz+p=Gt VOKJ tC` -"9hBBx'TVŷ)e\a |_.obAAIH[$a!Ah|I̘}EyBwW~1 N~׳V.ڑ57 -c,n5P|ju=!IoR=*;M`zP9k\6JvJH0_\g8oCFC>uɳU%g+4?(rhC7OO+JY4MOxV".` G@`ob&: 8}+::+5˫2DQjB7 f6;ПoRͯ6w(CB5}\C=#m#ٛdkX\mp M9cLԯPil؟MWŔD9A6%fI 48c&Cs#)%35oDߞ=axۿfZOћ Ni'J+aKz44wq%P>2]\*F>ͻl|C0zRn[Zș8K'a\GbCeg .S"bOe]8?$:XNV#6 H] -Gl/\{N^۷jWҲ$,˴vۺv2a ;H --u ^Bj`l `oKLjSYxn{t_=XLpש+&Ġ3+9}$GYf^~KBZekm|ѩ -35U=-{So \o!Aoz#U2p.U3K0+=e1l2ߗu*5 wlY=M6yl:`#àXbM0d]jnAs_bR9\:Q:b&]ܮt 1M ʱs|4МY5kǁJ%"+| r@K.(JIĝ|p -J|Bbdvb,x69&ab0I?υS_驩]N-KvBΖ͈ :c6טk4j N@17.M$'А첅$+|4;oy[Us!?I $G/b"yTVu-8jwσzQ'cV2J8Vc/ϱ tB H בZY#,!;EL>`אѪ h`I)ԽȮz`rƪ%Y ux%gY'˳2o-9qIuaIay3|t\H -kAsKR_΁=ܐ y/yͬ(q׉t<п#kHUHɗLO(sqsM usE8&ےp2ιS'k!شgYzX㦸cr -dg:}fВU$uM0L.$WUZ>#'d<0㓾T ~/8g kUeeD.&NWWzS^nڠĜ8xwJrtn\UT~nzbT>5%7+35)aoq -IT(ƸZ^/%'Pnv!L٫զM\\˘YɶG+6$W$Lx˴6[Sjv-څLd蘡xBGD_ 2{eM'"byvBJвZO]vq4 z|3Œ3_KYb[T-FwnR=9$1" C6_bWֵ=z#{:k(vPx?;BSFEM^3| rS7>yۋ,5+ᯊɭ[5~f[ Y7û؅͹WθnLSLaqUgHu&OyZږKDy:JaRl{}ؽ[`uymR}a8iFmXJ9C'ßK7 tEXfCCZ#Jtr T2CqN -f.zβ&xD >m0Y'nPy;97E37θMœVHEksA.+ePϛ$ \*^JKRia Xu`RX7%铄~{ -Rڵ]wlzC4=sBtE5SBt-yȣG^^¿RJQ,as,˛cZqU'JDjⓎ9{ܹ.:#"H ѧ Mt ̀s۪F8ۊ/o+ H<>Pժ;pxjHJZ#:)Fdsj,߼϶v3R~s>E5{ i.:7"UE=.j~*h;xqm1ݟq'7VCeũZ i;i ֘Й%@86O'oSl.+`FuLc0-ı33'BDf9exg/#d뢑HN,en -מ+rFkZiu)D{s(ih뜾;hR3݄I聘pwYM*%g ceXөmK,#+nRJ߹ -;Z'E9)E9 1왌Ɠ- -Y͵qM[W49[ N3RQ:hmWV,-1s`G,̍fɲ-.uώ}ŷ<#Ntri|_#7~-.OM7$qY[J Ʌ8[=ɍ=2Գº^٩:&/0Ę4?̏bWIGE;?(= NEhu_=ĉ Y2Hx ":]=20SЌGu;)ۇl)ezk!l4XAu7_KjF_4aˣ%vڿ%e;'Z?JXafd(Pm!YVG=Ot=d$!rb>XUS}E%Z)랧 J=`Z"Zdw8\Gk^~8ՄҸƔc6![ٛ$7C\U8%[|v0g?> TDfzl Z^;[I{ k τ@Ix CĿc rDYxayjņeh&# G,595oRQ9Er,RYpoT1cm3, tڹLyLc$ȣTsƏ.o?9x:eugSİjoWxE5/E邵szfqLȿ*Ip]eFƎJR(+N岂߇T2>nꓵ04wvJiM8+\ -4| TR}?V9Sng9*z;~/b8^ݱ*G>}8%;ԇav)n۴&Pe x&C-eRIȝU1TkwI`yŧ(nd-hecؑ9cY/ucMMHYC#zr`+$Qbӗmû@StR!DCm\=8KG?[s+[Q'h4|AM_cL\q4 -t{6R|Ġ 1lslz1 È934YN]m8([%15ΛYGAm&Q|3CZ:zp1PW m >;ObqcvȻOILWa&%E^5 9.^* |n`N4yNՐ\t0&gN8%NtbK{| -&`mq(,V<]Y ` K) S%6MkxCˉF>8.즎ќG?{5uPBwmYH@EJ͐7 *^1w|4LkR\m{cnSa܊FvIވ}K579'ѣ,LpkoGr.RٿM#f1$S¨A.],CǬG՟GBe]cǐjA{t  #j?U{CM qZR-䗫uPzf|c|mna *OVyY8wx`raJ{I9Zq)Tx ebUtD4. KNvv;g&Yh@@]'B<dz$ģRi>o(RFiH8쓋R\ ZPU©{ܗg]6XG[kOKcA&QddU86 /X c9$&6qnnò{F ~hnbUX Dh(骔n®Irֳh3IC [?7S(5}C{bG6=z('=K+k<;MbX1ڮFLF)ѬɇǑxo]6.(p+S)KՒs -_@jd`%2Od͏COt_Fr5J\FFu'5M~]*!pT JP EVn*nݸFWBˆebVBM[>N{v7%O39xufP_[bKfrzϦf'HCbwNwl -ZDL>iO/0t‰J !-wnY8:lvJC lza*_iJxIW#x&K9]~xOCki츮8N-=\gmxfm>9V4{/hw-Ii1'7O6r}礗3#צì+#)BUlm^{ld.JAQ)?D+#"$EogQ}DjjFE.m`pB㻕QǎH.·^R:(RxPBѓbr|z5 B+Y\vs -"mݟj]CRF0tſ2}c[MI7ۮ-5d HS 7*)[aF-|km5qbe%㈮l;=+\-;< tkKZCkvU4*ኣ\3]''ѤP}G,b{V-PNVW;OM~gU4رX ZRxTXy['̓Н{Yѫq.Щ@ws4 ;-%ejc=G A -pp; *sf ug*aS6ep׉eξIN(gg/Թx]朌Yȝc 45qh2@\t\`^M"Oi^o'L]f[-c{N܏]*[6PI7|ܼCNFx+3z=L? Guպ"nf}_Һa-ەg/>$Tb{}-ǾV7SP[C y]|> C->?ϋf{, kz:4 fTz\\Y"?V9NmүF_QL3dlBQ{<"_n9$AKj[͉oP -\7=(WWc pSHK%[v^bc=|w7v`l#~p^DU¦@ŘNI c1i m}{8JU1 @}FF񂺴8!TJ3 -pAb9%vvQT&e9:'zs4S59&w[iaO1t]軔.%2 T FCG#oNs o!*x^)iz->DXwlq 8?/mkU|4c.rX% G4νnؼ!Vt'(Fp6(xbTe=fJSҹi=cLڪY# "ډ*Wؿ#-ÖeNoDbge%.~״zY5o\8$.m%5Xʹm糾Y\ȑ6LjH+Ro1ka󪀝\ZgY6iO&WuI%^Wh`a~ge,h~PnY-DZ m4Pq=_"w FnLL+R|~:_64qYEiXf -[¨!*9-^fw&S启iCx•6rAxPqYʣm1#A>Ȭu9sKq.n)x)f8RQd>PzAnO-ʂ?!+X`]:̇耪%. <{  ٿҋ^1T֯/ou*w@PJ4Tŗ -gKb}ž UKdbU;-bY,Xq[osuT&B%s/' qTt|}j>c/{ _CwgDŽϽ.~qSwNƪ~ -aϲi39nτE!1Ծ{̖(;8mEePUcپsRCu7*`t@p 6>}JH")1 TKs -C1d28/b7"R({?ݬoHI‘i} NqNCm %Lu3R5dq\yi?0ǑkQ2)agqUJeX+ϕ"`k=*dlXsCJ\}p@ik]G@Mڳ` -==`}7j~TKvsMr_ku2L=zpEca^\x"#:⹖`H 2mpZ+cV26:۟6~%ǍPx+ހ]feKS*&N䢻[@,&6b4\m?y5I$x֏ReD]n( {ɱk9<^[ܡ_q_I1|>D] !-IbVm͖2\[PG2AcdYy:>ȘJLsa[w/z 8uDt ?Mht Qmڒ~5{ލӚ -qtlgY; @lq^pK{-w15p y[}kԊ[pb^o7r|2R}XW\Ƀ9}_6ҧ:n`ӕtw GyfrWdd,Xu_[+f߅^\NEK6}l۲\#X>[#".`_Z":A^:63 _F+󋱢si"&| Ď+3ol59/Hf.+c8uk )Z@NؙgNͥd Ak,>d>iAc9m9v[&A3Ӊ, .xEc?,sxn/ɓmM9fmA=29;:ya/_Oq()_5{ST=^+ zz.hګ{b[JG<ùJWrQj*wytDߦJlܧ*Zn̹mX<3Q cLBggBDZSO\zLK+R3,{!fG,¿ SNs[! -o!Uhj{ӊ5ʗE8(&yNw9l$Wkд˟C/zA>ߪ?uFkxvM D>Sgi¸1FrU_H25f$]]>lWzy-(ֿG+A+A8HZ)TMZBoYB;7kYѷ[e_gsԯ[s zlpEXꕃ%"JE^+߰"RmUcSxP21, SM 4n;Zk炪YkWϞFH]0|ֿġ{~R,@6J^H wxbF+y|ss%C^?˖M_<2T$f)8T*Xgs[Vc/QHN.xJ9p:/*9鼐$d`78~oԳOEf)d[2LbgEg\cm:_[?;nh/UFVj̍r޾6Q9d2mYy+OD=z؛Bu絘(O -ƇiS~285g|;-²zrM]s+exA`Tn^;k&~i9k:#l`T-Yl4gLXx٭hgSL``%4[gΰ[5wL6װ8˖{&'4ROz%ߌ6;61kGmuIXn,VmIRRx7U -.45vY±!;ƾzhGB;y`g*Eݬy}JAFT!4dp]n): zamy$]Xe -K1 =PŎ=YikZKespnR u!_ܧFau`lp?;s 1lشc9qUF&N*4.)# 0s $cog o5?Ogv޳@F*K/8'/uy\Q.(Ka {D'V. -@\$1Wz mO6$d1[!XP(ؤ< ]V>V`;m =(-*Arݹ01, 2<6BjKIX1- Zs~އ>UwwzM9aF[~Qf}6\ײW.RQ_b?0e:=(?Uӣ،`UȄ! &[ "7_\"h*.%5kORP uTIRҥ{I2_G;3[0MX cڒ9rUݑLDX`J ޵~(~Oajw#1B>0VAl -^(jG_EsI􇆬S\G9ܐOlrߡQ~#fPjXP)ͤoˢݢ "LY3[!;Uk;2u4/O?sM⸭EҤ|jipm.eOQя5b ;G"a:P!o/, :x2/3SŗMIApr|"l&3{T>(ڎF/;¶(2ވ\O7{W1 m򓵮0v`lMt,$}LlvvTovwC<v2uOъ>v vL*첔9})U+q}˟7̀%c>j|rFAnO.//O [5̛MZ!Ʊ8rځv+{|XdBi^?ĭE:=}zؕmgP}N< dL$6\gv<.@̇ ^QbKbF;NRΤԽ,Z{7'!رg`[!#qwL^@u嫁ǡG%QcCHܥe';֚T=[̙qVSGKXJ1<Ŀ[g[1R(twJTW<3GC6cH?*z/1JC*FLC*M֛i._{vo:u&=.*>-UYBs=;zInpX]BKE1NJ[A;܃͵]zےaO0*?/:X0ƹXTus8b):L>x8zp/TJ̾0 lMj> wz.QŰ78>Z0 W}/?6OH?°Pd[x Tķ2*ѳ.﷕"Oz~)2qJ#CKTi3w^;' Fd"~DvA F[0Qf-ɳ$49 RՔta%C(`^tdKÆ8p+gyO׮ `"}==Fg|d+=`N,BkZʲjz>.ܵqZ}j?ITmXVmmwYHM| -o9U8=/ -YF.a(p&ND|ZZ@U[ kJk|u#UA`ۛ ϳeQvHK#儭O%q/שE2B5.)T͐S%cruv>zK̚4 o:70ܩKkR}9߷bZԹ?>Kt|Y$tNr RxK7 ąVR~~`& bFr viU;-ݞ{D#ˈ%4?l* c1dP>Bx$,'_y33K2hrYaBk,cXk7 \w'von$K RX鲶50^Wlppp6/85܊,TL4,}nJENmRt0TxN|bCe^ϐ̏Cc0/ui}\;XcZx" +\\.sNۧ[X~8%٘| 5%p-¶ .a# ǹ(eLf;ICD}^fnafuJ9cH_gƺy9rGx㵒5\`SHnTcm?N!ڬq^pRoHHBaV05{ledӐʥ۵%r}=@l5u6qzl\v.Fb-7 a9[:O߁hAZd8vNǙ9U(5UDڈ]G+G;McҼr -yAEf?X? ❿W|e _ӻF]a$+w{Ht?an ?.-k3 -FCF3vUcTTQ5YN~Ƶ'kiʲđMZƝmwP#y&+v +{f*[1-٪YJ+G};e8 )]%YɨX9tƅ2a3c0v kP!6s0 Jv*N"&޻Y+hQ*0¾zwjgBlZOVQV^ -x֦xn!K#}%yCq&v1^#tr$#7(;{4hcӜ#rr `x oGUNrX֙ xS ]`i:_׹!&'k[yn_Yy΋} -jiy>E{Uuԝ6"% ++I`EwCx#:w00#CdxH`})8>y{b>c\j}Q,QDޥ!UBǜ35uYh#%߻_9*I]2񐞮 !+~GOQ2%6Zp6Z!i7,!2hݠ1{D15 g#`:"hmt@@\=KEXEUg\u5RJꈋeK;n vϦG)L8-q~Q8OVxqrfndgbnv\-x e03w$!ף>:jd߈n6HI*F`3[4́2Eb~`l;nL.RgxF۷Xhtd&7Lw6VWTL;oLG-zrn wD&>yш^7ՂR-ݻ5r&8ud^L2$CJ*aS |,\,S]Y6Y-8CtoKNneݨR9~F&/G -\v|?Qy+l[]ĢXVFh7u3czdQZѳnX>nVWMw{OpC03óPI"x4[e9R6 otkǥLfh(9L^$D5*t 12boyk+o,Bo8iM&%A&jTr혒nRSLUאhWDodzzUܧ34J yΓ8yw9of/!)Ny)Mi5,M:X4F*ODT脌+ t nǢoftqԜ>}uX_U/regዓV=ceg:91n_^;I_ɺؔaF0/lGp!QkM\s/ř*˂«E]wBq~˫έY&aϔ]s}~s- |corS*>*Z.q -v-|ެ%pG%5o4" -]{ xEWVzWwuőCatt/-Zi F;\ǢHE_ {\}m95 Q4QXu) (hl㙦j 8Fz:x(/u#^Z؃Lq|0_mI6ߧ L(y RMw;^{ST*%$-#gF Ʀ)-cf}!&xk GZX-*& eƥ,8TbU6SY J$iOd*UER^FV1 ӌN49k_ 7a1_ p%cxa&I(/]N(lҶ<u!96B~@䑁K;ֈr!J\@n+ XO?:QK\m ܛEiB/lҍg <<{Y3Kq"z?[glٝڍAH r=SSۗ ϊ(a%${\ L&.]l=\)+]DZQ|3-NX^?s^Ge Dܜq~kF=Gq߃PqYAmWg;g,}e}+Wa운;꼸&ޫ"ՈK'k; OjZؠ r0[q-|^3Ða{Zޯfl5 8tLېFLLh" JcX\VwXs/~ -MeMj7~8=(N{ ]6T=>?j" hFpl7 - lH<=WuޫR0(bLS/}1&'_Gvv@&wQ).^0䷝A?ϥ\Y<|foWm&{xWddՑlM84%{j7.j{@e!PfIypC'QbuůNQ1o5ً":Ҡ0x?6k5% -eM[5i[;ōvS,W}֙ꖜRYUfnzMn_ջ%-[Ŀ0rB.IrLոRUrzC {!nd P/=RK֔H&\za#X\>hg,ݦ/JFɢԓx;Vn cȻʞjnn܊+DYMN <(ZZY٩1?*mkRʤZ87-ёYVl9}3Z| 7 f},v[)DK#[tN0H>HC5u@:Lxo! 3vr^T-[*Dv -oJ^s{t0\;yN 0OWhY6VpDz6rЉވؾod@w6JqnԙU -)yO3DY;}u6F,qݍ-o%EX>#/l6Y.]n BTU5vt*]Ҷщ2GKhHbe>I vQ7hAв*-Wó`SY:Ee ^S*}c kgLVgjIaW(d~O0 _Wy\nF `j k}]0Z w$5٦50ŰT鱍JfTQ -:8/Xf>.#ёikA$"4XOy] -N#q<vLYnjݝ1w4Wˆ-갘Y1wo?y1vk+g~l>TN$eQ#2_~g,gSKko E=/oױy;VϰbJ~n}9V K?8zG_m1+З] .h*:w.48D3thc?}C o\} _|@T0 IL;Y" j&/Du8*~KsA2 .lSձHdL㲦a8v%y`-Oe1~}ue^o=M|_fj{]nHQk`!5FO]8v`lIr_@n"wﲒ%DVrOoͷ>[gVCUp ˆm`%?r> dh>:~FgyUIan,yB A#Nc^Hifh[;`Θy}bS`ɲ 37LVFqsZ9VT펌YH+s6)+ou~1w 8 e\#oDℶIU79JJD7\kS<X(+D(Vy:>2C+KubZ///4Z&cX3wBgdw4 ā5(h*}фku_?DFo24Xn'/tw>&0.eK /E81s9 -63/GDvTFk 0չ$toZϸ4ך1+wE<&dqh=Db }_%oX[ ADa)6z蘓qJa0SകfLR7(10䕏ևA;%$k\g8Xq0evAy1 #qE'd׵tk0%%B&'*YeQ&[E s`nߦgbseo8]V+,#M曓ܗ ~!4ZF[h.bh8 -:lga*LKTIg0'Mi8IXM|D7˻˥Wo@)4gr 4dVX뚖 W<0_Oq0D6Z^>0z?| ZtػNFuH[clh0z2\BB/yU%~aI[ W'r`IOԅP_ǜP]z_f7S?pGKIˣ ~GgIoyҰ.bWDջBI?ܞIdӥ(W"2<3\zf[oJ*pq(Z>2) ٝZ35$,<5dx'WV-)(l zmrl_59˟-"12jƜiU |k - ;:kwruHj7_pd/E-q'RŜff%;f ]],s2k 9R#{٫~>t]qwr\K,/e'E5p8aȣS{3-V}rKXbuUF 1}&!Bd%hNx[Tpkގw @c9ԼWd#BJd|Ƀw]_ƢXi6)CY ? iR̉L3:xV?T6d¹ڦ -}4N[0F3v1esó˒蜓"dKGnKǨdcBDLW^N i +mޠ:-銵VLftԘHh-Ta;=,ٽԧ!YϷsَXbvvWuy>/wc*ʩwLsD,$wqzs+{ -p0tox.UFztVh{)+M Z^y -`_T*#/ƺx0RN$Y~XѬdެo~e,PA;B>t߷>cxŜ79ޗnvC6**Q`t+:\t"H΃vL)`Ue&V@0_8dʸsc8YΨguZD'nJq(q*s@'-ƱecV4j0xSpmd+T㷫mB1cΡw´lud. -?NAz*kܙ}MH=Z"Bc,>-nΈld@²3ԗ5ጭ]s_McVmq9u8iǕs>y@آyMc f`F{Q<4.%maX1=9c}?ցI˳z)[6!W=Y1l/v㰩PtX}5U#_4&Jl߇L~)CڏZ RKt]R>ClJܾ.7}qLY&Kї >쓨w%iRHBI3>l)0e@&Pzc%D#Fr2""n=Do')4w>q%K'Ԟ) 8/px{< -GZ4Kl{N12Veg;o/Ҹ^yY9oxk纽~~y5%(}y#8U$@NP\#FK ǸbK,/Y~Mats =NèMty+Q:?ha[<>;9帛x#39*ߔc<333qWͪR'lwҢ -v'v5sdnqoFf;UEJ bf#Q$ˤ|KS~ϛ-O 6yE;z{։]P۝hzxBdze۳."Dha;oՅ -؜" =h@ۻX8 ?80.8OѪIqTW^΋.x!s;3{,fm[okFNbP R uaԉPQo[Y^C?"gi vT}qlɓN`3FzY ~aHn\ :9D Oꚁ,[CNLGCy(um755!cG2j]C?m*Oݾj,+@: -+8s < B[k>G JN#*=ծ)IA:s5W&Zfk)u#y-ƺQ6\5RcZJTfyxɸczc7>OpXSic0sO<ߐ\K=/<ֈrF6.UVH& r Fkw3#^X9kޑ{ƢBM󚢍HQ~\GgDScCwfy<}aLیxz8Gbuqi['=ZF4?E"G=1抨26+Kמp ͟ˈi#&U zS?-}z#ž_د$9nS3A\?d&]=㈉l$A"\ʙw~e+-מ* *^L:l", kumS MuwEcە\8תqE탫±/%wZ 5DcEo4Li"ou xŏZڽ_G"ܤ@»~Pk Xz|2ƷqqPR8ΖˑE;+Wup\"a"tx)[>SJ}gTo9H5?L}ysn -G:PDM!|)?#0L5"K3Y=6nZƘJOrEWm=᭦؇"j^+K")q -θAķ[X•Dعmq9j$ŹS}_9 -{ xmquAVW[؊%o %\ԛa\k{rJM"E+& 2ت(y6/ -vdDbrUp3-}炡w(lgz:z^#k>F^gkgəƞ^iuӳL?({IكSP0ٞni}oBw.ܦ]5x@l'Z<+AmzҺr 촯{$E(P,=QgE+NIf\f-S~a\(hŌ5V;48S`ޕ~&u}^/=%'/YVkVKPlgjOnesX9GeRĞu$=RǷ.@Da@\BNvr&mڑ. ي@A,8U/WrW -D?<(gsˌo9&>t_Fq_D,5B`Wpbu%5撎%*c=,<_QHY}[X{QԆճ=FU/wܫ =mVOFFclW֢1~1BQQ[R_Dc &2HtQTz=SD;/}ko$5zꭿ7\\K6;Yh='J0^Mp.k7G6̈́cKI"唌#/% 7JNW֦DFg_-ciVgk_<8 1/㔉 0;<j81z: `F*l ש_FϴG}~eVˆje\/Kbo )P6g[2/kZ)pSnˮfw $^}]%$B5+>JsML5ceT 4B KPD7C8zuF{߲c]3=iia`=bdJHPk=↙YVZ0ςUNA U]aцS-nu?ϸwa-t"&F2s656b5.?m15'a{RMX&j.#Gf>zD> ]ne_GJHPk`PU֜Ox:H3v`+iūQzx<>Io#yٮW,eja - e55`gjmsP`{8 |Smǘиw"bSዊGhX2hVNy#9q -%-G[NWdzΈᏰv`v FELa#NZJ@ӎR`ґt*J!-ep!'V5DbīUߺ"#ac/Ɣ[a9X7Y \YV FGc&QOJq0VH`@d5h4nF/7-3qwͤDvaʬO27̸/q בܱ*1&_V|(د$rx*'_ni1㈞[ -GH$2U^yM-]Dy⌼[URj̈́agaEsp'?\;8-|L99Ly<Ǻ۹ql[^yόŅTM=8if -jxI4G{Ln7{$2Q\?/yU7~Jj$V> -V?-G#ۂ]# Ilx1"i"# 4&f05_.m`u-~9X^v45>q+'礬4BR$XP&vK4}UnX#`{~}[Rj?[wݹ`$붞5ιlJo])`vaɭ^wNg:+-}0x^&77R^qzq`z8v)󀉸~NW>Ţ VV%R:ѫ^S -N@v8~Cp(%\HQ{g u}XG;N +צp07{:.L]뭬gfWrI*bCifQGы::;[2N臘cWyN{InO&YmHSY䑿ϑ 5 sRR*F'gΌyBAzel.-g{t*#d^)@'7ILD0E'#_ʾM?y@^b,}at(?o`lTէFMĪ8NfHqQ!"MC^]pIMFP؂{: -k#kW#s 1t7<qx -|c>6 'mN}?­#7 )WB4œN8W Τ8!;U$# r|@ɸEJ+\s&n畓/b\g -m>[u*)T#v,*kTᘘ; 9wNrG$/?s,mp)6^!|jT*C AuS☙븪lT_M:O_qC2T2yDl@ѦPQWR1,bsqd,uxбjokH{4S~P6_BmŰ^S ?,@[NKJ&٭ B7ߩ5E*3eUWVM JH>Qj!+'\j/'[(8@]ǣձUS4`GF'Tq=_ /ţgIe>EFٌmч <ӥ2Eibr,MW/#7%G.#V1H5ho8g4 WoǪ: -Qܻ.UR9sqQ-A!Њyd%Ԫty|* ~OI~Ŝ "m.Ä;Lb12_c(ǰUFC=RB.L(mվ&,8eANg("YQybX(Ly륉>]y!6$}zXOΠXUЛҴnE =AM?v*N.YrՄ&>F;!ѣ5y/,hYZ=Rj}` w/r[A"uCn?l9NIE"~w C? -h(;?X#u1ઙ0] 08Ȉ!y0 x3vJP5]0ߙ*ܧA_҃Ftכ{k~VCFw˙cH_ʧBu}#j#l/#%Q -j|@ KH۵o%(GE)!_\bb]%,/aEmRkHV(z|_rDZ{ٯ,u( ieDj;I4rͽ !('3 z$/"oBdD!H&xLQ\k+hQ[d 4J=`MpYԟ).%W].P D/Z$ʗn`o0BEil Z+3ݯ)VB6p|' ?po۷dRѸh}r'V_h'B1g-N%VcKzYz>|~v0"s=Ɓ Tu4II,`i'Ue=*sQK2()pz D䍒䓒Ss%61)0~ 7Q_]xgz@v8Z%.`bnQϰו XY -QK7]y|P H,s=+9 q"$M5?bY=7gܲm/|?)LYEΞ<c3Ɩ?x4шȣf B`{HON1oʕY|,Ej;ibƕꩡsSR'}sU- ̈ Mt1W#WJ -Qm@I3 oնP~f蔧Y~LX2*1ղuxȡƝv?E4nRm^gf,Q SKNjCq-;x_I(6: =~"널;p^t~]\zd_0jҁ Ҷ$55p<:vcvdmmSOԙ*,BA$d@vʗz7YİPYS)ƃd-͵龖:S_wS8IxuEUN1,ĉ;xwa TZ)h8m!ȲU٣dNOVNL V n¿\ V[KaqF( (S2D yw6li);Ɨ O@kab-fvͲK ?1YѲeUlcx -{(xȽoxT[qkpEL2E2 ]eݴUz؏Q+AUT5 ( H%l`xq% k#EНs|4E%Hچ`R’Pnw6|N71S@ Sp]V.h}<>ɓcO!55P`K#-I#Xr0ŷ|&'|9o@po"P~+%rSV /J)3.y#ڨϬy1fd|Xf߈corofco~j*]vbq^9њL8[@u`:P_?7N߅񺁘mPr)ipo%FY߭>E'.DG2Ig4:q5S2Y]flA9Y^)z@*54b*5EA&犆[X{Bbӱb4z^&cfHA6zu;5]jW}&l+k`%]jМ:51Iʔ ԤЧ1*~c.6]v&T[Ng`3[pOb9U -w}yr'fSdmzի#]I% I'krf np=xQfO-7^@;jZ` CZGbx9SۃQKPGo%cEFSz[sNo-v~{ŸyZպ"/&KIOtzɢUY%(*.;fK)pZZMz]EƻU|QtFۋֶW0E0X`nZtZir\.‡Dؙ^}u;NܬQFez(P&g7CKuBl!@ju^zv -z=HB?}`<)0}#?[7P }Ivy74 -kÂ0P2W&3 -Y+JIlg#s AH`gm`PzPBU[Y&Uq8$J}\]*Ei -)#kc2j%1T`9P\ip8mؖGV5ϡ2 LHR04"4 UT>Y4"= @yplhL֕-1Rel& Cwe4$rA -[7A,؈FCGP1)(#kDվH=S-^F8RУڵ-'Ie+igd=Wml= :U4Mi׻pk)!K))85S7W1<)O ) ni2@8]"e2 Ɛ7+JOhݸX #bB{K¹Yrե3_4ך(}SwAAXzLRu ۳/+}t?6U[L(MdkuKcS Qj~NЕ9@AM?Ag_/&ס7j F'2)~U$ȗT1F%50dԦZ1[n$iՈK46o^,'9a+d1rtѲ ¹)(N!:3^O!Ok -)t/l$ePSVW*۱ISB,Y@Rn+G5vVt׍QM>d_[?$}U*A? ZI.R8Qߑ2WdPDi>i'i|G8h֩y<3 - -0#B"S!D$ Wq]3yMÒ.OP%Wc]EI6R{1D&Й3'&^G(=ŚkڝzlYJ ="㥗}W7)Q4܋Ƃĝ5"0 ެ-zur[YD 2֡=u47XrC>$E̚|;Z]'M Pk;RZ%\a~cQp|5&RZSӣ^V=72>-\$׎0_uB:U\+n?]q_ξi+m٤3 u΃MR}|O zJ v;v<gZg(Gy2hhMDlrYK1YL`'ީe vK |p0N(ᮢ:xvi$GJǴN&&e4J`Wr\ '5:b w)JE5>RRfˤrjGX>\r&^;XiHOTQj$:8P۷&)7[>oji#Gͼa[F荨Bd.MSV"1rhg}52)\&VXSoL~ֳ;/ ^'0DJe31dկ߷ 2Y,V݅XP9PDܤ(FH1~(;cbmԜSKJeV|).aK䕹TOM.-Oʪ4{*T8)nJ!L#*tyj!`lդB/ -(@C -) -\qrI+2s鋇A]#ݬZNVXxȺ޼hQࡲyJ?DwpEV8YC#2 =*y1)Om:8$ϬPfTsbu聁P M!lK -9!ۨʤx~ 8Vge)L6^-? Vnu1r;G[9}j`),};H}g֞2SOŲ(v v+vr)g-5 !k+JyQn7nxXppF}P䆺pv0*8h7Cs*@pXc"{j))لĪ- <qW>7NPA>&ZG܋`%خܰӊ-@kk,*2i}3P|[oY{W'OHdooX#Q[_1oZ~hvuBJ⼒ Ei(> ރ x9[q1숏Q -3E#L !x~+Euy%E c [39[:W(O,)TX*VU8FmUsSN[]aH/, E75מ ƬTbG!:Q˃o:(IŐwއ6.:(W/*\n(~ߺôh2H%"^˚v Gu}zs\pIY|9RnzJ,H*1gMA=Cn0 -A!ʙSVRpJ6!NYVC=:վXNB %C)zXv XZW^"!]’*tcMZιBT5&ߥ* Ss}U7(SZϔЌֳXzک[yz^'ۏb6,8hԎ3f,ua9UA&籰7c$i4&3>C۹S2[P C -Q?bԎ3dzyp=(li߭.-箹eub:YWR(p4aŽWc},ec2hsxGf `{)]kv(?0`-YW6}x~#*6F:"^|&ykBʣ?.MB`(3rG6N<.njU =gf8]U1~jPײgQ\59Php?8_I82Wju|Xvfbl<Ś6rFdaÉ/~N<pg|<6ɗyFC_VPɼ2O^pKNۺO FN7Տjb4S k-vYZXcֺH)nyUO~[VqYȗ . \5R^ᛦ`1Vz^[bUk  xc1sab߱?uuP-; V -Nj horZљ -4qM.vBTAv_|>_H "& -BA߄ oprݛ;M<>cίqӈ{FIA&M YG#\;!Dޝ3X=œsZ[sGF #f) #7w;MYw M)ܽ ?gUr;yv}k#AQ+IKĭuVXnvYU x:Iz )oo?zv kJ^Fw y)u^vi[ s4IB6q'V0Q1.䉨(AEIi)X;g6ą']m~xI=/UKg)<5j@- FT-zFWLP2A,T1K7P\F(SЛ,$vH,4J}5L|;ѐb8"މ/'zٽm:oǶTr;dȅHLba1K@ _EY8*u b+&3:cv˟vBeYW 53+T~$9U1$ 09/ SvB+);M8;{=l]ku|k0.Oѹ~eVBԎ6 ?]a}T ExL/Gwr<ё&AK{˴s]'Y%Hw;@7qFJuprM3QJ1Oh,[ uY!_s#xݟBAvhH,h֯0bzkc}O/!@n179IBSk#ޏF\?q?OU~1Pc@aԻ`PEO1MGUvF1S@nמRV^?{cݛr=fw01Q`wWa{gYmc>h,+硥g5ÎZΡ7 ^xlTʿIQQ@[֥A,;]Q0 U֒ ktBΰ -{hJoA,u|?Lؚ~JJcnveTN+=+MƓ1XG`yb7Hc`\29 Mnɜ]fW@&6-2D oO2aCh5EdIe5Ⳳ"ZʻO6cp{uK̝tlkjGrnAa!@T9Վs$l(.uy[E=GȰRV?&V| ˍH7b]m|, pkE駸T X`HafEl)ːPvB֟4ŀ&J4W0֚sښ7g 7&;7PrFAfMFEfV/n -g+c&3_+P!~d]3@ZNxAd؊'4gG6RR<~=LAPyk6]xGfSewCeHigxj[qski{[u:FvUCYliHۻvfc^t`uKnKu>ik_|PM2NLaL#<81]5bvӖ d%jHR -O2|uE +UfrH BnԺoKB2zTA1&}OIjRz:&։{ɪ=4N&a1zo/iQ {Iq027WUWԴHlT؃Uе:tx/ǿ-4Z1lJkoRHJjD[fڲ͐Â)GLS# -,_tsY$-v:~eWYùėXJ\)&cr$ȸwL$] (r -RrkچL/кZXۖZFB_z&g5Ii0O^z݁dّFKEGA;wK9}Mŝ $:\TFԇM_m -=ed!o6;\L"+gwX^ Ժ&a3oDW/XT~dX-HqhI O!tKh2ۚBj%Tf7#uAS-H(%@1Bkk07%̄>krrMN^(ݩ vg&6J!w7O!Z_{=l6ltP-3LS2G'Bɦ,q^Q 0@mo1,m\yQOf 0t?ƏZ| dHn Zܥs"V.lR6"v+^p\lIJeUŜA08hT dM؂fjхjB A3 f,sE2z]1D`^`3`8̂AZ0_kQ:wODJs`دJrx :Qe.`fT7ަ\|TJd0QuK+q -iP!]MZm`8bA1am8&I ,ĉlr2!+l`/%}?4^"aOS\O`?vm -;A3]ԔXfjRJ O&B`_*JC -WZ^1hH͑E)8]~CJCo܃P3"Նz\#yf-3(i@dxv7:@TZwՓm0zLţ)z5s-5>o}i$~5ic KBˋs3d]Yu9xkǬs1d/_ڙD3Ú},0m9%nLh7}pZl:sޛ('_.m6#6=DjBaE+;c)jW;֎z۵5Ddww6BNLU~hi}j"4Nkg@HE1"4yI Am(6OJvny]y%xן EX1v-kr竆9"s;DW2D )!OHJNƭ('{# +0vUZefu2:Εkg&DT&b;HZ#Yg#+y܌㽵s7DۼzE  ԌT<]~ XNLK4#b.rcù' ɑT S7NINk/ 헋~@:GZd-=C_UUߚGH*fb&5NiSHP)^%Y 1_.{jB/}533C"JR}|wasF}Z-3=d'ZUt()#c`/ V֏[Z&rϚD֨\6 QԳ <{<*n_UW{K&;U BlIdVII^$SΓC7((4TV_ڿ'G!c0?r"xbkc_~aXYwiܥ&x *qjla>81v)MᎥ#G.oycPQxW60 0,.'bI֏  &'ihP-O]QAܷbv[m\I.C̤q*+T2QE|PMƶ㰞8pTA )kKkY }9KR ĎMx"֤OUx }Q.⬈|ޅbV4ŭrRǝ1!*] ˸s;i͚ŕ,v* őe[\/ܿpXaIi>i =íJ^k^ť-FPj00=u -v;-PT{E..#gPVqXC: -GU8U D_[*ᡃv{oNe8A.y3O!p^)SGGQ &Wq썲%G7wxN똽,{!g_hubwbH%!e<%O+?B'"{k:|=@6mt_abaSrɽ C x*|s ]FwWӕp̧$g::c[o0gPD y{0$OsPjlG2-2̿aW2d>AL)T` (66ɩ>Pr BHN%ZL ~PA]2$6"Ħʑ o=ˡŠib(QM6V?H)`E\OIN+#ׯˌ%X,Iӵc>`\:&*\bm\-q x%̣% Z|x>4N~./ИP?׎x9 -V;h/"?"߱ը(̓p՝GxU|ti C>Sw4O2EA)I 6b߮fd!gBOHZ~x(,ywdpVLL >*2j)C,wMgl/FPuP0Oٛ6%(m&íy_J|Oya8">#+jG,5J~ZneAQEs=SP ܍aFlp-d%Аw|sEFjpR.=BHQH I[}%{{ac ]`+6_=)qu G} -):/9^;ӥcs0+7+jN%Oy\`SN9n!巰Vj|yo4쇨xJ_)i1ЬFW"zQ[\D،A+/#oϨyW)dM%U;KkdPoU*zGکtNWցSUIfR`k!ЫH6JEŸցkM#bўUhlf|dIC7 ?ybmly_:p gu[,8beڵ1_Ⱥr=,6i4oO5Vb>_Ta ?X{qp# *6,ݿqiiCuՒd׭öhHWIF H>?q9įm]H l?mg /]f33><)_#)h*5*.lL\QM-FYE3z~0giYO? '05u@שBZkE esЊޣb^u"7=C~M><yO :Pp\5lߒŪ=T,vhp ʼnd5kѫNAA 5h5Z\IeėxؓŞ,d_žpd]!ͬ?Za~O792dž \EQ?O8~[n'>;{-x9Veu~asw^H(ޡB1B|\U7z"F%#;xLV1_|Rpi;H/vT LjӣZ mq@W=mV/~w"{n+z^l 2k0=!tGbA|!K!Y`[ƪ?t8 Klwjy&= -6.?> ̣c,5N]T-Rx]N -EvZ hA 1+L]U3WC}BE>.H}/Cm'>g Zi[7!K-''?EΛ#Q Tzei8[-' 펊ߏ.U -po{d"p9v7cepw1F6Gs%rudmG'2Ҩr@R#hk@tf1 -0Dhpu=p67GDc$ANIΒ=4i+&?qdd\SA]0Xe)Bdny6 yJTpS+> -)oyh\quR]!G --(:Nƈja Y*N@IV:5Cʴ[sf9,#M#m }mSPuBI5D"56NbJ"8@(#Y_Ho -Gv -T~8P=YfYՔs<ƫfM7j(rR&1o^?=r4f\Q[N$Wϒj/&FMFNƾF\l:.Tz~"K5Cݗ"POPU1_evIQ#U,.{េᗿwx}@ 抯w}ckʕjIL9H*{Kgvsќuх{i>G/x_ьNy *8W^ݪ=?5rui #yt뭒uws~uk˶fv^:^Z]7a|Cy{ -}V?7}ڸP!>4^ζT>0hx3>;?uk^V<Y$ӭፓaJ:QiJb?L}gCs{͍i/Z5 -ҏ^3?3ga/"Ȳ(HgNhk|u$[5[akB=] FeHPt?(/ pѦEQCop`;q 3y,jC0ѮJ:/7Bqب 4CM8"{S ȣ,)Qt۲XtU1N ȗch6r%&\{$J-]}Ƶң9Onkr^))Q财1~L׸lDvR̎q֓*صNAJz ?"mi{C=X@SG1 9D=pYG@1a-d-1B6Okm?l"`jM x@P8QvV'e߁hBm8,76SD1sJ>Ht|9O>{ ʺO=xE5B^]!4yHOJa+g)?]Qna1:UH-Dڼ4jJbVnէZì|9{WTyݒ"ԚB=TfQYH>E~'k۸X{ NޞZ|oQ9}WK=wUxuE_GRy쉳g_:N^h#tL8#L7-8~GK-KihǶE"NV$ŧ ~uKsu7ɀ|1Ũs=Kf,e), 2f&jb&ZƵ -en72oefFԬz3Y?#gIߪz#kNA*rw% -}.cVzFYA 8nd&~$g۰}N KԿNMV"@vK^%7\k VWZAsm17=V}b&ppc﵊ZCn;Y8p'La(o9yj0c%FHeU#sCr @_mmg_^ ]~p9ϑG`LC+*@dP(+"3zۦ7)}(nzi+4fDsf7 -fT?.? UQX9=O|#ϩj:K0$6ŗx9FlrE9s#=3l眓#57:XT+v&s&~sX܈ek0B-d֝V*V#pZEu-) )UE_Fꮃ6QG :tR|aJ^F -,uI [ϢƨW``C.WWKi5,J@UQ[mۇ5y(W_|s\j*.hóbJTP׾zI{wMxB(9"q"ȋ |N!7~ز4J=`4;~XF^!0ЯƯͲpnf٪I)0 -yjbل  *nLzrȗ%ދn+ThhJʛh7 6FYO|I<ܘ eK50EËƭOɡr:C^cL)tˆ=II8#TjC3(K;@cTg\_o5mr%Oc9{'"x\ uГu9$XWTRxPjdDL@I >t9$3:dJWYF[n3z+t˘>Om^Ns\`m[{*Q-P*Zqɲ@if6^ʫG|4rŪJ૝8սXMEnR>\CyDJcU{ɧȧ9=Xex11/2Պ5YئE3G|5s`},nŘ%e]D}fނQ.Y{4:rĞS`C'5EkZ}YgZ>`bDu(<E;Jfz)d0kF@2-U?;}Cbs#E}2GͲ#y}&1P3G\pAg9Iʶ25d:~C -I}zr"^.%Nëj* CHM%I?m`=঑+i_TKA/J=b$}訅l-E%}{bu+Q>6V1F.*sD;4ߧSd+ na5 iPy={ -yZ %^ Z/C.o1 2\;oIokLAض0ꖲz625}su-V2i}g&5eiU&[s> -6d$ MҦ,MXGDTE42 Ht0J q~> -kQ#be})\9{|!Ag1rx$MǾ?d#v/hM̄.h;iZhp$ ;$-vꄚ#P_QG 0< -z:Lss7:`Ui ~LU5Y=]/5ÁWiuAxgtIySb&_~k?WO?^6ޅ$Wavg9xJ?'xq[-@caʬnu0G_oN1#AӶdk) uKLCjx6 'ILU#(WNA0W}!FB9Y FQS:tk7tMR} jo1X:Mtja=ªIn8S-+!Z7ݗOmtXop\(Z@NAY^nC:Ow#մ2iMsަ%[*cD#KD]KKkA;BK]Y6Kvcpݛ}SuidF痳65`iw~WfR _= -"ge1ulq4̥s\]4:mK%̏]sm2dYQy!(?5^8a {0iTtڊ,YLV}P!I]jHD+Ѫ~m"L񖶨0O@5z^qvNE`Sc2+Pu,?YX:ʌCm.*(LjO r$”(}!k kV2" }LVA!Ec]gddDC!EVL.5s&̖3 YSjZ&]f$fJxΙ vʰߦTqP[o᧸aۦsxYrt#a(Kl6V'0Z?&Oߚ04Mș׾ƂeRõh6>(rR*ExB--šmX{kR @ߪ6+hdh+-ȵ8>Q( >(V;|\~}^|z:yj6 -I8|qJ<\ո+EtT0fћh̽EL^t_<2skVr@^%Z۝㪏cx ղ$ɍ~`7Dz}/{Ȭ{cciYJ@`1$o ?dQs2̛& nWsNeo qo>}Au`$ "RK8Fu -"ey/'7>єaܩ9)g5 -j6sӲa.l/:m_`CIbSYD]FE 3n)[(q1¥QMES߀yuUߘ1_]̊UE +l@{ :Ȯҁ4ՄprHoF_>O?[xf _gҊgCI r >Ym,kB~Nyz|gb0!I-AzKa T&O+MeZ; -/@h.KKXwd306Jh'C$4fZJ43T ;hvU!c -G?O1[/wq,pgxћYqx}h&~ۙv7Vcx6|Љ NH"1vzٹiSB~-[uDȓH` R$ ma@7ѳ -v1O^]7& [ aehZg 5.Z -t@Q&zqxSy꬜N1w:R5:8T }DDҖ. b0:WР-DA7*14)aIV-١ZfT3ڞh:5v )8([_"GƜzHy )ϾGaͻQH=U93{7j="hYec&| Lg掣7sjwN]OWڹ ,*_@R& iR^OqQ0aࣂ'1~ 75.̯>ѽKhB~^.71lt(B˂ %C[{{8U`]=186FLϮJo4~L.+ɌVb4EZ73n΃<)/؜9ϼFGF.[lʡ5wOMieb79=pڏ)q-^f[QizBX ϧ#'FN~4Ha}{vj7~@ǘ/idK[}d T)~js^,x]qG&5r~"p'  jX*-x ` Grz;AwYҞ P4-D+ V^SGq(b3M6IA:}xPt*|m f5ZfLaZ[oҋMAvzhN̹G ZVQ8ޚ~m;fo1gk=o3Rzfe}Hf_@n ^%k~sͭĭ=qnέWS|`.$~zٝ@u@ݾ#I%?Y! ehχ0c؊jMV66d-5ג=ކ/Sq+{Ƀ0~y˚ȅǖ;Ml$^3͕kJ!." [sUE{ס- AȳT<ɫOμ -)OH~?-&W87:w}6M`֛_??«EJ(;Li ->'M<$pIo0,fRi?igOsqIACϿ޷7ؿ,7}omה m{pxj$I|pmoQI9Nig(4 mw}{:Ԟu~{Ksk2`5|/BF0rUCnȑ3 rx\Dkn^nݣSkFH-?:᲌֔>(k}f \_y[>sM_FNGFxXS6?[SǟoT/j‰'VNct?]Hcj\fn/Na|Ȓf3yeQ\.-n;&0W҆zt"Vޮ%ߖ#'W\ZN k宿cꍋOGo<\1 G,,e(a+wYd.9>~Q7L.> o]S(!7$ Mr F'CQ};ŅNuJi󷎖RlTL*{=*dd/UZWW/۝}_(6 \QTSѢg^ܜ 5B{v<gZ8 HMKC`ըEdz/D^\]G++RDi+fʛ[6F!TIUѣH^LbdKbE,xˈ_R@j'ը,ԴQ uv t9Ly1@&l}{L>x{WFжiFgmpoly;St[7:w2܈kx&7+cx3ٻ <0ـG\Wfw0%բнex2x$YD&վajV k[PWqjLJB@0YCPX9NJ/9b[0Jq8tve'Hy.z/-Mخi|HХu&i%,>0ͬϫsHُ -N^vؓcz W]C0@jqiБs3~x -~LsWWW{v.?b5[#\\c[WϰQqBɧD̰HA.qP1uųë٩,?4dó i2?~f}˟܏|X#%Y1 !J}jy~V>H?ۣXn2Hn8 6n7b."{"'ȪD[ټ;9Ǹy+ߥ.%|([+JᄒX!FCg\ʃ`8SʰқzA1H|9:qs4<>ĕׇ6ɋ?ߜ|Hes᷻O'  0c endstream endobj 2805 0 obj <> endobj 2815 0 obj <>stream -8;YPl6&t4a%*]sB+FuMgXLUqLF]g;oIC;aQ%QM75)/E5,,@,iZ=n+2m)F]:^KMK)A)Kd6;DHG; -6&4T.W^W9N0'-\"hD.kLe],*9+UmfAL+a,-`],HI)Je>gZ1H5Q%S<"4QW6;315]"* -Q`C@;%#8I%5XHhWk#iis*_.dl2k:H"./H%mYM#\&nK(k"Z?'1Hl7rS"Ct9$"Ki;rl -HBMEFUO:WJ,1-4M+OCebOV.`\0E!3b+5BRUDN+)nL/)3jgU(2.HB\M`hT>i_`Je@% -(AElPQh2K`BTFT`Eg#3$QY/(t[pps6RU@s4NKoFgA -H!Q>fBQA,)6D:SFL_tDU)h+[]!7"cnfAV.)=CS'B8hoVL(K%-G$]Ju\El$fjXekmN -1AtNge>^IqY@C&2oC)KurkZ&7^A%6fbB=*:2F=s&>>()L*3BdRq]u'i8.K;`HNNcL -3D8Jn.*;kJ0d<:.g\/nK^6e3jbND_G_d/(&M5(.m[Kku,,jTZ/ZKU-!?/*9O_;FkU -kUE>(;8.dIaYpsk!q1C+N*g?;'t2Z4/>uTg<2D=Q1H`mZ$p)RI`97!l!N8YBL_8`k(KVpU!;a(A1[-3E -Xpej;8$Vk#B6>JcdFHN!I&>LV+D-;o`SeB%:1ldVO/9)CTR;qNHC/5B-U0QmIP&,/MUEs -,-Q&'l?fUr<8Ap\a?"]1@.B"!7Uq2#/n$T6?K[j;#tC&:,STp2fJ77ect6J?Fn]VH -\u0O9q5TH"-o(9?qa)JmN$_aF9kbU#**b9,(34oH0Ie,kb\4j#2Mn1h,O]^;JLR@) -[go&k92e,$&b(Gp&]n961;LUho*AVVulc/XTt-#jW+25'_(B1D!QiS&C<=6*@a:i2fUj`TTJ\c/o0 -_CY+R$$F78:Xu?CIg,nKe-Cs~> endstream endobj 2816 0 obj [/Indexed/DeviceRGB 255 2817 0 R] endobj 2817 0 obj <>stream -8;X]O>EqN@%''O_@%e@?J;%+8(9e>X=MR6S?i^YgA3=].HDXF.R$lIL@"pJ+EP(%0 -b]6ajmNZn*!='OQZeQ^Y*,=]?C.B+\Ulg9dhD*"iC[;*=3`oP1[!S^)?1)IZ4dup` -E1r!/,*0[*9.aFIR2&b-C#soRZ7Dl%MLY\.?d>Mn -6%Q2oYfNRF$$+ON<+]RUJmC0InDZ4OTs0S!saG>GGKUlQ*Q?45:CI&4J'_2j$XKrcYp0n+Xl_nU*O( -l[$6Nn+Z_Nq0]s7hs]`XX1nZ8&94a\~> endstream endobj 2812 0 obj <>>>/Subtype/Form>>stream -0.329 0.435 1 rg -/GS0 gs -q 1 0 0 1 20.8936 45.584 cm -0 0 m -0 657.033 l -0 663.426 2.232 668.609 4.986 668.609 c -333.663 668.609 l -336.417 668.609 338.649 663.426 338.649 657.033 c -338.649 0 l -338.649 -6.394 336.417 -11.576 333.663 -11.576 c -4.986 -11.576 l -2.232 -11.576 0 -6.394 0 0 c -f -Q - endstream endobj 2813 0 obj <>>>/Subtype/Form>>stream -0.329 0.435 1 rg -/GS0 gs -q 1 0 0 1 370.9829 38.5459 cm -0 0 m -0 783.538 l -0 786.292 2.232 788.524 4.986 788.524 c -353.048 788.524 l -355.802 788.524 358.034 786.292 358.034 783.538 c -358.034 0 l -358.034 -2.754 355.802 -4.986 353.048 -4.986 c -4.986 -4.986 l -2.232 -4.986 0 -2.754 0 0 c -f -Q - endstream endobj 2814 0 obj <>>>/Subtype/Form>>stream -0.329 0.435 1 rg -/GS0 gs -q 1 0 0 1 741 38.4873 cm -0 0 m -0 783.538 l -0 786.292 2.166 788.524 4.839 788.524 c -342.597 788.524 l -345.27 788.524 347.435 786.292 347.435 783.538 c -347.435 0 l -347.435 -2.754 345.27 -4.986 342.597 -4.986 c -4.839 -4.986 l -2.166 -4.986 0 -2.754 0 0 c -f -Q - endstream endobj 2820 0 obj <> endobj 2807 0 obj <> endobj 2819 0 obj <> endobj 2818 0 obj <> endobj 2802 0 obj <> endobj 2821 0 obj [/View/Design] endobj 2822 0 obj <>>> endobj 2800 0 obj <> endobj 2801 0 obj <> endobj 2792 0 obj <> endobj 2793 0 obj <> endobj 2794 0 obj <> endobj 2810 0 obj <> endobj 2796 0 obj <> endobj 2795 0 obj <> endobj 2797 0 obj <> endobj 2798 0 obj <> endobj 2811 0 obj <> endobj 2799 0 obj <> endobj 2836 0 obj <> endobj 2837 0 obj <>stream -H{|MWZgCx'N9WGţģ̠~䝐' -A1jDVTA5S%^I$W$:U" FϜ뜽/ -V@kసĨ\FϰI;7IJldbT\Xк;3ۓt| -ЮgtDH̏ wþt\RrP1 a!8&b@-ߍ IN^Ǜ!qO?8陘05錫r((S"ƿEYkծ~Vu H8sT϶B?ϚʹDgqg)#xި Jk~MZVk[lu4i"wKHt=)u 8SC\+p ͘9xcx b5'R/Oc)b(|ZHiV_im* 4%EIS*feO9QN+K4'fOzQ]Sxڸ[퉎z=D }>A4}~T?o#ÌQƟ?9!#8cW]g¨1f`N6͕fo4e5|,`Z}Mk5Z`'{}~`{Dsas4qp:9N9ηfR@d@lN;Y23QOU]zBͮ,M=MDoPLƿ/ո76܃XԂPAE0JT2nhe+aJ2KYӕO]J?Q+M"Qdb; q^jc=x#C}>M~2 0Z1cq8k\2O}xjYϜd&Ifi4s̯,pofL՞1QLKo~0 &B A,C&$d>[TI0f@$, a|_f )`>܅A$TPJx -a}| \^"T#A_)hڱ5J\m<=0s^] S+vaO>`88 C`P 9+pQC1Q۸TNPBop>B mx%v4 -NݩS)w]ԓ>'ʧt nRRݢb*!+m;wԈƉ8 clx*^iky2H2DvdoGsd a2\F`PGqs.t9 2,Zj<ߋ<5,5BG>J;Y$Έ(%?qtir:Չj$&9[n$TmTjGu^ bNRcUG7EܠWD'~Q!| -U2Jib% -EcDԈp -E(Nq[_UUis B(IP.U%ҋ.%b,\Y)"e5;K/)J;w(Ύ;yoy%,p%i xIT:C1hq*G7}cr&Gs]>xŽ7H@?WzUlh ^C" K3\ 11Um5N&UJʘ@b*ʥTʭ(5!&?LʫpʧTlıۯx61x.S!&X RMn|*? /:Eoڨ7"w.w:Ѷ-m+ccmml۩H!HM\88kn.V0 7p - ..۸kSq{B=cYp.EI{\w#K2༒؏s>d͆M.&;88taeuEtQ]CtqB[6]BɣKH]FtyJ̺帼\/qN tN#'Ɖuv C1A:ʆp[DE6Җe[z#h=BP=ō_QRƪ)-ei%r;-i9pZ8h4m$\EX5Q-U+Z캍^;Ղv:bۍTR1*NɶUoWmSI&Ҕ1%=vT U?`&5LiSpSSc817f6L 32c|ҿk>g$sv/m4>Ω|O83LvأN˴64K,_mښA LGf:&o⍜BV,Y%Ke->ҢeV&rDı?P^ - GBBTBéXx1*N%$EP)*MTR9*OQH2=OU*@jTjPMEEzdKTSjH(b)SjJͨ9ԊZֆR;jO#uԅ׺ݤq{HK.+mOttפҥ^.=:B iQCGKKK'I{ޓ6ޓLS >y}FT4Kz\|5Cxxb1O6hY{ u6xR -m~6N;!vI|! {3းg GxHfRӒi$BgI8IM3 =Ifj,13@O%!W ?O$\|IKYHx($?& YH8 =j 7K !v˦'0]hH%$fP$; P*;+h 0kc)RN阁1fcb>||XEXS|d|%XeXXUX푀$&NG$}qg8󸀋op$ -Fn$8a bc6bR[۰;_`W'b -Q ^&@Ga33,MWNtCwQ"r#H(!|Y3҈DD \F&Ce<*j ZOPєzx)k& -1h$^eġxB LH6ڡ#B'tFtfP=,z"L - iFQ!]37Uǽm܋f''|dxU[ ɲ yT߽:A(!cƗpaS$; Ew#_1᡺4 en+EomPKt{^k)9F6q„ch#"|xᮖ iٴY~4`w&[}\id=֝^qe%"VB$IErɔDLUGV[&$C!cP\Vjݦ{ -| 6<:3.3XI3\L`zw#1SpPUmT{5D U}|}|kzo\߹ܝa„O3d]]V("P Ѳ]1 -ɷ5>H$e -VTy/&;C[zYI,Ň-ccl *N(e8 IP@4LHNʅ3&)05 tjh:eC2d20A7߮~n:D#=@@,c){]R^InIK7]?p஭pEf%<G)&z[w_ uԌ8?`=;, ʥ-6jD^Iog2}˰13- -tƼ Q >[.c;u=@oe/ÊQ 7EU:Ba^`'7pmA/jQz@wQ&zn ށ]` JkBWW hWіC KT2x$\9kuJ+T3BZj ,'D?%OWdB\:#?, hޒzww9yp')d~u[LfVN*O"ZRբZ0=9C$ֵ"*tE'r 0Ka-K($=(\[drg22M'30l4 Yʖ*:CąG8Rwx4{ȟw,omj~p`-)8Hrq1.C21.XvZ 3aǜ/8$#lj!LA9Ae%mpК4wH? {3$ aTRw f4Wb0|(BcTK3#FT;qGr #r׈;d0aZ )=QqTpk@mL[ "\` #lƇ /Ln^aL8p#:^N Ԯ zDBcAW?p'h^My|~8{@ZGDxBD8`@sa!t#E4cFJ K#Ui1pqI`WZ 5 *:BhDb.+xC!MhgwL(5MO(γ'9P!bBP5ڐۚ5k@s[WeiAN6MVq4; -̛>'VY9NfSљt+ld{^6>?QiC{cTduuܻijK<$v%e+v9[`eU"zK^`(Á lʃ\s43óni7oPப>,*BœmP_?xpW !1`>FcĝVgiJyΥGNhr3e/lLTg& UƯW6~EԊhY-_Ouʊ=O͹8ö SJAo%]Tͯ84|pq%sSiR+O8~5.vz -zLZԨ d=*HBH *{+Gki:LƚjM5Jڒ Qrwqr{}&w$? ɏd ǒ@Z-Hf2 CYыTv־T~5LKDYkȒ -U>XE@S.Gv^xʉP9hM`a܋ ˓ ȥMͅ//.LLSH;˾wQ.!Z82W*eno9'_I\ve_Slg_EQy&x/*Vm?il,*:&Wk畹v#vNW`ʨ2ܢZmng2J|udO h*k\wQ?=8=ﻯ&G6{CH&YL`kD6 - 6T[M -<4H$)ep(A -TZ cǰcZԖav2v*eJ^ݛ?ܳgg}}WEK@8]V0qJ>R"Bjxa!?7{j\w:Nѩzgxb?ʊ3۾ef58ҙi}dbbS \F t!aWZD). p%-,]}Œ(L2!Osdi\WB=4Nj2cP(v}Ȯcc@2j/$+xDUQqQ -P1 -@0`=e $k
-
- - - -
-
- - - - -
-

-R Tools for Eurostat Open Data

-

This rOpenGov R package provides tools to access Eurostat database, which you can also browse on-line for the data sets and documentation. For contact information and source code, see the package website.

-
-
-

-Installation

-

Release version (CRAN):

-
install.packages("eurostat")
-

Development version (Github):

-
library(devtools)
-install_github("ropengov/eurostat")
-

Overall, the eurostat package includes the following functions:

-
clean_eurostat_cache    Clean Eurostat Cache
-cut_to_classes          Cuts the Values Column into Classes and
-                        Polishes the Labels
-dic_order               Order of Variable Levels from Eurostat
-                        Dictionary.
-eu_countries            Countries and Country Codes
-eurostat-package        R Tools for Eurostat open data
-eurostat_geodata_60_2016
-                        Geospatial data of Europe from Gisco in 1:60
-                        million scale from year 2016
-eurotime2date           Date Conversion from Eurostat Time Format
-eurotime2num            Conversion of Eurostat Time Format to Numeric
-get_eurostat            Read Eurostat Data
-get_eurostat_dic        Download Eurostat Dictionary
-get_eurostat_geospatial
-                        Download Geospatial Data from GISGO
-get_eurostat_json       Get Data from Eurostat API in JSON
-get_eurostat_raw        Download Data from Eurostat Database
-get_eurostat_toc        Download Table of Contents of Eurostat Data
-                        Sets
-harmonize_country_code
-                        Harmonize Country Code
-label_eurostat          Get Eurostat Codes
-search_eurostat         Grep Datasets Titles from Eurostat
-tgs00026                Auxiliary Data
-
-
-

-Finding data

-

Function get_eurostat_toc() downloads a table of contents of eurostat datasets. The values in column ‘code’ should be used to download a selected dataset.

-
# Load the package
-library(eurostat)
-library(rvest)
-
-# Get Eurostat data listing
-toc <- get_eurostat_toc()
-
-# Check the first items
-library(knitr)
-kable(head(toc))
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
titlecodetypelast update of datalast table structure changedata startdata endvalues
Database by themesdatafolderNANANANANA
General and regional statisticsgeneralfolderNANANANANA
European and national indicators for short-term analysiseuroindfolderNANANANANA
Business and consumer surveys (source: DG ECFIN)ei_bcsfolderNANANANANA
Consumer surveys (source: DG ECFIN)ei_bcs_csfolderNANANANANA
Consumers - monthly dataei_bsco_mdataset27.09.201827.09.20181980M012018M09NA
-

With search_eurostat() you can search the table of contents for particular patterns, e.g. all datasets related to passenger transport. The kable function to produces nice markdown output. Note that with the type argument of this function you could restrict the search to for instance datasets or tables.

-
# info about passengers
-kable(head(search_eurostat("passenger transport")))
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
titlecodetypelast update of datalast table structure changedata startdata endvalues
Volume of passenger transport relative to GDPtran_hv_pstradataset30.07.201830.07.201820002016NA
Modal split of passenger transporttran_hv_psmoddataset27.08.201827.08.201819902016NA
Railway transport - total annual passenger transport (1 000 pass., million pkm)rail_pa_totaldataset20.09.201807.09.201820042016NA
Railway transport - passenger transport by type of transport (detailed reporting only) (1 000 pass.)rail_pa_typepasdataset20.09.201831.08.201720042016NA
Railway transport - passenger transport by type of transport (detailed reporting only) (million pkm)rail_pa_typepkmdataset20.09.201831.08.201720042016NA
International railway passenger transport from the reporting country to the country of disembarkation (1 000 passengers)rail_pa_intgongdataset20.09.201817.07.201820042017NA
-

Codes for the dataset can be searched also from the Eurostat database. The Eurostat database gives codes in the Data Navigation Tree after every dataset in parenthesis.

-
-
-

-Downloading data

-

The package supports two of the Eurostats download methods: the bulk download facility and the Web Services’ JSON API. The bulk download facility is the fastest method to download whole datasets. It is also often the only way as the JSON API has limitation of maximum 50 sub-indicators at a time and whole datasets usually exceeds that. To download only a small section of the dataset the JSON API is faster, as it allows to make a data selection before downloading.

-

A user does not usually have to bother with methods, as both are used via main function get_eurostat(). If only the table id is given, the whole table is downloaded from the bulk download facility. If also filters are defined the JSON API is used.

-

Here an example of indicator ‘Modal split of passenger transport’. This is the percentage share of each mode of transport in total inland transport, expressed in passenger-kilometres (pkm) based on transport by passenger cars, buses and coaches, and trains. All data should be based on movements on national territory, regardless of the nationality of the vehicle. However, the data collection is not harmonized at the EU level.

-

Pick and print the id of the data set to download:

-
# For the original data, see
-# http://ec.europa.eu/eurostat/tgm/table.do?tab=table&init=1&plugin=1&language=en&pcode=tsdtr210
-id <- search_eurostat("Modal split of passenger transport", 
-                         type = "table")$code[1]
-print(id)
-

[1] “t2020_rk310”

-

Get the whole corresponding table. As the table is annual data, it is more convient to use a numeric time variable than use the default date format:

-
dat <- get_eurostat(id, time_format = "num")
-

Investigate the structure of the downloaded data set:

-
str(dat)
-
## Classes 'tbl_df', 'tbl' and 'data.frame':    2536 obs. of  5 variables:
-##  $ unit   : Factor w/ 1 level "PC": 1 1 1 1 1 1 1 1 1 1 ...
-##  $ vehicle: Factor w/ 3 levels "BUS_TOT","CAR",..: 1 1 1 1 1 1 1 1 1 1 ...
-##  $ geo    : Factor w/ 35 levels "AT","BE","CH",..: 1 2 3 4 5 6 7 8 9 10 ...
-##  $ time   : num  1990 1990 1990 1990 1990 1990 1990 1990 1990 1990 ...
-##  $ values : num  11 10.6 3.7 9.1 11.3 32.4 14.9 13.5 6 24.8 ...
-
kable(head(dat))
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
unitvehiclegeotimevalues
PCBUS_TOTAT199011.0
PCBUS_TOTBE199010.6
PCBUS_TOTCH19903.7
PCBUS_TOTDE19909.1
PCBUS_TOTDK199011.3
PCBUS_TOTEL199032.4
-

Or you can get only a part of the dataset by defining filters argument. It should be named list, where names corresponds to variable names (lower case) and values are vectors of codes corresponding desidered series (upper case). For time variable, in addition to a time, also a sinceTimePeriod and a lastTimePeriod can be used.

-
dat2 <- get_eurostat(id, filters = list(geo = c("EU28", "FI"), lastTimePeriod=1), time_format = "num")
-kable(dat2)
-
-

-Replacing codes with labels

-

By default variables are returned as Eurostat codes, but to get human-readable labels instead, use a type = "label" argument.

-
datl2 <- get_eurostat(id, filters = list(geo = c("EU28", "FI"), 
-                                         lastTimePeriod = 1), 
-                      type = "label", time_format = "num")
-kable(head(datl2))
-

Eurostat codes in the downloaded data set can be replaced with human-readable labels from the Eurostat dictionaries with the label_eurostat() function.

-
datl <- label_eurostat(dat)
-kable(head(datl))
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
unitvehiclegeotimevalues
PercentageMotor coaches, buses and trolley busesAustria199011.0
PercentageMotor coaches, buses and trolley busesBelgium199010.6
PercentageMotor coaches, buses and trolley busesSwitzerland19903.7
PercentageMotor coaches, buses and trolley busesGermany (until 1990 former territory of the FRG)19909.1
PercentageMotor coaches, buses and trolley busesDenmark199011.3
PercentageMotor coaches, buses and trolley busesGreece199032.4
-

The label_eurostat() allows conversion of individual variable vectors or variable names as well.

-
label_eurostat_vars(names(datl))
-

Vehicle information has 3 levels. You can check them now with:

-
levels(datl$vehicle)
-
-
-
-

-Selecting and modifying data

-
-

-EFTA, Eurozone, EU and EU candidate countries

-

To facilitate smooth visualization of standard European geographic areas, the package provides ready-made lists of the country codes used in the eurostat database for EFTA (efta_countries), Euro area (ea_countries), EU (eu_countries) and EU candidate countries (eu_candidate_countries). These can be used to select specific groups of countries for closer investigation. For conversions with other standard country coding systems, see the countrycode R package. To retrieve the country code list for EFTA, for instance, use:

-
data(efta_countries)
-kable(efta_countries)
- - - - - - - - - - - - - - - - - - - - - - - -
codename
ISIceland
LILiechtenstein
NONorway
CHSwitzerland
-
-
-

-EU data from 2012 in all vehicles:

-
dat_eu12 <- subset(datl, geo == "European Union (current composition)" & time == 2012)
-kable(dat_eu12, row.names = FALSE)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
unitvehiclegeotimevalues
PercentageMotor coaches, buses and trolley busesEuropean Union (current composition)20129.5
PercentagePassenger carsEuropean Union (current composition)201282.9
PercentageTrainsEuropean Union (current composition)20127.7
-
-
-

-EU data from 2000 - 2012 with vehicle types as variables:

-

Reshaping the data is best done with spread() in tidyr.

-
library("tidyr")
-dat_eu_0012 <- subset(dat, geo == "EU28" & time %in% 2000:2012)
-dat_eu_0012_wide <- spread(dat_eu_0012, vehicle, values)
-kable(subset(dat_eu_0012_wide, select = -geo), row.names = FALSE)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
unittimeBUS_TOTCARTRN
PC200010.482.47.2
PC200110.282.77.1
PC20029.983.36.8
PC20039.983.56.7
PC20049.883.46.8
PC20059.883.36.9
PC20069.783.27.1
PC20079.883.17.1
PC20089.982.87.4
PC20099.383.67.1
PC20109.483.47.2
PC20119.483.27.4
PC20129.582.97.7
-
-
-

-Train passengers for selected EU countries in 2000 - 2012

-
dat_trains <- subset(datl, geo %in% c("Austria", "Belgium", "Finland", "Sweden")
-                     & time %in% 2000:2012 
-                     & vehicle == "Trains")
-
-dat_trains_wide <- spread(dat_trains, geo, values) 
-kable(subset(dat_trains_wide, select = -vehicle), row.names = FALSE)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
unittimeAustriaBelgiumFinlandSweden
Percentage20009.76.35.16.8
Percentage20019.76.44.87.1
Percentage20029.76.54.87.1
Percentage20039.56.54.77.0
Percentage20049.47.14.76.8
Percentage20059.86.64.87.1
Percentage200610.06.94.87.6
Percentage200710.07.15.07.9
Percentage200811.17.55.48.6
Percentage200911.17.55.18.7
Percentage201011.07.75.28.7
Percentage201111.37.75.08.7
Percentage201211.87.85.39.1
-
-
-
-

-Visualization

-

Visualizing train passenger data with ggplot2:

-
library(ggplot2)
-p <- ggplot(dat_trains, aes(x = time, y = values, colour = geo)) 
-p <- p + geom_line()
-print(p)
-

-

Triangle plot

-

Triangle plot is handy for visualizing data sets with three variables.

-
library(tidyr)
-library(plotrix)
-library(eurostat)
-library(dplyr)
-library(tidyr)
-
-# All sources of renewable energy are to be grouped into three sets
- dict <- c("Solid biofuels (excluding charcoal)" = "Biofuels",
- "Biogasoline" = "Biofuels",
- "Other liquid biofuels" = "Biofuels",
- "Biodiesels" = "Biofuels",
- "Biogas" = "Biofuels",
- "Hydro power" = "Hydro power",
- "Tide, Wave and Ocean" = "Hydro power",
- "Solar thermal" = "Wind, solar, waste and Other",
- "Geothermal Energy" = "Wind, solar, waste and Other",
- "Solar photovoltaic" = "Wind, solar, waste and Other",
- "Municipal waste (renewable)" = "Wind, solar, waste and Other",
- "Wind power" = "Wind, solar, waste and Other",
- "Bio jet kerosene" = "Wind, solar, waste and Other")
-# Some cleaning of the data is required
- energy3 <- get_eurostat("ten00081") %>%
- label_eurostat(dat) %>%
- filter(time == "2013-01-01",
- product != "Renewable energies") %>%
- mutate(nproduct = dict[as.character(product)], # just three categories
- geo = gsub(geo, pattern=" \\(.*", replacement="")) %>%
- select(nproduct, geo, values) %>%
- group_by(nproduct, geo) %>%
- summarise(svalue = sum(values)) %>%
- group_by(geo) %>%
- mutate(tvalue = sum(svalue),
- svalue = svalue/sum(svalue)) %>%
- filter(tvalue > 1000) %>% # only large countries
- spread(nproduct, svalue)
- 
-# Triangle plot
- par(cex=0.75, mar=c(0,0,0,0))
- positions <- plotrix::triax.plot(as.matrix(energy3[, c(3,5,4)]),
-                     show.grid = TRUE,
-                     label.points= FALSE, point.labels = energy3$geo,
-                     col.axis="gray50", col.grid="gray90",
-                     pch = 19, cex.axis=0.8, cex.ticks=0.7, col="grey50")
-
- # Larger labels
- ind <- which(energy3$geo %in%  c("Norway", "Iceland","Denmark","Estonia", "Turkey", "Italy", "Finland"))
- df <- data.frame(positions$xypos, geo = energy3$geo)
- points(df$x[ind], df$y[ind], cex=2, col="red", pch=19)
- text(df$x[ind], df$y[ind], df$geo[ind], adj = c(0.5,-1), cex=1.5)
-

-
-

-Maps

-
-

-Disposable income of private households by NUTS 2 regions at 1:60mln resolution using tmap

-

The mapping examples below use tmap package.

-
library(dplyr)
-library(eurostat)
-library(sf)
-
## Linking to GEOS 3.6.2, GDAL 2.2.3, proj.4 4.9.3
-
library(tmap)
-
-# Download attribute data from Eurostat
-sp_data <- eurostat::get_eurostat("tgs00026", time_format = "raw", stringsAsFactors = FALSE) %>% 
-  # subset to have only a single row per geo
-  dplyr::filter(time == 2010, nchar(geo) == 4) %>% 
-  # categorise
-  dplyr::mutate(income = cut_to_classes(values, n = 5))
-
## Table tgs00026 cached at /tmp/RtmpEtdcUo/eurostat/tgs00026_raw_code_FF.rds
-
# Download geospatial data from GISCO
-geodata <- get_eurostat_geospatial(output_class = "sf", resolution = "60", nuts_level = 2, year = 2013)
-
## 
-## COPYRIGHT NOTICE
-## 
-## When data downloaded from this page 
-## <http://ec.europa.eu/eurostat/web/gisco/geodata/reference-data/administrative-units-statistical-units>
-## is used in any printed or electronic publication, 
-## in addition to any other provisions 
-## applicable to the whole Eurostat website, 
-## data source will have to be acknowledged 
-## in the legend of the map and 
-## in the introductory page of the publication 
-## with the following copyright notice:
-## 
-## - EN: (C) EuroGeographics for the administrative boundaries
-## - FR: (C) EuroGeographics pour les limites administratives
-## - DE: (C) EuroGeographics bezuglich der Verwaltungsgrenzen
-## 
-## For publications in languages other than 
-## English, French or German, 
-## the translation of the copyright notice 
-## in the language of the publication shall be used.
-## 
-## If you intend to use the data commercially, 
-## please contact EuroGeographics for 
-## information regarding their licence agreements.
-## 
-
## No encoding supplied: defaulting to UTF-8.
-
## 
-## # --------------------------
-## HEADS UP!!
-## 
-## Function now returns the data in 'sf'-class (simple features) 
-## by default which is different 
-## from previous behaviour's 'SpatialPolygonDataFrame'. 
-## 
-## If you prefer either 'SpatialPolygonDataFrame' or 
-## fortified 'data_frame' (for ggplot2::geom_polygon), 
-## please specify it explicitly to 'output_class'-argument!
-## 
-## # --------------------------          
-## 
-
# merge with attribute data with geodata
-map_data <- inner_join(geodata, sp_data)
-
## Joining, by = "geo"
-

Construct the map

-
map1 <- tmap::tm_shape(geodata) +
-  tmap::tm_fill("lightgrey") +
-  tmap::tm_shape(map_data) +
-  tmap::tm_grid() +
-  tmap::tm_polygons("income", title = "Disposable household\nincomes in 2010",  
-                    palette = "Oranges")
-print(map1)  
-

-

Interactive maps can be generated as well

-
# Interactive
-tmap_mode("view")
-map1
-
-# Set the mode back to normal plotting
-tmap_mode("plot")
-print(map1)
-
-
-

-Disposable income of private households by NUTS 2 regions in Poland with labels at 1:1mln resolution using tmap

-
library(eurostat)
-library(dplyr)
-library(sf)
-library(RColorBrewer)
-
-# Downloading and manipulating the tabular data
-print("Let us focus on year 2014 and NUTS-3 level")
-
## [1] "Let us focus on year 2014 and NUTS-3 level"
-
euro_sf2 <- get_eurostat("tgs00026", time_format = "raw",
-                         stringsAsFactors = FALSE,
-             filter = list(time = "2014")) %>% 
- 
-  # Subset to NUTS-3 level
-  dplyr::filter(grepl("PL",geo)) %>% 
-  # label the single geo column
-  mutate(label = paste0(label_eurostat(.)[["geo"]], "\n", values, "€"),
-         income = cut_to_classes(values))
-
-print("Download geospatial data from GISCO")
-
## [1] "Download geospatial data from GISCO"
-
geodata <- get_eurostat_geospatial(output_class = "sf", resolution = "60", nuts_level = 2, year = 2013)
-
## 
-## COPYRIGHT NOTICE
-## 
-## When data downloaded from this page 
-## <http://ec.europa.eu/eurostat/web/gisco/geodata/reference-data/administrative-units-statistical-units>
-## is used in any printed or electronic publication, 
-## in addition to any other provisions 
-## applicable to the whole Eurostat website, 
-## data source will have to be acknowledged 
-## in the legend of the map and 
-## in the introductory page of the publication 
-## with the following copyright notice:
-## 
-## - EN: (C) EuroGeographics for the administrative boundaries
-## - FR: (C) EuroGeographics pour les limites administratives
-## - DE: (C) EuroGeographics bezuglich der Verwaltungsgrenzen
-## 
-## For publications in languages other than 
-## English, French or German, 
-## the translation of the copyright notice 
-## in the language of the publication shall be used.
-## 
-## If you intend to use the data commercially, 
-## please contact EuroGeographics for 
-## information regarding their licence agreements.
-## 
-
## No encoding supplied: defaulting to UTF-8.
-
## 
-## # --------------------------
-## HEADS UP!!
-## 
-## Function now returns the data in 'sf'-class (simple features) 
-## by default which is different 
-## from previous behaviour's 'SpatialPolygonDataFrame'. 
-## 
-## If you prefer either 'SpatialPolygonDataFrame' or 
-## fortified 'data_frame' (for ggplot2::geom_polygon), 
-## please specify it explicitly to 'output_class'-argument!
-## 
-## # --------------------------          
-## 
-
# Merge with attribute data with geodata
-map_data <- inner_join(geodata, euro_sf2)
-
## Joining, by = "geo"
-
# plot map
-map2 <- tm_shape(geodata) +
-  tm_fill("lightgrey") +
-  tm_shape(map_data, is.master = TRUE) +
-  tm_polygons("income", title = "Disposable household incomes in 2014",
-              palette = "Oranges", border.col = "white") + 
-  tm_text("NUTS_NAME", just = "center") + 
-  tm_scale_bar()
-map2
-

-
-
-

-Disposable income of private households by NUTS 2 regions at 1:10mln resolution using spplot

-
library(sp)
-library(eurostat)
-library(dplyr)
-library(RColorBrewer)
-dat <- get_eurostat("tgs00026", time_format = "raw", stringsAsFactors = FALSE) %>% 
-  # subsetting to year 2014 and NUTS-2 level
-  dplyr::filter(time == 2014, nchar(geo) == 4) %>% 
-  # classifying the values the variable
-  dplyr::mutate(cat = cut_to_classes(values))
-
## Reading cache file /tmp/RtmpEtdcUo/eurostat/tgs00026_raw_code_FF.rds
-
## Table  tgs00026  read from cache file:  /tmp/RtmpEtdcUo/eurostat/tgs00026_raw_code_FF.rds
-
# Download geospatial data from GISCO
-geodata <- get_eurostat_geospatial(output_class = "spdf", resolution = "10", nuts_level = 2, year = 2013)
-
## 
-## COPYRIGHT NOTICE
-## 
-## When data downloaded from this page 
-## <http://ec.europa.eu/eurostat/web/gisco/geodata/reference-data/administrative-units-statistical-units>
-## is used in any printed or electronic publication, 
-## in addition to any other provisions 
-## applicable to the whole Eurostat website, 
-## data source will have to be acknowledged 
-## in the legend of the map and 
-## in the introductory page of the publication 
-## with the following copyright notice:
-## 
-## - EN: (C) EuroGeographics for the administrative boundaries
-## - FR: (C) EuroGeographics pour les limites administratives
-## - DE: (C) EuroGeographics bezuglich der Verwaltungsgrenzen
-## 
-## For publications in languages other than 
-## English, French or German, 
-## the translation of the copyright notice 
-## in the language of the publication shall be used.
-## 
-## If you intend to use the data commercially, 
-## please contact EuroGeographics for 
-## information regarding their licence agreements.
-## 
-
## No encoding supplied: defaulting to UTF-8.
-
## SpatialPolygonDataFrame at resolution 1: 10  cached at:  /tmp/RtmpEtdcUo/eurostat/spdf1022013.RData
-
## 
-## # --------------------------
-## HEADS UP!!
-## 
-## Function now returns the data in 'sf'-class (simple features) 
-## by default which is different 
-## from previous behaviour's 'SpatialPolygonDataFrame'. 
-## 
-## If you prefer either 'SpatialPolygonDataFrame' or 
-## fortified 'data_frame' (for ggplot2::geom_polygon), 
-## please specify it explicitly to 'output_class'-argument!
-## 
-## # --------------------------          
-## 
-
# merge with attribute data with geodata
-geodata@data <- left_join(geodata@data, dat)
-
## Joining, by = "geo"
-
# plot map
-sp::spplot(obj = geodata, "cat", main = "Disposable household income",
-       xlim = c(-22,34), ylim = c(35,70), 
-           col.regions = c("dim grey", brewer.pal(n = 5, name = "Oranges")),
-       col = "white", usePolypath = FALSE)
-

-
-
-

-Disposable income of private households by NUTS 2 regions at 1:60mln resolution using ggplot2

-

Meanwhile the CRAN version of ggplot2 is lacking support for simple features, you can plot maps with ggplot2 by downloading geospatial data as data.frame with output_class argument set as df.

-
library(eurostat)
-library(dplyr)
-library(ggplot2)
-dat <- get_eurostat("tgs00026", time_format = "raw", stringsAsFactors = FALSE) %>% 
-  # subsetting to year 2014 and NUTS-2 level
-  dplyr::filter(time == 2014, nchar(geo) == 4) %>% 
-  # classifying the values the variable
-  dplyr::mutate(cat = cut_to_classes(values))
-
## Reading cache file /tmp/RtmpEtdcUo/eurostat/tgs00026_raw_code_FF.rds
-
## Table  tgs00026  read from cache file:  /tmp/RtmpEtdcUo/eurostat/tgs00026_raw_code_FF.rds
-
# Download geospatial data from GISCO
-geodata <- get_eurostat_geospatial(resolution = "60", nuts_level = "2", year = 2013)
-
## 
-## COPYRIGHT NOTICE
-## 
-## When data downloaded from this page 
-## <http://ec.europa.eu/eurostat/web/gisco/geodata/reference-data/administrative-units-statistical-units>
-## is used in any printed or electronic publication, 
-## in addition to any other provisions 
-## applicable to the whole Eurostat website, 
-## data source will have to be acknowledged 
-## in the legend of the map and 
-## in the introductory page of the publication 
-## with the following copyright notice:
-## 
-## - EN: (C) EuroGeographics for the administrative boundaries
-## - FR: (C) EuroGeographics pour les limites administratives
-## - DE: (C) EuroGeographics bezuglich der Verwaltungsgrenzen
-## 
-## For publications in languages other than 
-## English, French or German, 
-## the translation of the copyright notice 
-## in the language of the publication shall be used.
-## 
-## If you intend to use the data commercially, 
-## please contact EuroGeographics for 
-## information regarding their licence agreements.
-## 
-
## No encoding supplied: defaulting to UTF-8.
-
## 
-## # --------------------------
-## HEADS UP!!
-## 
-## Function now returns the data in 'sf'-class (simple features) 
-## by default which is different 
-## from previous behaviour's 'SpatialPolygonDataFrame'. 
-## 
-## If you prefer either 'SpatialPolygonDataFrame' or 
-## fortified 'data_frame' (for ggplot2::geom_polygon), 
-## please specify it explicitly to 'output_class'-argument!
-## 
-## # --------------------------          
-## 
-
# merge with attribute data with geodata
-map_data <- inner_join(geodata, dat)
-
## Joining, by = "geo"
-
ggplot(data=map_data) + geom_sf(aes(fill=cat),color="dim grey", size=.1) + 
-    scale_fill_brewer(palette = "Oranges") +
-  guides(fill = guide_legend(reverse=T, title = "euro")) +
-  labs(title="Disposable household income in 2014",
-       caption="(C) EuroGeographics for the administrative boundaries 
-                Map produced in R with a help from Eurostat-package <github.com/ropengov/eurostat/>") +
-  theme_light() + theme(legend.position=c(.8,.8)) +
-  coord_sf(xlim=c(-12,44), ylim=c(35,70))
-

-
-
-
-

-SDMX

-

Eurostat data is available also in the SDMX format. The eurostat R package does not provide custom tools for this but the generic rsdmx and rjsdmx R packages can be used to access data in that format when necessary:

-
library(rsdmx)
-
-# Data set URL
-url <- "http://ec.europa.eu/eurostat/SDMX/diss-web/rest/data/cdh_e_fos/..PC.FOS1.BE/?startperiod=2005&endPeriod=2011"
-
-# Read the data from eurostat
-d <- readSDMX(url)
-
-# Convert to data frame and show the first entries
-df <- as.data.frame(d)
-
-kable(head(df))
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
UNITY_GRADFOS07GEOFREQobsTimeobsValueOBS_STATUS
PCTOTALFOS1BEA2009NAna
PCTOTALFOS1BEA2006NAna
PCY_GE1990FOS1BEA200943.75NA
PCY_GE1990FOS1BEA2006NAna
-
-
-
-

-Further examples

-

For further examples, see the package homepage.

-
- -
-

-Version info

-

This tutorial was created with

-
sessionInfo()
-
## R version 3.5.1 (2018-07-02)
-## Platform: x86_64-pc-linux-gnu (64-bit)
-## Running under: Ubuntu 18.04.1 LTS
-## 
-## Matrix products: default
-## BLAS: /home/lei/bin/R-3.5.1/lib/libRblas.so
-## LAPACK: /home/lei/bin/R-3.5.1/lib/libRlapack.so
-## 
-## locale:
-##  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
-##  [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
-##  [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
-##  [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
-##  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
-## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       
-## 
-## attached base packages:
-## [1] stats     graphics  grDevices utils     datasets  methods   base     
-## 
-## other attached packages:
-##  [1] rsdmx_0.5-13       sp_1.3-1           RColorBrewer_1.1-2
-##  [4] tmap_2.1-1         sf_0.6-3           dplyr_0.7.6       
-##  [7] plotrix_3.7-4      ggplot2_3.0.0      tidyr_0.8.1       
-## [10] bindrcpp_0.2.2     rvest_0.3.2        xml2_1.2.0        
-## [13] eurostat_3.2.93    knitr_1.20        
-## 
-## loaded via a namespace (and not attached):
-##  [1] httr_1.3.1         viridisLite_0.3.0  jsonlite_1.5      
-##  [4] shiny_1.1.0        assertthat_0.2.0   stats4_3.5.1      
-##  [7] highr_0.7          yaml_2.2.0         pillar_1.3.0      
-## [10] backports_1.1.2    lattice_0.20-35    glue_1.3.0        
-## [13] digest_0.6.18      promises_1.0.1     colorspace_1.3-2  
-## [16] htmltools_0.3.6    httpuv_1.4.5       plyr_1.8.4        
-## [19] XML_3.98-1.16      pkgconfig_2.0.2    raster_2.6-7      
-## [22] broom_0.5.0        purrr_0.2.5        xtable_1.8-3      
-## [25] webshot_0.5.1      scales_1.0.0       satellite_1.0.1   
-## [28] later_0.7.5        tibble_1.4.2       withr_2.1.2       
-## [31] lazyeval_0.2.1     mapview_2.6.0      magrittr_1.5      
-## [34] crayon_1.3.4       mime_0.6           memoise_1.1.0     
-## [37] evaluate_0.12      fs_1.2.6           nlme_3.1-137      
-## [40] MASS_7.3-50        lwgeom_0.1-4       class_7.3-14      
-## [43] Cairo_1.5-9        tools_3.5.1        hms_0.4.2         
-## [46] stringr_1.3.1      munsell_0.5.0      compiler_3.5.1    
-## [49] pkgdown_1.1.0.9000 e1071_1.7-0        rlang_0.2.2       
-## [52] RCurl_1.95-4.11    classInt_0.2-3     units_0.6-1       
-## [55] grid_3.5.1         tmaptools_2.0-1    dichromat_2.0-0   
-## [58] htmlwidgets_1.3    crosstalk_1.0.0    bitops_1.0-6      
-## [61] base64enc_0.1-3    labeling_0.3       rmarkdown_1.10    
-## [64] gtable_0.2.0       curl_3.2           DBI_1.0.0         
-## [67] roxygen2_6.1.0     R6_2.3.0           lubridate_1.7.4   
-## [70] rgdal_1.3-4        rgeos_0.3-28       bindr_0.1.1       
-## [73] commonmark_1.6     rprojroot_1.3-2    KernSmooth_2.23-15
-## [76] readr_1.1.1        desc_1.2.0         stringi_1.2.4     
-## [79] Rcpp_0.12.19       png_0.1-7          leaflet_2.0.2     
-## [82] spData_0.2.9.4     tidyselect_0.2.5
-
-
- - - -
- - -
- -
-

Site built with pkgdown.

-
- -
-
- - - - - diff --git a/docs/articles/eurostat_tutorial.md b/docs/articles/eurostat_tutorial.md deleted file mode 100755 index 6ddfdebd..00000000 --- a/docs/articles/eurostat_tutorial.md +++ /dev/null @@ -1,1449 +0,0 @@ -R Tools for Eurostat Open Data -============================== - -This [rOpenGov](http://ropengov.github.io) R package provides tools to -access [Eurostat database](http://ec.europa.eu/eurostat/data/database), -which you can also browse on-line for the data sets and documentation. -For contact information and source code, see the [package -website](http://ropengov.github.io/eurostat/). - -Installation -============ - -Release version -[(CRAN)](https://cran.r-project.org/web/packages/eurostat/index.html): - - install.packages("eurostat") - -Development version [(Github)](https://github.com/rOpenGov/eurostat): - - library(devtools) - install_github("ropengov/eurostat") - -Overall, the eurostat package includes the following functions: - -Finding data -============ - -Function `get_eurostat_toc()` downloads a table of contents of eurostat -datasets. The values in column 'code' should be used to download a -selected dataset. - - # Load the package - library(eurostat) - library(rvest) - - # Get Eurostat data listing - toc <- get_eurostat_toc() - - # Check the first items - library(knitr) - kable(head(toc)) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
titlecodetypelast update of datalast table structure changedata startdata endvalues
Database by themesdatafolderNANANANANA
General and regional statisticsgeneralfolderNANANANANA
European and national indicators for short-term analysiseuroindfolderNANANANANA
Business and consumer surveys (source: DG ECFIN)ei_bcsfolderNANANANANA
Consumer surveys (source: DG ECFIN)ei_bcs_csfolderNANANANANA
Consumers - monthly dataei_bsco_mdataset27.03.201827.03.20181980M012018M03NA
- -With `search_eurostat()` you can search the table of contents for -particular patterns, e.g. all datasets related to *passenger transport*. -The kable function to produces nice markdown output. Note that with the -`type` argument of this function you could restrict the search to for -instance datasets or tables. - - # info about passengers - kable(head(search_eurostat("passenger transport"))) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
titlecodetypelast update of datalast table structure changedata startdata endvalues
Volume of passenger transport relative to GDPtran_hv_pstradataset16.08.201714.08.201720002015NA
Modal split of passenger transporttran_hv_psmoddataset17.08.201717.08.201719902015NA
Railway transport - total annual passenger transport (1 000 pass., million pkm)rail_pa_totaldataset27.02.201808.11.201620042015NA
Railway transport - passenger transport by type of transport (detailed reporting only) (1 000 pass.)rail_pa_typepasdataset13.04.201831.08.201720042016NA
Railway transport - passenger transport by type of transport (detailed reporting only) (million pkm)rail_pa_typepkmdataset13.04.201831.08.201720042016NA
International railway passenger transport from the reporting country to the country of disembarkation (1 000 passengers)rail_pa_intgongdataset13.04.201818.07.201720022016NA
- -Codes for the dataset can be searched also from the [Eurostat -database](http://ec.europa.eu/eurostat/data/database). The Eurostat -database gives codes in the Data Navigation Tree after every dataset in -parenthesis. - -Downloading data -================ - -The package supports two of the Eurostats download methods: the bulk -download facility and the Web Services' JSON API. The bulk download -facility is the fastest method to download whole datasets. It is also -often the only way as the JSON API has limitation of maximum 50 -sub-indicators at a time and whole datasets usually exceeds that. To -download only a small section of the dataset the JSON API is faster, as -it allows to make a data selection before downloading. - -A user does not usually have to bother with methods, as both are used -via main function `get_eurostat()`. If only the table id is given, the -whole table is downloaded from the bulk download facility. If also -filters are defined the JSON API is used. - -Here an example of indicator 'Modal split of passenger transport'. This -is the percentage share of each mode of transport in total inland -transport, expressed in passenger-kilometres (pkm) based on transport by -passenger cars, buses and coaches, and trains. All data should be based -on movements on national territory, regardless of the nationality of the -vehicle. However, the data collection is not harmonized at the EU level. - -Pick and print the id of the data set to download: - - # For the original data, see - # http://ec.europa.eu/eurostat/tgm/table.do?tab=table&init=1&plugin=1&language=en&pcode=tsdtr210 - id <- search_eurostat("Modal split of passenger transport", - type = "table")$code[1] - print(id) - -\[1\] "t2020\_rk310" - -Get the whole corresponding table. As the table is annual data, it is -more convient to use a numeric time variable than use the default date -format: - - dat <- get_eurostat(id, time_format = "num") - -Investigate the structure of the downloaded data set: - - str(dat) - - ## Classes 'tbl_df', 'tbl' and 'data.frame': 2431 obs. of 5 variables: - ## $ unit : Factor w/ 1 level "PC": 1 1 1 1 1 1 1 1 1 1 ... - ## $ vehicle: Factor w/ 3 levels "BUS_TOT","CAR",..: 1 1 1 1 1 1 1 1 1 1 ... - ## $ geo : Factor w/ 35 levels "AT","BE","CH",..: 1 2 3 4 5 6 7 8 9 10 ... - ## $ time : num 1990 1990 1990 1990 1990 1990 1990 1990 1990 1990 ... - ## $ values : num 11 10.6 3.7 9.1 11.3 32.4 14.9 13.5 6 24.8 ... - - kable(head(dat)) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
unitvehiclegeotimevalues
PCBUS_TOTAT199011.0
PCBUS_TOTBE199010.6
PCBUS_TOTCH19903.7
PCBUS_TOTDE19909.1
PCBUS_TOTDK199011.3
PCBUS_TOTEL199032.4
- -Or you can get only a part of the dataset by defining `filters` -argument. It should be named list, where names corresponds to variable -names (lower case) and values are vectors of codes corresponding -desidered series (upper case). For time variable, in addition to a -`time`, also a `sinceTimePeriod` and a `lastTimePeriod` can be used. - - dat2 <- get_eurostat(id, filters = list(geo = c("EU28", "FI"), lastTimePeriod=1), time_format = "num") - kable(dat2) - -Replacing codes with labels ---------------------------- - -By default variables are returned as Eurostat codes, but to get -human-readable labels instead, use a `type = "label"` argument. - - datl2 <- get_eurostat(id, filters = list(geo = c("EU28", "FI"), - lastTimePeriod = 1), - type = "label", time_format = "num") - kable(head(datl2)) - -Eurostat codes in the downloaded data set can be replaced with -human-readable labels from the Eurostat dictionaries with the -`label_eurostat()` function. - - datl <- label_eurostat(dat) - kable(head(datl)) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
unitvehiclegeotimevalues
PercentageMotor coaches, buses and trolley busesAustria199011.0
PercentageMotor coaches, buses and trolley busesBelgium199010.6
PercentageMotor coaches, buses and trolley busesSwitzerland19903.7
PercentageMotor coaches, buses and trolley busesGermany (until 1990 former territory of the FRG)19909.1
PercentageMotor coaches, buses and trolley busesDenmark199011.3
PercentageMotor coaches, buses and trolley busesGreece199032.4
- -The `label_eurostat()` allows conversion of individual variable vectors -or variable names as well. - - label_eurostat_vars(names(datl)) - -Vehicle information has 3 levels. You can check them now with: - - levels(datl$vehicle) - -Selecting and modifying data -============================ - -EFTA, Eurozone, EU and EU candidate countries ---------------------------------------------- - -To facilitate smooth visualization of standard European geographic -areas, the package provides ready-made lists of the country codes used -in the eurostat database for EFTA (efta\_countries), Euro area -(ea\_countries), EU (eu\_countries) and EU candidate countries -(eu\_candidate\_countries). These can be used to select specific groups -of countries for closer investigation. For conversions with other -standard country coding systems, see the [countrycode](...) R package. -To retrieve the country code list for EFTA, for instance, use: - - data(efta_countries) - kable(efta_countries) - - - - - - - - - - - - - - - - - - - - - - - - - - -
codename
ISIceland
LILiechtenstein
NONorway
CHSwitzerland
- -EU data from 2012 in all vehicles: ----------------------------------- - - dat_eu12 <- subset(datl, geo == "European Union (current composition)" & time == 2012) - kable(dat_eu12, row.names = FALSE) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
unitvehiclegeotimevalues
PercentageMotor coaches, buses and trolley busesEuropean Union (current composition)20129.5
PercentagePassenger carsEuropean Union (current composition)201282.8
PercentageTrainsEuropean Union (current composition)20127.7
- -EU data from 2000 - 2012 with vehicle types as variables: ---------------------------------------------------------- - -Reshaping the data is best done with `spread()` in `tidyr`. - - library("tidyr") - dat_eu_0012 <- subset(dat, geo == "EU28" & time %in% 2000:2012) - dat_eu_0012_wide <- spread(dat_eu_0012, vehicle, values) - kable(subset(dat_eu_0012_wide, select = -geo), row.names = FALSE) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
unittimeBUS_TOTCARTRN
PC200010.482.47.2
PC200110.282.77.1
PC20029.983.36.8
PC20039.983.56.7
PC20049.883.46.8
PC20059.883.36.9
PC20069.783.27.1
PC20079.883.17.1
PC20089.982.87.4
PC20099.383.67.1
PC20109.483.57.2
PC20119.483.27.3
PC20129.582.87.7
- -Train passengers for selected EU countries in 2000 - 2012 ---------------------------------------------------------- - - dat_trains <- subset(datl, geo %in% c("Austria", "Belgium", "Finland", "Sweden") - & time %in% 2000:2012 - & vehicle == "Trains") - - dat_trains_wide <- spread(dat_trains, geo, values) - kable(subset(dat_trains_wide, select = -vehicle), row.names = FALSE) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
unittimeAustriaBelgiumFinlandSweden
Percentage20009.76.35.16.8
Percentage20019.76.44.87.1
Percentage20029.76.54.87.1
Percentage20039.56.54.77.0
Percentage20049.47.14.76.8
Percentage20059.86.64.87.1
Percentage200610.06.94.87.6
Percentage200710.07.15.07.9
Percentage200811.17.55.48.6
Percentage200911.17.55.18.7
Percentage201011.07.75.28.7
Percentage201111.37.75.08.7
Percentage201211.87.85.39.1
- -Visualization -============= - -Visualizing train passenger data with `ggplot2`: - - library(ggplot2) - - ## Want to understand how all the pieces fit together? See the R for - ## Data Science book: http://r4ds.had.co.nz/ - - p <- ggplot(dat_trains, aes(x = time, y = values, colour = geo)) - p <- p + geom_line() - print(p) - -![](fig/trains_plot-1.png) - -**Triangle plot** - -Triangle plot is handy for visualizing data sets with three variables. - - library(tidyr) - library(plotrix) - library(eurostat) - library(dplyr) - library(tidyr) - - # All sources of renewable energy are to be grouped into three sets - dict <- c("Solid biofuels (excluding charcoal)" = "Biofuels", - "Biogasoline" = "Biofuels", - "Other liquid biofuels" = "Biofuels", - "Biodiesels" = "Biofuels", - "Biogas" = "Biofuels", - "Hydro power" = "Hydro power", - "Tide, Wave and Ocean" = "Hydro power", - "Solar thermal" = "Wind, solar, waste and Other", - "Geothermal Energy" = "Wind, solar, waste and Other", - "Solar photovoltaic" = "Wind, solar, waste and Other", - "Municipal waste (renewable)" = "Wind, solar, waste and Other", - "Wind power" = "Wind, solar, waste and Other", - "Bio jet kerosene" = "Wind, solar, waste and Other") - # Some cleaning of the data is required - energy3 <- get_eurostat("ten00081") %>% - label_eurostat(dat) %>% - filter(time == "2013-01-01", - product != "Renewable energies") %>% - mutate(nproduct = dict[as.character(product)], # just three categories - geo = gsub(geo, pattern=" \\(.*", replacement="")) %>% - select(nproduct, geo, values) %>% - group_by(nproduct, geo) %>% - summarise(svalue = sum(values)) %>% - group_by(geo) %>% - mutate(tvalue = sum(svalue), - svalue = svalue/sum(svalue)) %>% - filter(tvalue > 1000) %>% # only large countries - spread(nproduct, svalue) - - # Triangle plot - par(cex=0.75, mar=c(0,0,0,0)) - positions <- plotrix::triax.plot(as.matrix(energy3[, c(3,5,4)]), - show.grid = TRUE, - label.points= FALSE, point.labels = energy3$geo, - col.axis="gray50", col.grid="gray90", - pch = 19, cex.axis=0.8, cex.ticks=0.7, col="grey50") - - # Larger labels - ind <- which(energy3$geo %in% c("Norway", "Iceland","Denmark","Estonia", "Turkey", "Italy", "Finland")) - df <- data.frame(positions$xypos, geo = energy3$geo) - points(df$x[ind], df$y[ind], cex=2, col="red", pch=19) - text(df$x[ind], df$y[ind], df$geo[ind], adj = c(0.5,-1), cex=1.5) - -![](fig/plotGallery-1.png) - -Maps ----- - -### Disposable income of private households by NUTS 2 regions at 1:60mln resolution using tmap - -The mapping examples below use -[`tmap`](https://github.com/mtennekes/tmap) package. - - library(dplyr) - library(eurostat) - library(sf) - - ## Linking to GEOS 3.5.1, GDAL 2.2.1, proj.4 4.9.3 - - library(tmap) - - # Download attribute data from Eurostat - sp_data <- eurostat::get_eurostat("tgs00026", time_format = "raw", stringsAsFactors = FALSE) %>% - # subset to have only a single row per geo - dplyr::filter(time == 2010, nchar(geo) == 4) %>% - # categorise - dplyr::mutate(income = cut_to_classes(values, n = 5)) - - ## Table tgs00026 cached at /tmp/RtmpCypIG8/eurostat/tgs00026_raw_code_FF.rds - - # Download geospatial data from CISGO - geodata <- get_eurostat_geospatial(output_class = "sf", resolution = "60") - - ## - ## COPYRIGHT NOTICE - ## - ## When data downloaded from this page - ## - ## is used in any printed or electronic publication, - ## in addition to any other provisions - ## applicable to the whole Eurostat website, - ## data source will have to be acknowledged - ## in the legend of the map and - ## in the introductory page of the publication - ## with the following copyright notice: - ## - ## - EN: (C) EuroGeographics for the administrative boundaries - ## - FR: (C) EuroGeographics pour les limites administratives - ## - DE: (C) EuroGeographics bezuglich der Verwaltungsgrenzen - ## - ## For publications in languages other than - ## English, French or German, - ## the translation of the copyright notice - ## in the language of the publication shall be used. - ## - ## If you intend to use the data commercially, - ## please contact EuroGeographics for - ## information regarding their licence agreements. - ## - - ## sf at resolution 1:60 read from local file - - ## - ## # -------------------------- - ## HEADS UP!! - ## - ## Function now returns the data in 'sf'-class (simple features) - ## by default which is different - ## from previous behaviour's 'SpatialPolygonDataFrame'. - ## - ## If you prefer either 'SpatialPolygonDataFrame' or - ## fortified 'data_frame' (for ggplot2::geom_polygon), - ## please specify it explicitly to 'output_class'-argument! - ## - ## # -------------------------- - ## - - # merge with attribute data with geodata - map_data <- inner_join(geodata, sp_data) - - ## Joining, by = "geo" - - # plot map using tmap - data(Europe) - -Construct the map - - map1 <- tmap::tm_shape(Europe) + - tmap::tm_fill("lightgrey") + - tmap::tm_shape(map_data) + - tmap::tm_grid() + - tmap::tm_polygons("income", title = "Disposable household\nincomes in 2010", - palette = "Oranges") + - tmap::tm_format_Europe() - print(map1) - -![](fig/map1ex-1.png) - -Interactive maps can be generated as well - - # Interactive - tmap_mode("view") - map1 - - # Set the mode back to normal plotting - tmap_mode("plot") - print(map1) - -### Disposable income of private households by NUTS 2 regions in Poland with labels at 1:1mln resolution using tmap - - library(eurostat) - library(dplyr) - library(sf) - library(RColorBrewer) - - # Downloading and manipulating the tabular data - euro_sf2 <- eurostat::get_eurostat("tgs00026", time_format = "raw", stringsAsFactors = FALSE) %>% - # subsetting to year 2014 and NUTS-3 level - dplyr::filter(time == 2014, grepl("PL",geo)) %>% - # label the single geo column - mutate(label = paste0(label_eurostat(.)[["geo"]], "\n", values, "€"), - income = cut_to_classes(values)) - - ## Reading cache file /tmp/RtmpCypIG8/eurostat/tgs00026_raw_code_FF.rds - - ## Table tgs00026 read from cache file: /tmp/RtmpCypIG8/eurostat/tgs00026_raw_code_FF.rds - - # Download geospatial data from CISGO - geodata <- get_eurostat_geospatial(output_class = "sf", resolution = "60") - - ## - ## COPYRIGHT NOTICE - ## - ## When data downloaded from this page - ## - ## is used in any printed or electronic publication, - ## in addition to any other provisions - ## applicable to the whole Eurostat website, - ## data source will have to be acknowledged - ## in the legend of the map and - ## in the introductory page of the publication - ## with the following copyright notice: - ## - ## - EN: (C) EuroGeographics for the administrative boundaries - ## - FR: (C) EuroGeographics pour les limites administratives - ## - DE: (C) EuroGeographics bezuglich der Verwaltungsgrenzen - ## - ## For publications in languages other than - ## English, French or German, - ## the translation of the copyright notice - ## in the language of the publication shall be used. - ## - ## If you intend to use the data commercially, - ## please contact EuroGeographics for - ## information regarding their licence agreements. - ## - - ## sf at resolution 1:60 read from local file - - ## - ## # -------------------------- - ## HEADS UP!! - ## - ## Function now returns the data in 'sf'-class (simple features) - ## by default which is different - ## from previous behaviour's 'SpatialPolygonDataFrame'. - ## - ## If you prefer either 'SpatialPolygonDataFrame' or - ## fortified 'data_frame' (for ggplot2::geom_polygon), - ## please specify it explicitly to 'output_class'-argument! - ## - ## # -------------------------- - ## - - # merge with attribute data with geodata - map_data <- inner_join(geodata, euro_sf2) - - ## Joining, by = "geo" - - # plot map - map2 <- tm_shape(Europe) + - tm_fill("lightgrey") + - tm_shape(map_data, is.master = TRUE) + - tm_polygons("income", title = "Disposable household incomes in 2014", - palette = "Oranges", border.col = "white") + - tm_text("NUTS_NAME", just = "center") + - tm_scale_bar() + - tm_format_Europe(legend.outside = TRUE, attr.outside = TRUE) - map2 - -![](fig/maps2-1.png) - -### Disposable income of private households by NUTS 2 regions at 1:10mln resolution using spplot - - library(sp) - library(eurostat) - library(dplyr) - library(RColorBrewer) - dat <- get_eurostat("tgs00026", time_format = "raw", stringsAsFactors = FALSE) %>% - # subsetting to year 2014 and NUTS-3 level - dplyr::filter(time == 2014, nchar(geo) == 4) %>% - # classifying the values the variable - dplyr::mutate(cat = cut_to_classes(values)) - - ## Reading cache file /tmp/RtmpCypIG8/eurostat/tgs00026_raw_code_FF.rds - - ## Table tgs00026 read from cache file: /tmp/RtmpCypIG8/eurostat/tgs00026_raw_code_FF.rds - - # Download geospatial data from CISGO - geodata <- get_eurostat_geospatial(output_class = "spdf", resolution = "10", nuts_level = 2) - - ## - ## COPYRIGHT NOTICE - ## - ## When data downloaded from this page - ## - ## is used in any printed or electronic publication, - ## in addition to any other provisions - ## applicable to the whole Eurostat website, - ## data source will have to be acknowledged - ## in the legend of the map and - ## in the introductory page of the publication - ## with the following copyright notice: - ## - ## - EN: (C) EuroGeographics for the administrative boundaries - ## - FR: (C) EuroGeographics pour les limites administratives - ## - DE: (C) EuroGeographics bezuglich der Verwaltungsgrenzen - ## - ## For publications in languages other than - ## English, French or German, - ## the translation of the copyright notice - ## in the language of the publication shall be used. - ## - ## If you intend to use the data commercially, - ## please contact EuroGeographics for - ## information regarding their licence agreements. - ## - - ## No encoding supplied: defaulting to UTF-8. - - ## SpatialPolygonDataFrame at resolution 1: 10 cached at: /tmp/RtmpCypIG8/eurostat/spdf102.RData - - ## - ## # -------------------------- - ## HEADS UP!! - ## - ## Function now returns the data in 'sf'-class (simple features) - ## by default which is different - ## from previous behaviour's 'SpatialPolygonDataFrame'. - ## - ## If you prefer either 'SpatialPolygonDataFrame' or - ## fortified 'data_frame' (for ggplot2::geom_polygon), - ## please specify it explicitly to 'output_class'-argument! - ## - ## # -------------------------- - ## - - # merge with attribute data with geodata - geodata@data <- left_join(geodata@data, dat) - - ## Joining, by = "geo" - - # plot map - sp::spplot(obj = geodata, "cat", main = "Disposable household income", - xlim = c(-22,34), ylim = c(35,70), - col.regions = c("dim grey", brewer.pal(n = 5, name = "Oranges")), - col = "white", usePolypath = FALSE) - -![](fig/maps3-1.png) - -### Disposable income of private households by NUTS 2 regions at 1:60mln resolution using ggplot2 - -Meanwhile the CRAN version of `ggplot2` is lacking support for simple -features, you can plot maps with `ggplot2` by downloading geospatial -data as `data.frame` with `output_class` argument set as `df`. - - library(eurostat) - library(dplyr) - library(ggplot2) - dat <- get_eurostat("tgs00026", time_format = "raw", stringsAsFactors = FALSE) %>% - # subsetting to year 2014 and NUTS-2 level - dplyr::filter(time == 2014, nchar(geo) == 4) %>% - # classifying the values the variable - dplyr::mutate(cat = cut_to_classes(values)) - - ## Reading cache file /tmp/RtmpCypIG8/eurostat/tgs00026_raw_code_FF.rds - - ## Table tgs00026 read from cache file: /tmp/RtmpCypIG8/eurostat/tgs00026_raw_code_FF.rds - - # Download geospatial data from CISGO - geodata <- get_eurostat_geospatial(output_class = "df", resolution = "60", nuts_level = "2") - - ## - ## COPYRIGHT NOTICE - ## - ## When data downloaded from this page - ## - ## is used in any printed or electronic publication, - ## in addition to any other provisions - ## applicable to the whole Eurostat website, - ## data source will have to be acknowledged - ## in the legend of the map and - ## in the introductory page of the publication - ## with the following copyright notice: - ## - ## - EN: (C) EuroGeographics for the administrative boundaries - ## - FR: (C) EuroGeographics pour les limites administratives - ## - DE: (C) EuroGeographics bezuglich der Verwaltungsgrenzen - ## - ## For publications in languages other than - ## English, French or German, - ## the translation of the copyright notice - ## in the language of the publication shall be used. - ## - ## If you intend to use the data commercially, - ## please contact EuroGeographics for - ## information regarding their licence agreements. - ## - - ## Regions defined for each Polygons - - ## Joining, by = "id" - - ## data_frame at resolution 1:60 read from local file - - ## - ## # -------------------------- - ## HEADS UP!! - ## - ## Function now returns the data in 'sf'-class (simple features) - ## by default which is different - ## from previous behaviour's 'SpatialPolygonDataFrame'. - ## - ## If you prefer either 'SpatialPolygonDataFrame' or - ## fortified 'data_frame' (for ggplot2::geom_polygon), - ## please specify it explicitly to 'output_class'-argument! - ## - ## # -------------------------- - ## - - # merge with attribute data with geodata - map_data <- inner_join(geodata, dat) - - ## Joining, by = "geo" - - # plot map - ggplot(data=map_data, aes(x=long,y=lat,group=group)) + - geom_polygon(aes(fill=cat),color="dim grey", size=.1) + - scale_fill_brewer(palette = "Oranges") + - # scale_fill_continuous(trans = 'reverse', ) + - guides(fill = guide_legend(reverse=T, title = "€")) + - labs(title="Disposable household income in 2014", - caption="(C) EuroGeographics for the administrative boundaries - Map produced in R with a help from Eurostat-package ") + - theme_light() + theme(legend.position=c(.8,.8)) + - coord_map(project="orthographic", xlim=c(-12,44), ylim=c(35,70)) - - ## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font - ## metrics unknown for Unicode character U+20ac - - ## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): font - ## metrics unknown for Unicode character U+20ac - - ## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): conversion - ## failure on '€' in 'mbcsToSbcs': dot substituted for - - ## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): conversion - ## failure on '€' in 'mbcsToSbcs': dot substituted for <82> - - ## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): conversion - ## failure on '€' in 'mbcsToSbcs': dot substituted for - - ## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : - ## conversion failure on '€' in 'mbcsToSbcs': dot substituted for - - ## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : - ## conversion failure on '€' in 'mbcsToSbcs': dot substituted for <82> - - ## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : - ## conversion failure on '€' in 'mbcsToSbcs': dot substituted for - - ## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : - ## conversion failure on '€' in 'mbcsToSbcs': dot substituted for - - ## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : - ## conversion failure on '€' in 'mbcsToSbcs': dot substituted for <82> - - ## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : - ## conversion failure on '€' in 'mbcsToSbcs': dot substituted for - - ## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : - ## conversion failure on '€' in 'mbcsToSbcs': dot substituted for - - ## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : - ## conversion failure on '€' in 'mbcsToSbcs': dot substituted for <82> - - ## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : - ## conversion failure on '€' in 'mbcsToSbcs': dot substituted for - - ## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : - ## conversion failure on '€' in 'mbcsToSbcs': dot substituted for - - ## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : - ## conversion failure on '€' in 'mbcsToSbcs': dot substituted for <82> - - ## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, : - ## conversion failure on '€' in 'mbcsToSbcs': dot substituted for - - ## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x - ## $y, : conversion failure on '€' in 'mbcsToSbcs': dot substituted for - - ## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x - ## $y, : conversion failure on '€' in 'mbcsToSbcs': dot substituted for <82> - - ## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x - ## $y, : conversion failure on '€' in 'mbcsToSbcs': dot substituted for - -![](fig/maps4-1.png) - -SDMX ----- - -Eurostat data is available also in the SDMX format. The eurostat R -package does not provide custom tools for this but the generic rsdmx R -package can be used to access data in that format when necessary: - - library(rsdmx) - - # Data set URL - url <- "http://ec.europa.eu/eurostat/SDMX/diss-web/rest/data/cdh_e_fos/..PC.FOS1.BE/?startperiod=2005&endPeriod=2011" - - # Read the data from eurostat - d <- readSDMX(url) - - # Convert to data frame and show the first entries - df <- as.data.frame(d) - - kable(head(df)) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
UNITY_GRADFOS07GEOFREQobsTimeobsValueOBS_STATUS
PCTOTALFOS1BEA2009NAna
PCTOTALFOS1BEA2006NAna
PCY_GE1990FOS1BEA200943.75NA
PCY_GE1990FOS1BEA2006NAna
- -Further examples -================ - -For further examples, see the [package -homepage](http://ropengov.github.io/eurostat/articles/index.html). - -Citations and related work -========================== - -### Citing the data sources - -Eurostat data: cite [Eurostat](http://ec.europa.eu/eurostat/). - -Administrative boundaries: cite EuroGeographics - -### Citing the eurostat R package - -For main developers and contributors, see the [package -homepage](http://ropengov.github.io/eurostat). - -This work can be freely used, modified and distributed under the -BSD-2-clause (modified FreeBSD) license: - - citation("eurostat") - - ## - ## Kindly cite the eurostat R package as follows: - ## - ## (C) Leo Lahti, Janne Huovari, Markus Kainu, Przemyslaw Biecek. - ## Retrieval and analysis of Eurostat open data with the eurostat - ## package. R Journal 9(1):385-392, 2017. Version 3.1.6003 Package - ## URL: http://ropengov.github.io/eurostat Manuscript URL: - ## https://journal.r-project.org/archive/2017/RJ-2017-019/index.html - ## - ## A BibTeX entry for LaTeX users is - ## - ## @Misc{, - ## title = {eurostat R package}, - ## author = {Leo Lahti and Janne Huovari and Markus Kainu and Przemyslaw Biecek}, - ## journal = {R Journal}, - ## volume = {9}, - ## number = {1}, - ## pages = {385-392}, - ## year = {2017}, - ## url = {https://journal.r-project.org/archive/2017/RJ-2017-019/index.html}, - ## note = {Version 3.1.6003}, - ## } - -### Related work - -This [rOpenGov](http://ropengov.github.io) R package is based on the -earlier CRAN packages -[statfi](https://cran.r-project.org/package=statfi) and -[smarterpoland](https://cran.r-project.org/package=SmarterPoland). - -The independent [reurostat](https://github.com/Tungurahua/reurostat) -package develops related Eurostat tools but seems to be in an -experimental stage at the time of writing this tutorial. - -The more generic [quandl](https://cran.r-project.org/package=quandl), -[datamart](https://cran.r-project.org/package=datamart), -[rsdmx](https://cran.r-project.org/package=rsdmx), and -[pdfetch](https://cran.r-project.org/package=pdfetch) packages may -provide access to some versions of eurostat data but these packages are -more generic and hence, in contrast to the eurostat R package, lack -tools that are specifically customized to facilitate eurostat analysis. - -### Contact - -For contact information, see the [package -homepage](http://ropengov.github.io/eurostat). - -Version info -============ - -This tutorial was created with - - sessionInfo() - - ## R version 3.4.3 (2017-11-30) - ## Platform: x86_64-pc-linux-gnu (64-bit) - ## Running under: Ubuntu 17.10 - ## - ## Matrix products: default - ## BLAS: /home/lei/bin/R-3.4.3/lib/libRblas.so - ## LAPACK: /home/lei/bin/R-3.4.3/lib/libRlapack.so - ## - ## locale: - ## [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C - ## [3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8 - ## [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 - ## [7] LC_PAPER=en_US.UTF-8 LC_NAME=C - ## [9] LC_ADDRESS=C LC_TELEPHONE=C - ## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C - ## - ## attached base packages: - ## [1] stats graphics grDevices utils datasets methods base - ## - ## other attached packages: - ## [1] rsdmx_0.5-10 sp_1.2-7 RColorBrewer_1.1-2 - ## [4] tmap_1.11-1 sf_0.6-1 dplyr_0.7.4 - ## [7] plotrix_3.7 ggplot2_2.2.1.9000 tidyr_0.8.0 - ## [10] bindrcpp_0.2 rvest_0.3.2 xml2_1.2.0 - ## [13] rmarkdown_1.8 eurostat_3.1.6003 testthat_2.0.0 - ## [16] pkgdown_0.1.0.9000 knitr_1.19 devtools_1.13.4 - ## - ## loaded via a namespace (and not attached): - ## [1] colorspace_1.3-2 deldir_0.1-14 gdalUtils_2.0.1.7 - ## [4] class_7.3-14 leaflet_1.1.0 rgdal_1.2-16 - ## [7] rprojroot_1.3-2 satellite_1.0.1 base64enc_0.1-3 - ## [10] dichromat_2.0-0 roxygen2_6.0.1 R.methodsS3_1.7.1 - ## [13] codetools_0.2-15 splines_3.4.3 mnormt_1.5-5 - ## [16] pkgload_0.0.0.9000 geojsonlint_0.2.0 jsonlite_1.5 - ## [19] Cairo_1.5-9 tmaptools_1.2-3 rematch_1.0.1 - ## [22] broom_0.4.4 png_0.1-7 R.oo_1.21.0 - ## [25] rgeos_0.3-26 shiny_1.0.5 mapproj_1.2-5 - ## [28] readr_1.1.1 compiler_3.4.3 httr_1.3.1 - ## [31] mapview_2.3.0 backports_1.1.2 assertthat_0.2.0 - ## [34] Matrix_1.2-12 lazyeval_0.2.1 htmltools_0.3.6 - ## [37] tools_3.4.3 coda_0.19-1 gtable_0.2.0 - ## [40] glue_1.2.0 reshape2_1.4.3 maps_3.2.0 - ## [43] gmodels_2.16.2 V8_1.5 Rcpp_0.12.16 - ## [46] highlight_0.4.7.2 raster_2.6-7 spdep_0.7-4 - ## [49] gdata_2.18.0 debugme_1.1.0 nlme_3.1-131 - ## [52] udunits2_0.13 iterators_1.0.9 crosstalk_1.0.0 - ## [55] psych_1.8.3.3 stringr_1.3.0 mime_0.5 - ## [58] gtools_3.5.0 XML_3.98-1.9 LearnBayes_2.15 - ## [61] MASS_7.3-48 scales_0.5.0.9000 BiocInstaller_1.28.0 - ## [64] hms_0.4.1 parallel_3.4.3 expm_0.999-2 - ## [67] yaml_2.1.16 curl_3.2 memoise_1.1.0 - ## [70] geosphere_1.5-7 stringi_1.1.7 jsonvalidate_1.0.0 - ## [73] highr_0.6 desc_1.1.1 foreach_1.4.4 - ## [76] e1071_1.6-8 boot_1.3-20 pkgbuild_0.0.0.9000 - ## [79] spData_0.2.8.3 rlang_0.1.6.9003 pkgconfig_2.0.1 - ## [82] commonmark_1.4 bitops_1.0-6 evaluate_0.10.1 - ## [85] lattice_0.20-35 purrr_0.2.4 bindr_0.1 - ## [88] htmlwidgets_1.0 labeling_0.3 tidyselect_0.2.3 - ## [91] osmar_1.1-7 plyr_1.8.4 magrittr_1.5 - ## [94] R6_2.2.2 DBI_0.8 pillar_1.1.0 - ## [97] whisker_0.4 foreign_0.8-69 withr_2.1.1.9000 - ## [100] units_0.5-1 RCurl_1.95-4.10 tibble_1.4.2 - ## [103] crayon_1.3.4 rmapshaper_0.3.0 KernSmooth_2.23-15 - ## [106] grid_3.4.3 callr_2.0.1 webshot_0.5.0.9000 - ## [109] digest_0.6.15 classInt_0.2-3 xtable_1.8-2 - ## [112] httpuv_1.3.5 R.utils_2.6.0 stats4_3.4.3 - ## [115] munsell_0.4.3 viridisLite_0.3.0 diff --git a/docs/articles/eurostat_tutorial.pdf b/docs/articles/eurostat_tutorial.pdf deleted file mode 100755 index a2a7bd93..00000000 Binary files a/docs/articles/eurostat_tutorial.pdf and /dev/null differ diff --git a/docs/articles/index.html b/docs/articles/index.html deleted file mode 100755 index 23cf4b8e..00000000 --- a/docs/articles/index.html +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - -Articles • eurostat - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - -
- - - -
- - -
-

Site built with pkgdown.

-
- -
-
- - - - - - diff --git a/docs/articles/main.R b/docs/articles/main.R deleted file mode 100755 index 17973e1d..00000000 --- a/docs/articles/main.R +++ /dev/null @@ -1,13 +0,0 @@ -library(knitr) -library(rmarkdown) -render("eurostat_tutorial.Rmd", output_format = "md_document") -render("eurostat_tutorial.Rmd", output_format = "pdf_document") -render("eurostat_tutorial.Rmd", output_format = "html_document") - -#knit("eurostat_tutorial.Rmd") -#knit("manuscript.Rmd") -#render("manuscript.Rmd", output_format = "html_document") -#render("manuscript.Rmd", output_format = "pdf_document") -#knit2pdf("eurostat.Rnw") -#library(rmarkdown) -#render("eurostat_tutorial.Rmd", output_format = "pdf_document") diff --git a/docs/articles/publications.html b/docs/articles/publications.html deleted file mode 100755 index 6b685a33..00000000 --- a/docs/articles/publications.html +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - - -Publications using the eurostat R package • eurostat - - - - - - - - - -
-
- - - -
-
- - - - -

You can send us a note via the issue tracker if you like to add a publication using the eurostat R package on this list:

-
    -
  • Retrieval and analysis of Eurostat open data with the eurostat package. R Journal 2017. (manuscript; source code).
  • -
-

External publications using the eurostat package:

-
    -
  • Kenett RDS, Shmueli G. Information Quality: The Potential of Data and Analytics to Generate Knowledge. John Wiley & Sons, 2016.
  • -
-
- - - -
- - -
- -
-

Site built with pkgdown.

-
- -
-
- - - - - diff --git a/docs/authors.html b/docs/authors.html deleted file mode 100755 index 12a6dc96..00000000 --- a/docs/authors.html +++ /dev/null @@ -1,194 +0,0 @@ - - - - - - - - -Citation and Authors • eurostat - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - -
- -
-
- - -

Lahti L, Huovari J, Kainu M, Biecek P (2017). -“eurostat R package.” -Version 3.2.93, https://journal.r-project.org/archive/2017/RJ-2017-019/index.html. -

-
@Misc{,
-  title = {eurostat R package},
-  author = {Leo Lahti and Janne Huovari and Markus Kainu and Przemyslaw Biecek},
-  journal = {R Journal},
-  volume = {9},
-  number = {1},
-  pages = {385-392},
-  year = {2017},
-  url = {https://journal.r-project.org/archive/2017/RJ-2017-019/index.html},
-  note = {Version 3.2.93},
-}
- - - -
    -
  • -

    Leo Lahti. Author, maintainer. -

    -
  • -
  • -

    Janne Huovari. Author. -

    -
  • -
  • -

    Markus Kainu. Author. -

    -
  • -
  • -

    Przemyslaw Biecek. Author. -

    -
  • -
  • -

    Joona Lehtomaki. Contributor. -

    -
  • -
  • -

    Francois Briatte. Contributor. -

    -
  • -
  • -

    Oliver Reiter. Contributor. -

    -
  • -
- -
- -
- - -
- - -
-

Site built with pkgdown.

-
- -
-
- - - - - - diff --git a/docs/docsearch.css b/docs/docsearch.css deleted file mode 100755 index e5f1fe1d..00000000 --- a/docs/docsearch.css +++ /dev/null @@ -1,148 +0,0 @@ -/* Docsearch -------------------------------------------------------------- */ -/* - Source: https://github.com/algolia/docsearch/ - License: MIT -*/ - -.algolia-autocomplete { - display: block; - -webkit-box-flex: 1; - -ms-flex: 1; - flex: 1 -} - -.algolia-autocomplete .ds-dropdown-menu { - width: 100%; - min-width: none; - max-width: none; - padding: .75rem 0; - background-color: #fff; - background-clip: padding-box; - border: 1px solid rgba(0, 0, 0, .1); - box-shadow: 0 .5rem 1rem rgba(0, 0, 0, .175); -} - -@media (min-width:768px) { - .algolia-autocomplete .ds-dropdown-menu { - width: 175% - } -} - -.algolia-autocomplete .ds-dropdown-menu::before { - display: none -} - -.algolia-autocomplete .ds-dropdown-menu [class^=ds-dataset-] { - padding: 0; - background-color: rgb(255,255,255); - border: 0; - max-height: 80vh; -} - -.algolia-autocomplete .ds-dropdown-menu .ds-suggestions { - margin-top: 0 -} - -.algolia-autocomplete .algolia-docsearch-suggestion { - padding: 0; - overflow: visible -} - -.algolia-autocomplete .algolia-docsearch-suggestion--category-header { - padding: .125rem 1rem; - margin-top: 0; - font-size: 1.3em; - font-weight: 500; - color: #00008B; - border-bottom: 0 -} - -.algolia-autocomplete .algolia-docsearch-suggestion--wrapper { - float: none; - padding-top: 0 -} - -.algolia-autocomplete .algolia-docsearch-suggestion--subcategory-column { - float: none; - width: auto; - padding: 0; - text-align: left -} - -.algolia-autocomplete .algolia-docsearch-suggestion--content { - float: none; - width: auto; - padding: 0 -} - -.algolia-autocomplete .algolia-docsearch-suggestion--content::before { - display: none -} - -.algolia-autocomplete .ds-suggestion:not(:first-child) .algolia-docsearch-suggestion--category-header { - padding-top: .75rem; - margin-top: .75rem; - border-top: 1px solid rgba(0, 0, 0, .1) -} - -.algolia-autocomplete .ds-suggestion .algolia-docsearch-suggestion--subcategory-column { - display: block; - padding: .1rem 1rem; - margin-bottom: 0.1; - font-size: 1.0em; - font-weight: 400 - /* display: none */ -} - -.algolia-autocomplete .algolia-docsearch-suggestion--title { - display: block; - padding: .25rem 1rem; - margin-bottom: 0; - font-size: 0.9em; - font-weight: 400 -} - -.algolia-autocomplete .algolia-docsearch-suggestion--text { - padding: 0 1rem .5rem; - margin-top: -.25rem; - font-size: 0.8em; - font-weight: 400; - line-height: 1.25 -} - -.algolia-autocomplete .algolia-docsearch-footer { - width: 110px; - height: 20px; - z-index: 3; - margin-top: 10.66667px; - float: right; - font-size: 0; - line-height: 0; -} - -.algolia-autocomplete .algolia-docsearch-footer--logo { - background-image: url("data:image/svg+xml;utf8,"); - background-repeat: no-repeat; - background-position: 50%; - background-size: 100%; - overflow: hidden; - text-indent: -9000px; - width: 100%; - height: 100%; - display: block; - transform: translate(-8px); -} - -.algolia-autocomplete .algolia-docsearch-suggestion--highlight { - color: #FF8C00; - background: rgba(232, 189, 54, 0.1) -} - - -.algolia-autocomplete .algolia-docsearch-suggestion--text .algolia-docsearch-suggestion--highlight { - box-shadow: inset 0 -2px 0 0 rgba(105, 105, 105, .5) -} - -.algolia-autocomplete .ds-suggestion.ds-cursor .algolia-docsearch-suggestion--content { - background-color: rgba(192, 192, 192, .15) -} diff --git a/docs/index.html b/docs/index.html deleted file mode 100755 index 1343af8e..00000000 --- a/docs/index.html +++ /dev/null @@ -1,201 +0,0 @@ - - - - - - - -Tools for Eurostat Open Data • eurostat - - - - - - - - - -
-
- - - -
-
- - - - -


-

license PRs Welcome Code of Conduct

-

Build Status AppVeyor Status codecov.io Downloads Downloads

-

Gitter Watch on GitHub Star on GitHub Follow

-


-
- -

R tools to access open data from Eurostat. Data search, download, manipulation and visualization.

-
-

-Installation

-

To install the CRAN release version, use:

-
install.packages("eurostat")
-

For the latest github development version, use:

-
install_github("ropengov/eurostat")
-
-
-

-Using the package

-

The R Journal manuscript provides an overview of the package. Various tutorials are available and provide more detailed demonstrations. Check the following:

- -
-
-

-Contribute

-

Check the Github page for source code.

-

Contributions are very welcome:

- -
-
-

-Acknowledgements

-

Kindly cite this work as follows: Leo Lahti, Przemyslaw Biecek, Markus Kainu and Janne Huovari. Retrieval and analysis of Eurostat open data with the eurostat package. R Journal 9(1):385-392, 2017). R package version 3.2.93. URL: http://ropengov.github.io/eurostat

-

We are greatful to all contributors, including Joona Lehtomäki, Francois Briatte, and Oliver Reiter, and for the Eurostat open data portal! This project is part of rOpenGov.

-
-
-

-Disclaimer

-

This package is in no way officially related to or endorsed by Eurostat.

-
-
-
- - - -
- - -
- -
-

Site built with pkgdown.

-
- -
-
- - - - - diff --git a/docs/jquery.sticky-kit.min.js b/docs/jquery.sticky-kit.min.js deleted file mode 100755 index 1c162717..00000000 --- a/docs/jquery.sticky-kit.min.js +++ /dev/null @@ -1,11 +0,0 @@ -/* Sticky-kit v1.1.2 | WTFPL | Leaf Corcoran 2015 | */ -/* - Source: https://github.com/leafo/sticky-kit - License: MIT -*/ -(function(){var b,f;b=this.jQuery||window.jQuery;f=b(window);b.fn.stick_in_parent=function(d){var A,w,J,n,B,K,p,q,k,E,t;null==d&&(d={});t=d.sticky_class;B=d.inner_scrolling;E=d.recalc_every;k=d.parent;q=d.offset_top;p=d.spacer;w=d.bottoming;null==q&&(q=0);null==k&&(k=void 0);null==B&&(B=!0);null==t&&(t="is_stuck");A=b(document);null==w&&(w=!0);J=function(a,d,n,C,F,u,r,G){var v,H,m,D,I,c,g,x,y,z,h,l;if(!a.data("sticky_kit")){a.data("sticky_kit",!0);I=A.height();g=a.parent();null!=k&&(g=g.closest(k)); -if(!g.length)throw"failed to find stick parent";v=m=!1;(h=null!=p?p&&a.closest(p):b("
"))&&h.css("position",a.css("position"));x=function(){var c,f,e;if(!G&&(I=A.height(),c=parseInt(g.css("border-top-width"),10),f=parseInt(g.css("padding-top"),10),d=parseInt(g.css("padding-bottom"),10),n=g.offset().top+c+f,C=g.height(),m&&(v=m=!1,null==p&&(a.insertAfter(h),h.detach()),a.css({position:"",top:"",width:"",bottom:""}).removeClass(t),e=!0),F=a.offset().top-(parseInt(a.css("margin-top"),10)||0)-q, -u=a.outerHeight(!0),r=a.css("float"),h&&h.css({width:a.outerWidth(!0),height:u,display:a.css("display"),"vertical-align":a.css("vertical-align"),"float":r}),e))return l()};x();if(u!==C)return D=void 0,c=q,z=E,l=function(){var b,l,e,k;if(!G&&(e=!1,null!=z&&(--z,0>=z&&(z=E,x(),e=!0)),e||A.height()===I||x(),e=f.scrollTop(),null!=D&&(l=e-D),D=e,m?(w&&(k=e+u+c>C+n,v&&!k&&(v=!1,a.css({position:"fixed",bottom:"",top:c}).trigger("sticky_kit:unbottom"))),eb&&!v&&(c-=l,c=Math.max(b-u,c),c=Math.min(q,c),m&&a.css({top:c+"px"})))):e>F&&(m=!0,b={position:"fixed",top:c},b.width="border-box"===a.css("box-sizing")?a.outerWidth()+"px":a.width()+"px",a.css(b).addClass(t),null==p&&(a.after(h),"left"!==r&&"right"!==r||h.append(a)),a.trigger("sticky_kit:stick")),m&&w&&(null==k&&(k=e+u+c>C+n),!v&&k)))return v=!0,"static"===g.css("position")&&g.css({position:"relative"}), -a.css({position:"absolute",bottom:d,top:"auto"}).trigger("sticky_kit:bottom")},y=function(){x();return l()},H=function(){G=!0;f.off("touchmove",l);f.off("scroll",l);f.off("resize",y);b(document.body).off("sticky_kit:recalc",y);a.off("sticky_kit:detach",H);a.removeData("sticky_kit");a.css({position:"",bottom:"",top:"",width:""});g.position("position","");if(m)return null==p&&("left"!==r&&"right"!==r||a.insertAfter(h),h.remove()),a.removeClass(t)},f.on("touchmove",l),f.on("scroll",l),f.on("resize", -y),b(document.body).on("sticky_kit:recalc",y),a.on("sticky_kit:detach",H),setTimeout(l,0)}};n=0;for(K=this.length;n - - - - - diff --git a/docs/news/index.html b/docs/news/index.html deleted file mode 100755 index 8240f602..00000000 --- a/docs/news/index.html +++ /dev/null @@ -1,370 +0,0 @@ - - - - - - - - -Changelog • eurostat - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - -
- -
-
- - -
-

-eurostat 3.2.3 Unreleased -

-
-

-Minor features

-
    -
  • dplyr moved from Dependencies to Imports
  • -
  • curl removed from Imports
  • -
  • solved geospatial map issues
  • -
  • eurostat_url moved to options
  • -
-
-
-
-

-eurostat 3.2.1 2018-05-20 -

-
-

-Major updates

-
    -
  • Improved support for sf in map visualization
  • -
-
-
-

-Minor features

-
    -
  • data/ generation script in data-raw/ updated to make all data reproducible
  • -
-
-
-

-Bug fixes

-
    -
  • Typo corrected from Cisco to Gisco
  • -
-
-
-
-

-eurostat 3.1.5 2017-08-09 -

-
-

-Minor features

-
    -
  • Added new example data set to reduce repeated downloads from eurostat service

  • -
  • Now label_eurostat() gives always an error by default, if labelling introduces duplicated labels. A new fix_duplicated argument is add to fix duplicated labels automatically. (#79, #90)

  • -
  • Shrinked the package tarball size

  • -
-
-
-

-Bug fixes

-
    -
  • Modified tutorial to accommodate the CRAN error

  • -
  • Fixed cut_to_classes to generate unique breaks

  • -
-
-
-
-

-eurostat 3.1.1 2017-03-16 -

-
-

-R Journal submission

-
    -
  • Release version associated with the R Journal manuscript 2017 final version
  • -
  • Git release added with Zenodo DOI
  • -
-
-
-

-Minor features

-
    -
  • Changed maintainer email address from louhos to leo
  • -
  • Added ./docs/ (automated package website generated with pkgdown)
  • -
  • Expanded unit tests
  • -
  • Gitter badge added to README
  • -
  • Added ./revdep/ to check possible reverse dependencies automatically
  • -
  • Cheat sheet added
  • -
-
-
-

-Bug fixes

-
    -
  • -search_eurostat() accepts new argument fixed: if TRUE (default), pattern provided will used as is; if FALSE, pattern will be interpreted as a true regex pattern.
  • -
  • Augmented the list of Suggested packages in the DESCRIPTION file, including the Cairo package (#70)
  • -
  • Updated the journal manuscript based on reviewer feedback
  • -
-
-
-
-

-eurostat 2.2.20001 Unreleased -

-
    -
  • Development version opened
  • -
-
-
-

-eurostat 2.2.1 2016-09-14 -

-
    -
  • Fixed canonical cran url in README
  • -
-
-
-

-eurostat 2.1.1 Unreleased -

-
    -
  • The complete package now using tibbles
  • -
  • Rare encoding issues circumvented (#55)
  • -
  • Improved functionality within firewall-protected systems (#63)
  • -
-
-
-

-eurostat 2.0 Unreleased -

- -
-
-

-eurostat 1.2.27 Unreleased -

-
    -
  • Calls to extract_numeric are replaced by as.numeric (#60)
  • -
  • The column ‘flags’ is not being labelled even if type = “label” (#61)
  • -
-
-
-

-eurostat 1.2.22 Unreleased -

-
    -
  • The European Commission and the Eurostat generally uses ISO 3166-1 alpha-2 codes with two exceptions: EL (not GR) is used to represent Greece, and UK (not GB) is used to represent the United Kingdom. This now can be handled with harmonize_country_code() which converts the raw data values from EL to GR and from UK to GB.
  • -
  • Harmonized roxygen documentation to better follow CRAN conventions
  • -
  • Changed Windows encoding to UTF for input files
  • -
  • Improved memory usage
  • -
-
-
-

-eurostat 1.2.21 2016-03-11 -

-
    -
  • The get_eurostat() can now get data also from the Eurostat JSON API via get_eurostat_json(). It also have a new argument type to select labels for variable values instead of codes.
  • -
  • Fix an error after update to tidyr 0.4.0 (#47).
  • -
-
-
-

-eurostat 1.2.13 2016-01-19 -

-
    -
  • New select_time argument for get_eurostat() to select a time frequency in case of multi-frequency datasets. Now the get_eurostat() also gives an error if you try to get multi-frequency with other time formats than time_format = "raw". (#30) time column is also now in ascending order.
  • -
  • -get_eurostat() gets a new argument compress_file to control compression of the cache file. Also cache filenames includes now all relevant arguments. (#28)
  • -
  • For search_eurostat() a new type option type = "all" to search all types.
  • -
  • For label_eurostat() new arguments. A code to retain also codes for spesified colums. A eu_order to order factor levels in Eurostat order, which uses the new function dic_order().
  • -
  • Now label_eurostat_vars(x) gives labels for names, if x is other than a character or a factor and label_eurostat_tables(x) does not accept other than a character or a factor.
  • -
  • For get_eurostat() a new argument stringsAsFactors to control the factor conversion of variables.
  • -
  • -eurotime2date (and get_eurostat) convers now also daily data.
  • -
-
-
-

-eurostat 1.0.16 2015-03-27 -

-
    -
  • Fixed vignette error
  • -
-
-
-

-eurostat 1.0.14 (2015-03-19) Unreleased -

-
    -
  • Package largely rewritten
  • -
  • Vignette added
  • -
  • Changed the value column to values in the get_eurostat output
  • -
-
-
-

-eurostat 0.9.1 (2014-04-24) Unreleased -

-
    -
  • Package collected from statfi and smarterpoland
  • -
-
-
- - - -
- -
- - -
-

Site built with pkgdown.

-
- -
-
- - - - - - diff --git a/docs/pkgdown.css b/docs/pkgdown.css deleted file mode 100755 index 6ca2f37a..00000000 --- a/docs/pkgdown.css +++ /dev/null @@ -1,232 +0,0 @@ -/* Sticky footer */ - -/** - * Basic idea: https://philipwalton.github.io/solved-by-flexbox/demos/sticky-footer/ - * Details: https://github.com/philipwalton/solved-by-flexbox/blob/master/assets/css/components/site.css - * - * .Site -> body > .container - * .Site-content -> body > .container .row - * .footer -> footer - * - * Key idea seems to be to ensure that .container and __all its parents__ - * have height set to 100% - * - */ - -html, body { - height: 100%; -} - -body > .container { - display: flex; - height: 100%; - flex-direction: column; - - padding-top: 60px; -} - -body > .container .row { - flex: 1 0 auto; -} - -footer { - margin-top: 45px; - padding: 35px 0 36px; - border-top: 1px solid #e5e5e5; - color: #666; - display: flex; - flex-shrink: 0; -} -footer p { - margin-bottom: 0; -} -footer div { - flex: 1; -} -footer .pkgdown { - text-align: right; -} -footer p { - margin-bottom: 0; -} - -img.icon { - float: right; -} - -img { - max-width: 100%; -} - -/* Typographic tweaking ---------------------------------*/ - -.contents h1.page-header { - margin-top: calc(-60px + 1em); -} - -/* Section anchors ---------------------------------*/ - -a.anchor { - margin-left: -30px; - display:inline-block; - width: 30px; - height: 30px; - visibility: hidden; - - background-image: url(./link.svg); - background-repeat: no-repeat; - background-size: 20px 20px; - background-position: center center; -} - -.hasAnchor:hover a.anchor { - visibility: visible; -} - -@media (max-width: 767px) { - .hasAnchor:hover a.anchor { - visibility: hidden; - } -} - - -/* Fixes for fixed navbar --------------------------*/ - -.contents h1, .contents h2, .contents h3, .contents h4 { - padding-top: 60px; - margin-top: -40px; -} - -/* Static header placement on mobile devices */ -@media (max-width: 767px) { - .navbar-fixed-top { - position: absolute; - } - .navbar { - padding: 0; - } -} - - -/* Sidebar --------------------------*/ - -#sidebar { - margin-top: 30px; -} -#sidebar h2 { - font-size: 1.5em; - margin-top: 1em; -} - -#sidebar h2:first-child { - margin-top: 0; -} - -#sidebar .list-unstyled li { - margin-bottom: 0.5em; -} - -.orcid { - height: 16px; - vertical-align: middle; -} - -/* Reference index & topics ----------------------------------------------- */ - -.ref-index th {font-weight: normal;} - -.ref-index td {vertical-align: top;} -.ref-index .alias {width: 40%;} -.ref-index .title {width: 60%;} - -.ref-index .alias {width: 40%;} -.ref-index .title {width: 60%;} - -.ref-arguments th {text-align: right; padding-right: 10px;} -.ref-arguments th, .ref-arguments td {vertical-align: top;} -.ref-arguments .name {width: 20%;} -.ref-arguments .desc {width: 80%;} - -/* Nice scrolling for wide elements --------------------------------------- */ - -table { - display: block; - overflow: auto; -} - -/* Syntax highlighting ---------------------------------------------------- */ - -pre { - word-wrap: normal; - word-break: normal; - border: 1px solid #eee; -} - -pre, code { - background-color: #f8f8f8; - color: #333; -} - -pre code { - overflow: auto; - word-wrap: normal; - white-space: pre; -} - -pre .img { - margin: 5px 0; -} - -pre .img img { - background-color: #fff; - display: block; - height: auto; -} - -code a, pre a { - color: #375f84; -} - -a.sourceLine:hover { - text-decoration: none; -} - -.fl {color: #1514b5;} -.fu {color: #000000;} /* function */ -.ch,.st {color: #036a07;} /* string */ -.kw {color: #264D66;} /* keyword */ -.co {color: #888888;} /* comment */ - -.message { color: black; font-weight: bolder;} -.error { color: orange; font-weight: bolder;} -.warning { color: #6A0366; font-weight: bolder;} - -/* Clipboard --------------------------*/ - -.hasCopyButton { - position: relative; -} - -.btn-copy-ex { - position: absolute; - right: 0; - top: 0; - visibility: hidden; -} - -.hasCopyButton:hover button.btn-copy-ex { - visibility: visible; -} - -/* mark.js ----------------------------*/ - -mark { - background-color: rgba(255, 255, 51, 0.5); - border-bottom: 2px solid rgba(255, 153, 51, 0.3); - padding: 1px; -} - -/* vertical spacing after htmlwidgets */ -.html-widget { - margin-bottom: 10px; -} diff --git a/docs/pkgdown.js b/docs/pkgdown.js deleted file mode 100755 index de9bd724..00000000 --- a/docs/pkgdown.js +++ /dev/null @@ -1,110 +0,0 @@ -/* http://gregfranko.com/blog/jquery-best-practices/ */ -(function($) { - $(function() { - - $("#sidebar") - .stick_in_parent({offset_top: 40}) - .on('sticky_kit:bottom', function(e) { - $(this).parent().css('position', 'static'); - }) - .on('sticky_kit:unbottom', function(e) { - $(this).parent().css('position', 'relative'); - }); - - $('body').scrollspy({ - target: '#sidebar', - offset: 60 - }); - - $('[data-toggle="tooltip"]').tooltip(); - - var cur_path = paths(location.pathname); - var links = $("#navbar ul li a"); - var max_length = -1; - var pos = -1; - for (var i = 0; i < links.length; i++) { - if (links[i].getAttribute("href") === "#") - continue; - var path = paths(links[i].pathname); - - var length = prefix_length(cur_path, path); - if (length > max_length) { - max_length = length; - pos = i; - } - } - - // Add class to parent
  • , and enclosing
  • if in dropdown - if (pos >= 0) { - var menu_anchor = $(links[pos]); - menu_anchor.parent().addClass("active"); - menu_anchor.closest("li.dropdown").addClass("active"); - } - }); - - function paths(pathname) { - var pieces = pathname.split("/"); - pieces.shift(); // always starts with / - - var end = pieces[pieces.length - 1]; - if (end === "index.html" || end === "") - pieces.pop(); - return(pieces); - } - - function prefix_length(needle, haystack) { - if (needle.length > haystack.length) - return(0); - - // Special case for length-0 haystack, since for loop won't run - if (haystack.length === 0) { - return(needle.length === 0 ? 1 : 0); - } - - for (var i = 0; i < haystack.length; i++) { - if (needle[i] != haystack[i]) - return(i); - } - - return(haystack.length); - } - - /* Clipboard --------------------------*/ - - function changeTooltipMessage(element, msg) { - var tooltipOriginalTitle=element.getAttribute('data-original-title'); - element.setAttribute('data-original-title', msg); - $(element).tooltip('show'); - element.setAttribute('data-original-title', tooltipOriginalTitle); - } - - if(Clipboard.isSupported()) { - $(document).ready(function() { - var copyButton = ""; - - $(".examples, div.sourceCode").addClass("hasCopyButton"); - - // Insert copy buttons: - $(copyButton).prependTo(".hasCopyButton"); - - // Initialize tooltips: - $('.btn-copy-ex').tooltip({container: 'body'}); - - // Initialize clipboard: - var clipboardBtnCopies = new Clipboard('[data-clipboard-copy]', { - text: function(trigger) { - return trigger.parentNode.textContent; - } - }); - - clipboardBtnCopies.on('success', function(e) { - changeTooltipMessage(e.trigger, 'Copied!'); - e.clearSelection(); - }); - - clipboardBtnCopies.on('error', function() { - changeTooltipMessage(e.trigger,'Press Ctrl+C or Command+C to copy'); - }); - }); - } -})(window.jQuery || window.$) diff --git a/docs/pkgdown.yml b/docs/pkgdown.yml deleted file mode 100755 index fc2b6ebb..00000000 --- a/docs/pkgdown.yml +++ /dev/null @@ -1,9 +0,0 @@ -pandoc: 1.19.2.4 -pkgdown: 1.1.0.9000 -pkgdown_sha: 98bfe0fdfd59b33ef1a88ef6896cd60f805f0e81 -articles: - blogposts: blogposts.html - cheatsheet: cheatsheet.html - eurostat_tutorial: eurostat_tutorial.html - publications: publications.html - diff --git a/docs/reference/clean_eurostat_cache.html b/docs/reference/clean_eurostat_cache.html deleted file mode 100755 index 275dd068..00000000 --- a/docs/reference/clean_eurostat_cache.html +++ /dev/null @@ -1,177 +0,0 @@ - - - - - - - - -Clean Eurostat Cache — clean_eurostat_cache • eurostat - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - -
    - -
    -
    - - -
    -

    Delete all .rds files from the eurostat cache directory. - See get_eurostat for more on cache.

    -
    - -
    clean_eurostat_cache(cache_dir = NULL)
    - -

    Arguments

    - - - - - - -
    cache_dir

    A path to cache directory. If NULL (default) -tries to clean default temporary cache directory.

    - - -

    Examples

    -
    clean_eurostat_cache()
    #> The cache does not exist
    -
    - -
    - -
    - - -
    -

    Site built with pkgdown.

    -
    - -
    -
    - - - - - - diff --git a/docs/reference/convert_time_col.html b/docs/reference/convert_time_col.html deleted file mode 100755 index 62470b59..00000000 --- a/docs/reference/convert_time_col.html +++ /dev/null @@ -1,171 +0,0 @@ - - - - - - - - -Time Column Conversions — convert_time_col • eurostat - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - -
    - -
    -
    - - -
    -

    Internal function to convert time column.

    -
    - -
    convert_time_col(x, time_format)
    - -

    Arguments

    - - - - - - - - - - -
    x

    A time column (vector)

    time_format

    see tidy_eurostat

    - - -
    - -
    - -
    - - -
    -

    Site built with pkgdown.

    -
    - -
    -
    - - - - - - diff --git a/docs/reference/cut_to_classes.html b/docs/reference/cut_to_classes.html deleted file mode 100755 index 2d47ecbe..00000000 --- a/docs/reference/cut_to_classes.html +++ /dev/null @@ -1,210 +0,0 @@ - - - - - - - - -Cuts the Values Column into Classes and Polishes the Labels — cut_to_classes • eurostat - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - -
    - -
    -
    - - -
    -

    Categorises a numeric vector into automatic or manually defined categories. -and polishes the labels ready for used in mapping with merge_with_geodata function and ggplot2.

    -
    - -
    cut_to_classes(x, n = 5, style = "equal", manual = FALSE,
    -  manual_breaks = NULL, decimals = 0, nodata_label = "No data")
    - -

    Arguments

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    x

    A numeric vector, eg. values variable in data returned by get_eurostat

    n

    A numeric. number of classes/categories

    style

    Chosen style: one of "fixed", "sd", "equal", "pretty", "quantile", "kmeans", "hclust", -"bclust", "fisher", or "jenks"

    manual

    Logical. If manual breaks are being used

    manual_breaks

    Numeric vector with manual threshold values

    decimals

    Number of decimals to include with labels

    nodata_label

    String. Text label for NA category.

    - -

    Value

    - -

    a factor.

    - -

    Examples

    -
    # NOT RUN { - lp <- get_eurostat("nama_aux_lp") - lp$class <- cut_to_classes(lp$values, n=5, style="equal", decimals=1) - -# }
    -
    - -
    - -
    - - -
    -

    Site built with pkgdown.

    -
    - -
    -
    - - - - - - diff --git a/docs/reference/dic_order.html b/docs/reference/dic_order.html deleted file mode 100755 index 74385f5c..00000000 --- a/docs/reference/dic_order.html +++ /dev/null @@ -1,189 +0,0 @@ - - - - - - - - -Order of Variable Levels from Eurostat Dictionary. — dic_order • eurostat - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - -
    - -
    -
    - - -
    -

    Orders the factor levels.

    -
    - -
    dic_order(x, dic, type)
    - -

    Arguments

    - - - - - - - - - - - - - - -
    x

    a variable (code or labelled) to get order for.

    dic

    a name of the dictionary. Correspond a variable name in the -data_frame from get_eurostat. Can be also data_frame from -get_eurostat_dic.

    type

    a type of the x. Could be code or label.

    - -

    Value

    - -

    A numeric vector of orders.

    -

    Details

    - -

    Some variables, like classifications, have logical or conventional ordering. Eurostat data tables are nor neccessary ordered in this order. The function dic_order get the ordering from Eurostat classifications dictionaries. The function label_eurostat can also order factor levels of labels with argument eu_order = TRUE.

    - -
    - -
    - -
    - - -
    -

    Site built with pkgdown.

    -
    - -
    -
    - - - - - - diff --git a/docs/reference/eu_countries.html b/docs/reference/eu_countries.html deleted file mode 100755 index 1a791dbd..00000000 --- a/docs/reference/eu_countries.html +++ /dev/null @@ -1,178 +0,0 @@ - - - - - - - - -Countries and Country Codes — eu_countries • eurostat - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - -
    - -
    -
    - - -
    -

    Countries and country codes in EU, -Euro area, EFTA and EU candidate countries.

    -
    - -
    eu_countries
    -
    -ea_countries
    -
    -efta_countries
    -
    -eu_candidate_countries
    - - -

    Format

    - -

    A data_frame:

    -
    code

    Country code in the Eurostat database

    -
    name

    Country name in English

    -
    -

    Source

    - -

    http://ec.europa.eu/eurostat/statistics-explained/index.php/Tutorial:Country_codes_and_protocol_order, - http://ec.europa.eu/eurostat/statistics-explained/index.php/Glossary:Euro_area

    - -
    - -
    - -
    - - -
    -

    Site built with pkgdown.

    -
    - -
    -
    - - - - - - diff --git a/docs/reference/eurostat-package.html b/docs/reference/eurostat-package.html deleted file mode 100755 index f987a741..00000000 --- a/docs/reference/eurostat-package.html +++ /dev/null @@ -1,182 +0,0 @@ - - - - - - - - -R Tools for Eurostat open data — eurostat-package • eurostat - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - -
    - -
    -
    - - -
    -

    Brief summary of the eurostat package

    -
    - - - -

    Details

    - - - - - - - - - -
    Package:eurostat
    Type:Package
    Version:See sessionInfo() or DESCRIPTION file
    Date:2014-2017
    License:BSD_2_clause + LICENSE
    LazyLoad:yes
    Package:
    -

    R Tools for Eurostat Open Data

    -

    References

    - -

    See citation("eurostat") -https://ropengov.github.io/eurostat

    - -

    Examples

    -
    library(eurostat)
    -
    - -
    - -
    - - -
    -

    Site built with pkgdown.

    -
    - -
    -
    - - - - - - diff --git a/docs/reference/eurostat_geodata_60.html b/docs/reference/eurostat_geodata_60.html deleted file mode 100755 index a638b018..00000000 --- a/docs/reference/eurostat_geodata_60.html +++ /dev/null @@ -1,172 +0,0 @@ - - - - - - - - -Geospatial data of Europe from Gisco in 1:60 million scale — eurostat_geodata_60 • eurostat - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - -
    - -
    -
    - - -
    -

    Geospatial data of Europe from Gisco in 1:60 million scale

    -
    - -
    eurostat_geodata_60
    - - -

    Format

    - -

    sf

    -
    id

    Country code in the Eurostat database

    -
    CNTRY_CODE

    Country code

    -
    NUTS_NAME

    NUTS name in local language

    -
    LEVL_CODE

    NUTS code

    -
    FID

    Country code

    -
    NUTS_ID

    NUTS code

    -
    geo

    NUTS code

    -
    geometry

    geospatial information

    -
    -

    Source

    - -

    http://ec.europa.eu/eurostat/web/gisco/geodata/reference-data/administrative-units-statistical-units

    - -
    - -
    - -
    - - -
    -

    Site built with pkgdown.

    -
    - -
    -
    - - - - - - diff --git a/docs/reference/eurostat_geodata_60_2013.html b/docs/reference/eurostat_geodata_60_2013.html deleted file mode 100755 index 437696f0..00000000 --- a/docs/reference/eurostat_geodata_60_2013.html +++ /dev/null @@ -1,175 +0,0 @@ - - - - - - - - -Geospatial data of Europe from Gisco in 1:60 million scale from year 2013 — eurostat_geodata_60_2013 • eurostat - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - -
    - -
    -
    - - -
    -

    Geospatial data of Europe from Gisco in 1:60 million scale from year 2013

    -
    - -
    eurostat_geodata_60_2013
    - - -

    Format

    - -

    sf

    -
    id

    Country code in the Eurostat database

    -
    CNTRY_CODE

    Country code

    -
    NUTS_NAME

    NUTS name in local language

    -
    LEVL_CODE

    NUTS code

    -
    FID

    Country code

    -
    NUTS_ID

    NUTS code

    -
    geo

    NUTS code

    -
    geometry

    geospatial information

    -
    -

    Source

    - -

    http://ec.europa.eu/eurostat/web/gisco/geodata/reference-data/administrative-units-statistical-units

    - -
    - -
    - -
    - - -
    -

    Site built with pkgdown.

    -
    - -
    -
    - - - - - - diff --git a/docs/reference/eurostat_geodata_60_2016.html b/docs/reference/eurostat_geodata_60_2016.html deleted file mode 100755 index 293f1141..00000000 --- a/docs/reference/eurostat_geodata_60_2016.html +++ /dev/null @@ -1,175 +0,0 @@ - - - - - - - - -Geospatial data of Europe from Gisco in 1:60 million scale from year 2016 — eurostat_geodata_60_2016 • eurostat - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - -
    - -
    -
    - - -
    -

    Geospatial data of Europe from Gisco in 1:60 million scale from year 2016

    -
    - -
    eurostat_geodata_60_2016
    - - -

    Format

    - -

    sf

    -
    id

    Country code in the Eurostat database

    -
    CNTRY_CODE

    Country code

    -
    NUTS_NAME

    NUTS name in local language

    -
    LEVL_CODE

    NUTS code

    -
    FID

    Country code

    -
    NUTS_ID

    NUTS code

    -
    geometry

    geospatial information

    -
    geo

    NUTS code

    -
    -

    Source

    - -

    http://ec.europa.eu/eurostat/web/gisco/geodata/reference-data/administrative-units-statistical-units

    - -
    - -
    - -
    - - -
    -

    Site built with pkgdown.

    -
    - -
    -
    - - - - - - diff --git a/docs/reference/eurostat_url.html b/docs/reference/eurostat_url.html deleted file mode 100755 index 29f6898f..00000000 --- a/docs/reference/eurostat_url.html +++ /dev/null @@ -1,179 +0,0 @@ - - - - - - - - -Eurostat Base URL — eurostat_url • eurostat - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - -
    - -
    -
    - - -
    -

    Base URL

    -
    - -
    eurostat_url(...)
    - -

    Arguments

    - - - - - - -
    ...

    Arguments to be passed

    - -

    Value

    - -

    url

    -

    References

    - -

    see citation("eurostat").

    - -
    - -
    - -
    - - -
    -

    Site built with pkgdown.

    -
    - -
    -
    - - - - - - diff --git a/docs/reference/eurotime2date.html b/docs/reference/eurotime2date.html deleted file mode 100755 index 95af4110..00000000 --- a/docs/reference/eurotime2date.html +++ /dev/null @@ -1,201 +0,0 @@ - - - - - - - - -Date Conversion from Eurostat Time Format — eurotime2date • eurostat - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - -
    - -
    -
    - - -
    -

    Date conversion from Eurostat time format. A function to -convert Eurostat time values to objects of class Date -representing calendar dates.

    -
    - -
    eurotime2date(x, last = FALSE)
    - -

    Arguments

    - - - - - - - - - - -
    x

    a charter string with time information in Eurostat time format.

    last

    a logical. If FALsE (default) the date is -the first date of the period (month, quarter or year). If TRUE -the date is the last date of the period.

    - -

    Value

    - -

    an object of class Date.

    - -

    Examples

    -
    # NOT RUN {
    -   na_q <- get_eurostat("namq_10_pc", time_format = "raw")
    -   na_q$time <- eurotime2date(x = na_q$time)
    -
    -   un <- get_eurostat("une_rt_m", time_format = "raw")
    -   un$time <- eurotime2date(x = un$time)
    -
    -   na_a <- get_eurostat("nama_10_pc", time_format = "raw")
    -   na_a$time <- eurotime2date(x = na_a$time)
    -
    -   eur_d <- get_eurostat("ert_bil_eur_d", time_format = "raw")
    -   eur_d$time <- eurotime2date(x = eur_d$time)
    -
    -# }
    -
    - -
    - -
    - - -
    -

    Site built with pkgdown.

    -
    - -
    -
    - - - - - - diff --git a/docs/reference/eurotime2num.html b/docs/reference/eurotime2num.html deleted file mode 100755 index 65a11ed5..00000000 --- a/docs/reference/eurotime2num.html +++ /dev/null @@ -1,194 +0,0 @@ - - - - - - - - -Conversion of Eurostat Time Format to Numeric — eurotime2num • eurostat - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - -
    - -
    -
    - - -
    -

    A conversion of a Eurostat time format to numeric.

    -
    - -
    eurotime2num(x)
    - -

    Arguments

    - - - - - - -
    x

    a charter string with time information in Eurostat time format.

    - -

    Value

    - -

    see as.numeric.

    -

    Details

    - -

    Bi-annual, quarterly and monthly data is presented as fraction of - the year in beginning of the period. Conversion of daily data is not - supported.

    - -

    Examples

    -
    # NOT RUN {
    -   na_q <- get_eurostat("namq_10_pc", time_format = "raw")
    -   na_q$time <- eurotime2num(x = na_q$time)
    -
    -   un <- get_eurostat("une_rt_m", time_format = "raw")
    -   un$time <- eurotime2num(x = un$time)
    -
    -   na_a <- get_eurostat("nama_10_pc", time_format = "raw")
    -   na_a$time <- eurotime2num(x = na_a$time)
    -
    -# }
    -
    - -
    - -
    - - -
    -

    Site built with pkgdown.

    -
    - -
    -
    - - - - - - diff --git a/docs/reference/get_eurostat.html b/docs/reference/get_eurostat.html deleted file mode 100755 index 95220202..00000000 --- a/docs/reference/get_eurostat.html +++ /dev/null @@ -1,320 +0,0 @@ - - - - - - - - -Read Eurostat Data — get_eurostat • eurostat - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - -
    - -
    -
    - - -
    -

    Download data sets from Eurostat ec.europa.eu/eurostat.

    -
    - -
    get_eurostat(id, time_format = "date", filters = "none",
    -  type = "code", select_time = NULL, cache = TRUE,
    -  update_cache = FALSE, cache_dir = NULL, compress_file = TRUE,
    -  stringsAsFactors = default.stringsAsFactors(), keepFlags = FALSE,
    -  ...)
    - -

    Arguments

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    id

    A code name for the dataset of interest. -See search_eurostat or details for how to get code.

    time_format

    a string giving a type of the conversion of the time -column from the eurostat format. A "date" (default) convers to -a Date with a first date of the period. -A "date_last" convers to a Date with - a last date of the period. A "num" convers to a numeric and "raw" - does not do conversion. See eurotime2date and - eurotime2num.

    filters

    a "none" (default) to get a whole dataset or a named list of -filters to get just part of the table. Names of list objects are -Eurostat variable codes and values are vectors of observation codes. -If NULL the whole -dataset is returned via API. More on details. See more on filters and -limitations per query via API from for -get_eurostat_json.

    type

    A type of variables, "code" (default) or "label".

    select_time

    a character symbol for a time frequence or NULL, -which is used by default as most datasets have just one time -frequency. For datasets with multiple time -frequencies, select the desired time format with: - Y = annual, S = semi-annual, Q = quarterly, M = monthly. -For all frequencies in same data frame time_format = "raw" -should be used.

    cache

    a logical whether to do caching. Default is TRUE. Affects -only queries from the bulk download facility.

    update_cache

    a locigal whether to update cache. Can be set also with -options(eurostat_update = TRUE)

    cache_dir

    a path to a cache directory. The directory have to exist. -The NULL (default) uses and creates -'eurostat' directory in the temporary directory from -tempdir. Directory can also be set with -option eurostat_cache_dir.

    compress_file

    a logical whether to compress the -RDS-file in caching. Default is TRUE.

    stringsAsFactors

    if TRUE (the default) variables are -converted to factors in original Eurostat order. If FALSE -they are returned as a character.

    keepFlags

    a logical whether the flags (e.g. "confidential", -"provisional") should be kept in a separate column or if they -can be removed. Default is FALSE. For flag values see: -http://ec.europa.eu/eurostat/data/database/information. -Also possible non-real zero "0n" is indicated in flags column. -Flags are not available for eurostat API, so keepFlags -can not be used with a filters.

    ...

    further argument for get_eurostat_json.

    - -

    Value

    - -

    a tibble. One column for each dimension in the data, - the time column for a time dimension and - the values column for numerical values. - Eurostat data does not include all missing values and a treatment of - missing values depend on source. In bulk download - facility missing values are dropped if all dimensions are missing - on particular time. In JSON API missing values are dropped - only if all dimensions are missing on all times. The data from - bulk download facility can be completed for example with - complete.

    -

    Details

    - -

    Data sets are downloaded from -the Eurostat bulk download facility or from The Eurostat Web Services -JSON API. -If only the table id is given, the whole table is downloaded from the -bulk download facility. If also filters are defined the JSON API is -used.

    -

    The bulk download facility is the fastest method to download whole datasets. -It is also often the only way as the JSON API has limitation of maximum -50 sub-indicators at time and whole datasets usually exceeds that. Also, -it seems that multi frequency datasets can only be retrived via -bulk download facility and the select_time is not available for -JSON API method.

    -

    If your connection is thru a proxy, you probably have to set proxy parameters -to use JSON API, see get_eurostat_json.

    -

    By default datasets from the bulk download facility are cached as they are -often rather large. Caching is not (currently) possible for datasets from -JSON API. -Cache files are stored in a temporary directory by default or in -a named directory if cache_dir or option eurostat_cache_dir is defined. -The cache can be emptied with clean_eurostat_cache.

    -

    The id, a code, for the dataset can be searched with -the search_eurostat or from the Eurostat database -http://ec.europa.eu/eurostat/data/database. The Eurostat -database gives codes in the Data Navigation Tree after every dataset -in parenthesis.

    -

    See also

    - - - -

    Examples

    -
    # NOT RUN {
    -k <- get_eurostat("nama_10_lp_ulc")
    -k <- get_eurostat("nama_10_lp_ulc", time_format = "num")
    -k <- get_eurostat("nama_10_lp_ulc", update_cache = TRUE)
    -dir.create(file.path(tempdir(), "r_cache"))
    -k <- get_eurostat("nama_10_lp_ulc",
    -                  cache_dir = file.path(tempdir(), "r_cache"))
    -options(eurostat_update = TRUE)
    -k <- get_eurostat("nama_10_lp_ulc")
    -options(eurostat_update = FALSE)
    -options(eurostat_cache_dir = file.path(tempdir(), "r_cache"))
    -k <- get_eurostat("nama_10_lp_ulc")
    -k <- get_eurostat("nama_10_lp_ulc", cache = FALSE)
    -k <- get_eurostat("avia_gonc", select_time = "Y", cache = FALSE)
    -
    -dd <- get_eurostat("nama_10_gdp",
    -                     filters = list(geo = "FI",
    -                                    na_item = "B1GQ",
    -                                    unit = "CLV_I10"))
    -# }
    -
    - -
    - -
    - - -
    -

    Site built with pkgdown.

    -
    - -
    -
    - - - - - - diff --git a/docs/reference/get_eurostat_dic.html b/docs/reference/get_eurostat_dic.html deleted file mode 100755 index cb313b3b..00000000 --- a/docs/reference/get_eurostat_dic.html +++ /dev/null @@ -1,202 +0,0 @@ - - - - - - - - -Download Eurostat Dictionary — get_eurostat_dic • eurostat - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - -
    - -
    -
    - - -
    -

    Download a Eurostat dictionary.

    -
    - -
    get_eurostat_dic(dictname, lang = "en")
    - -

    Arguments

    - - - - - - - - - - -
    dictname

    A character, dictionary for the variable to be downloaded.

    lang

    A character, language code. Options: "en" (default) / "fr" / "de".

    - -

    Value

    - -

    tibble with two columns: code names and full names.

    -

    Details

    - -

    For given coded variable from Eurostat ec.europa.eu/eurostat. - The dictionaries link codes with human-readable labels. - To translate codes to labels, use label_eurostat.

    -

    References

    - -

    See citation("eurostat").

    -

    See also

    - - - -

    Examples

    -
    # NOT RUN {
    -               tmp <- get_eurostat_dic("crop_pro")
    -               head(tmp)
    -               tmp <- get_eurostat_dic("crop_pro", lang = "fr")
    -
    -# }
    -
    - -
    - -
    - - -
    -

    Site built with pkgdown.

    -
    - -
    -
    - - - - - - diff --git a/docs/reference/get_eurostat_geospatial.html b/docs/reference/get_eurostat_geospatial.html deleted file mode 100755 index 0957bb92..00000000 --- a/docs/reference/get_eurostat_geospatial.html +++ /dev/null @@ -1,231 +0,0 @@ - - - - - - - - -Download Geospatial Data from GISGO — get_eurostat_geospatial • eurostat - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - -
    - -
    -
    - - -
    -

    Downloads either a simple features (sf), SpatialPolygonDataFrame or a data_frame preprocessed using - broom::tidy().

    -
    - -
    get_eurostat_geospatial(output_class = "sf", resolution = "60",
    -  nuts_level = "all", year = "2016", cache = TRUE,
    -  update_cache = FALSE, cache_dir = NULL)
    - -

    Arguments

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    output_class

    A string. Class of object returned, -either sf simple features, df (data_frame) or - spdf (SpatialPolygonDataFrame)

    resolution

    Resolution of the geospatial data. One of -"60" (1:60million), "20" (1:20million), "10" (1:10million), "03" (1:3million) or "01" (1:1million).

    nuts_level

    Level of NUTS classification of the geospatial data. One of -"0", "1", "2", "3" or "all" (mimics the original behaviour)

    year

    NUTS release year. One of -"2003", "2006", "2010", "2013" or "2016"

    cache

    a logical whether to do caching. Default is TRUE. Affects -only queries from the bulk download facility.

    update_cache

    a locigal whether to update cache. Can be set also with -options(eurostat_update = TRUE)

    cache_dir

    a path to a cache directory. The directory have to exist. -The NULL (default) uses and creates -'eurostat' directory in the temporary directory from -tempdir. Directory can also be set with -option eurostat_cache_dir.

    - -

    Value

    - -

    a sf, data_frame or SpatialPolygonDataFrame.

    -

    Details

    - -

    The data source URL is http://ec.europa.eu/eurostat/web/gisco/geodata/reference-data/administrative-units-statistical-units.

    - -

    Examples

    -
    # NOT RUN { - lp <- get_eurostat_geospatial(output_class = "sf", resolution = "60", nuts_level = "all") - lp %>% select(NUTS_ID) %>% plot() - lp <- get_eurostat_geospatial(output_class = "spdf", resolution = "60", nuts_level = "all") - spplot(lp, "STAT_LEVL_") - # or - lp <- get_eurostat_geospatial(output_class = "df", resolution = "60", nuts_level = "all") - ggplot(lp, aes(x=long,y=lat,group=group,fill=STAT_LEVL_),color="white") + geom_polygon() - -# }
    -
    -
    - -
    - -
    - - -
    -

    Site built with pkgdown.

    -
    - -
    -
    - - - - - - diff --git a/docs/reference/get_eurostat_json.html b/docs/reference/get_eurostat_json.html deleted file mode 100755 index 7957495a..00000000 --- a/docs/reference/get_eurostat_json.html +++ /dev/null @@ -1,234 +0,0 @@ - - - - - - - - -Get Data from Eurostat API in JSON — get_eurostat_json • eurostat - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - -
    - -
    -
    - - -
    -

    Retrieve data from Eurostat API in JSON format.

    -
    - -
    get_eurostat_json(id, filters = NULL, type = c("code", "label",
    -  "both"), lang = c("en", "fr", "de"),
    -  stringsAsFactors = default.stringsAsFactors(), ...)
    - -

    Arguments

    - - - - - - - - - - - - - - - - - - - - - - - - - - -
    id

    A code name for the dataset of interested. See the table of -contents of eurostat datasets for more details.

    filters

    A named list of filters. Names of list objects are Eurostat -variable codes and values are vectors of observation codes. If NULL -(default) the whole dataset is returned. See details for more on filters -and limitations per query.

    type

    A type of variables, "code" (default), "label" or "both". The -"both" will return a data_frame with named vectors, labels as values and -codes as names.

    lang

    A language used for metadata (en/fr/de).

    stringsAsFactors

    if TRUE (the default) variables are converted -to factors in original Eurostat order. If FALSE they are returned as -a character.

    ...

    Other arguments passed on to GET. For example -a proxy parameters, see details. -.

    - -

    Value

    - -

    A dataset as a data_frame.

    -

    Details

    - -

    Data to retrieve from - The - Eurostat Web Services can be specified with filters. Normally, it is - better to use JSON query through get_eurostat, than to use - get_eurostat_json directly.

    -

    Queries are limited to 50 sub-indicators at a time. A time can be - filtered with fixed "time" filter or with "sinceTimePeriod" and - "lastTimePeriod" filters. A sinceTimePeriod = 2000 returns - observations from 2000 to a last available. A lastTimePeriod = 10 - returns a 10 last observations.

    -

    To use a proxy to connect, a use_proxy can be - passed to GET. For example - get_eurostat_json(id, filters, - config = httr::use_proxy(url, port, username, password)).

    - -

    Examples

    -
    # NOT RUN { - tmp <- get_eurostat_json("cdh_e_fos") - yy <- get_eurostat_json(id = "nama_gdp_c", filters = list(geo=c("EU28", "FI"), - unit="EUR_HAB", - indic_na="B1GM")) -# }
    -
    - -
    - -
    - - -
    -

    Site built with pkgdown.

    -
    - -
    -
    - - - - - - diff --git a/docs/reference/get_eurostat_raw.html b/docs/reference/get_eurostat_raw.html deleted file mode 100755 index 9609f435..00000000 --- a/docs/reference/get_eurostat_raw.html +++ /dev/null @@ -1,200 +0,0 @@ - - - - - - - - -Download Data from Eurostat Database — get_eurostat_raw • eurostat - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - -
    - -
    -
    - - -
    -

    Download data from the eurostat database.

    -
    - -
    get_eurostat_raw(id)
    - -

    Arguments

    - - - - - - -
    id

    A code name for the dataset of interested. See the table of -contents of eurostat datasets for more details.

    - -

    Value

    - -

    A dataset in tibble format. First column contains comma - separated codes of cases. Other columns usually corresponds to - years and column names are years with preceding X. Data is in - character format as it contains values together with eurostat - flags for data.

    -

    Details

    - -

    Data is downloaded from - http://ec.europa.eu/eurostat/estat-navtree-portlet-prod/BulkDownloadListing and transformed into tabular format.

    -

    References

    - -

    see citation("eurostat")

    -

    See also

    - - - -

    Examples

    -
    # NOT RUN {
    -               tmp <- eurostat:::get_eurostat_raw("educ_iste")
    -               head(tmp)
    -
    -# }
    -
    - -
    - -
    - - -
    -

    Site built with pkgdown.

    -
    - -
    -
    - - - - - - diff --git a/docs/reference/get_eurostat_toc.html b/docs/reference/get_eurostat_toc.html deleted file mode 100755 index ae205496..00000000 --- a/docs/reference/get_eurostat_toc.html +++ /dev/null @@ -1,189 +0,0 @@ - - - - - - - - -Download Table of Contents of Eurostat Data Sets — get_eurostat_toc • eurostat - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - -
    - -
    -
    - - -
    -

    Download table of contents (TOC) of eurostat datasets.

    -
    - -
    get_eurostat_toc()
    - - -

    Value

    - -

    A tibble with eight columns

      -
    • titleThe name of dataset of theme

    • -
    • codeThe codename of dataset of theme, will be used by the eurostat and get_eurostat_raw functions.

    • -
    • typeIs it a dataset, folder or table.

    • -
    • last.update.of.data, last.table.structure.change, data.start, data.endDates.

    • -
    - -

    Details

    - -

    The TOC is downloaded from http://ec.europa.eu/eurostat/estat-navtree-portlet-prod/BulkDownloadListing?sort=1&file=table_of_contents_en.txt. The values in column 'code' should be used to download a selected dataset.

    -

    References

    - -

    See citation("eurostat").

    -

    See also

    - - - -

    Examples

    -
    # NOT RUN {
    -tmp <- get_eurostat_toc(); head(tmp)
    -# }
    -
    - -
    - -
    - - -
    -

    Site built with pkgdown.

    -
    - -
    -
    - - - - - - diff --git a/docs/reference/harmonize_country_code.html b/docs/reference/harmonize_country_code.html deleted file mode 100755 index 840ed0aa..00000000 --- a/docs/reference/harmonize_country_code.html +++ /dev/null @@ -1,190 +0,0 @@ - - - - - - - - -Harmonize Country Code — harmonize_country_code • eurostat - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - -
    - -
    -
    - - -
    -

    The European Commission and the Eurostat generally uses ISO - 3166-1 alpha-2 codes with two exceptions: EL (not GR) is used to - represent Greece, and UK (not GB) is used to represent the - United Kingdom. This function turns country codes into to ISO - 3166-1 alpha-2.

    -
    - -
    harmonize_country_code(x)
    - -

    Arguments

    - - - - - - -
    x

    A character or a factor vector of eurostat countycodes.

    - -

    Value

    - -

    a vector.

    - -

    Examples

    -
    # NOT RUN { - lp <- get_eurostat("nama_aux_lp") - lp$geo <- harmonize_country_code(lp$geo) - -# }
    -
    - -
    - -
    - - -
    -

    Site built with pkgdown.

    -
    - -
    -
    - - - - - - diff --git a/docs/reference/index.html b/docs/reference/index.html deleted file mode 100755 index a735926e..00000000 --- a/docs/reference/index.html +++ /dev/null @@ -1,273 +0,0 @@ - - - - - - - - -Function reference • eurostat - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -

    All functions

    -

    -
    -

    clean_eurostat_cache()

    -

    Clean Eurostat Cache

    -

    cut_to_classes()

    -

    Cuts the Values Column into Classes and Polishes the Labels

    -

    dic_order()

    -

    Order of Variable Levels from Eurostat Dictionary.

    -

    eu_countries ea_countries efta_countries eu_candidate_countries

    -

    Countries and Country Codes

    -

    eurostat-package

    -

    R Tools for Eurostat open data

    -

    eurostat_geodata_60_2016

    -

    Geospatial data of Europe from Gisco in 1:60 million scale from year 2016

    -

    eurotime2date()

    -

    Date Conversion from Eurostat Time Format

    -

    eurotime2num()

    -

    Conversion of Eurostat Time Format to Numeric

    -

    get_eurostat()

    -

    Read Eurostat Data

    -

    get_eurostat_dic()

    -

    Download Eurostat Dictionary

    -

    get_eurostat_geospatial()

    -

    Download Geospatial Data from GISGO

    -

    get_eurostat_json()

    -

    Get Data from Eurostat API in JSON

    -

    get_eurostat_raw()

    -

    Download Data from Eurostat Database

    -

    get_eurostat_toc()

    -

    Download Table of Contents of Eurostat Data Sets

    -

    harmonize_country_code()

    -

    Harmonize Country Code

    -

    label_eurostat() label_eurostat_vars() label_eurostat_tables()

    -

    Get Eurostat Codes

    -

    search_eurostat() grepEurostatTOC()

    -

    Grep Datasets Titles from Eurostat

    -

    tgs00026

    -

    Auxiliary Data

    -
    - - -
    - -
    - - -
    -

    Site built with pkgdown.

    -
    - -
    -
    - - - - - - diff --git a/docs/reference/label_eurostat.html b/docs/reference/label_eurostat.html deleted file mode 100755 index ec31c287..00000000 --- a/docs/reference/label_eurostat.html +++ /dev/null @@ -1,270 +0,0 @@ - - - - - - - - -Get Eurostat Codes — label_eurostat • eurostat - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - -
    - -
    -
    - - -
    -

    Get definitions for Eurostat codes from Eurostat dictionaries.

    -
    - -
    label_eurostat(x, dic = NULL, code = NULL, eu_order = FALSE,
    -  lang = "en", countrycode = NULL, countrycode_nomatch = NULL,
    -  custom_dic = NULL, fix_duplicated = FALSE)
    -
    -label_eurostat_vars(x, lang = "en")
    -
    -label_eurostat_tables(x, lang = "en")
    - -

    Arguments

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    x

    A character or a factor vector or a data_frame.

    dic

    A string (vector) naming eurostat dictionary or dictionaries. -If NULL (default) dictionry names taken from column names of -the data_frame.

    code

    For data_frames names of the column for which also code columns -should be retained. The suffix "_code" is added to code column names.

    eu_order

    Logical. Should Eurostat ordering used for label levels. -Affects only factors.

    lang

    A character, code for language. Available are "en" (default), -"fr" and "de".

    countrycode

    A NULL or a name of the coding scheme for -the countrycode -to label "geo" variable with countrycode-package. It can be used to -convert to short and long country names in many different languages. -If NULL (default) eurostat dictionary is used instead.

    countrycode_nomatch

    What to do when using the countrycode to label a "geo" and -countrycode fails to find a match, for example other than country codes like EU28. -the original code is used with -a NULL (default), eurostat dictionary label is used with "eurostat", -and NA is used with NA.

    custom_dic

    a named vector or named list of named vectors to give an own dictionary -for (part of) codes. Names of the vector should be codes and values labels. List -can be used to spesify dictonaries and then list names should be dictionary codes.

    fix_duplicated

    A logical. If TRUE, the code is added to the -duplicated label values. If FALSE (default) error is given if -labelling produce duplicates.

    - -

    Value

    - -

    a vector or a data_frame.

    -

    Details

    - -

    A character or a factor vector of codes returns a corresponding - vector of definitions. label_eurostat labels also data_frames from - get_eurostat. For vectors a dictionary name have to be - supplied. For data_frames dictonary names are taken from column names. - "time" and "values" columns are returned as they were, so you can supply - data_frame from get_eurostat and get data_frame with - definitions instead of codes.

    -

    Some Eurostat dictionaries includes dublicated labels. By default - dublicated labels cause an error, but they can be fixed automatically - with fix_duplicated = TRUE.

    -

    Functions

    - -
      -
    • label_eurostat_vars: Get definitions for variable (column) names. For -objects other than characters or factors definitions are get for names.

    • -
    • label_eurostat_tables: Get definitions for table names

    • -
    - -

    Examples

    -
    # NOT RUN { - lp <- get_eurostat("nama_10_lp_ulc") - lpl <- label_eurostat(lp) - str(lpl) - lpl_order <- label_eurostat(lp, eu_order = TRUE) - lpl_code <- label_eurostat(lp, code = "unit") - label_eurostat_vars(names(lp)) - label_eurostat_tables("nama_10_lp_ulc") - label_eurostat(c("FI", "DE", "EU28"), dic = "geo") - label_eurostat(c("FI", "DE", "EU28"), dic = "geo", custom_dic = c(DE = "Germany")) - label_eurostat(c("FI", "DE", "EU28"), dic = "geo", countrycode = "country.name", - custom_dic = c(EU28 = "EU")) - label_eurostat(c("FI", "DE", "EU28"), dic = "geo", countrycode = "country.name") - # In Finnish - label_eurostat(c("FI", "DE", "EU28"), dic = "geo", countrycode = "cldr.short.fi") - -# }
    -
    - -
    - -
    - - -
    -

    Site built with pkgdown.

    -
    - -
    -
    - - - - - - diff --git a/docs/reference/merge_eurostat_geodata.html b/docs/reference/merge_eurostat_geodata.html deleted file mode 100755 index abc45974..00000000 --- a/docs/reference/merge_eurostat_geodata.html +++ /dev/null @@ -1,189 +0,0 @@ - - - - - - - - -Merge Geospatial GISCO Data with Eurostat data_frame — merge_eurostat_geodata • eurostat - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - -
    - -
    -
    - - -

    Merges data_frame obtained from Eurostat with get_eurostat with geospatial data preprocessed either using ggplot2::fortify into a data_frame or a regular SpatialPolygonDataFrame. The resulting data_frame can be plotted using ggplot2 and SpatialPolygonDataFrame using sp::spplot.

    - -
    merge_eurostat_geodata(data, geocolumn = "geo", resolution = "60",
    -  all_regions = FALSE, cache = TRUE, update_cache = FALSE,
    -  cache_dir = NULL)
    - -

    Arguments

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    data

    A data_frame including a character vector that -consists of values following current NUTS classification

    geocolumn

    A string. Name of the column with NUTS information -(geo in data_frames fetched using get_eurostat)

    resolution

    Resolution of the geospatial data. One of "60" (1:60million), "20" (1:20million), "10" (1:10million), "01" (1:1million),

    all_regions

    Logical. To include all the regions from spatial data or only the ones included in the fetched Eurostat attribute data

    cache

    cache. Logical.

    update_cache

    Update cache. Logical.

    cache_dir

    Cache directory.

    - -

    Value

    - -

    a data_frame or SpatialPolygonDataFrame.

    - -

    Examples

    -
    # NOT RUN { - lp <- get_eurostat("nama_aux_lp") - lpl <- merge_eurostat_geodata(lp, geocolumn="geo", resolution=60, - all_regions=FALSE) - str(lpl) - -# }
    -
    -
    - -
    - -
    - - -
    -

    Site built with pkgdown.

    -
    - -
    -
    - - - diff --git a/docs/reference/search_eurostat.html b/docs/reference/search_eurostat.html deleted file mode 100755 index d38d64b8..00000000 --- a/docs/reference/search_eurostat.html +++ /dev/null @@ -1,226 +0,0 @@ - - - - - - - - -Grep Datasets Titles from Eurostat — search_eurostat • eurostat - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - -
    - -
    -
    - - -
    -

    Lists names of dataset from eurostat with the particular -pattern in the description.

    -
    - -
    search_eurostat(pattern, type = "dataset", fixed = TRUE)
    -
    -grepEurostatTOC(pattern, type = "dataset")
    - -

    Arguments

    - - - - - - - - - - - - - - -
    pattern

    Character, datasets, folder or tables with this pattern in -the description will be returned (depending on the 'type' argument)

    type

    Grep the Eurostat table of contents either for -'dataset' (default), 'folder', 'table' or "all" (for all types).

    fixed

    logical. If TRUE, pattern is a string to be matched as is. -Change to FALSE if more complex regex matching is needed.

    - -

    Value

    - -

    A tibble with eight columns

      -
    • titleThe name of dataset of theme

    • -
    • codeThe codename of dataset of theme, will be used by the get_eurostat and get_eurostat_raw functions.

    • -
    • typeIs it a dataset, folder or table.

    • -
    • last.update.of.data, last.table.structure.change, data.start, data.endDates.

    • -
    - -

    Details

    - -

    Downloads list of all datasets available on -eurostat and return list of names of datasets that contains particular -pattern in the dataset description. E.g. all datasets related to -education of teaching.

    -

    Functions

    - -
      -
    • grepEurostatTOC: Old deprecated version

    • -
    -

    References

    - -

    See citation("eurostat")

    -

    See also

    - - - -

    Examples

    -
    # NOT RUN {
    -  tmp <- search_eurostat("education")
    -  head(tmp)
    -  # Use "fixed = TRUE" when pattern has characters that would need escaping.
    -  # Here, parentheses would normally need to be escaped in regex
    -  tmp <- search_eurostat("Live births (total) by NUTS 3 region", fixed = TRUE)
    -# }
    -
    - -
    - -
    - - -
    -

    Site built with pkgdown.

    -
    - -
    -
    - - - - - - diff --git a/docs/reference/set_eurostat_toc.html b/docs/reference/set_eurostat_toc.html deleted file mode 100755 index 0fd7428e..00000000 --- a/docs/reference/set_eurostat_toc.html +++ /dev/null @@ -1,179 +0,0 @@ - - - - - - - - -Set Eurostat TOC — set_eurostat_toc • eurostat - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - -
    - -
    -
    - - -
    -

    Internal function.

    -
    - -
    set_eurostat_toc(...)
    - -

    Arguments

    - - - - - - -
    ...

    Arguments to be passed

    - -

    Value

    - -

    Empty element

    -

    References

    - -

    see citation("eurostat")

    - -
    - -
    - -
    - - -
    -

    Site built with pkgdown.

    -
    - -
    -
    - - - - - - diff --git a/docs/reference/tgs00026.html b/docs/reference/tgs00026.html deleted file mode 100755 index 7bb912f9..00000000 --- a/docs/reference/tgs00026.html +++ /dev/null @@ -1,166 +0,0 @@ - - - - - - - - -Auxiliary Data — tgs00026 • eurostat - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - -
    - -
    -
    - - -
    -

    Auxiliary Data Sets

    -
    - -
    tgs00026
    - - -

    Format

    - -

    data_frame

    -

    Details

    - -

    Retrieved with: tgs00026 <- get_eurostat("tgs00026", time_format = "raw")

    - -
    - -
    - -
    - - -
    -

    Site built with pkgdown.

    -
    - -
    -
    - - - - - - diff --git a/docs/reference/tidy_eurostat.html b/docs/reference/tidy_eurostat.html deleted file mode 100755 index ec203ff4..00000000 --- a/docs/reference/tidy_eurostat.html +++ /dev/null @@ -1,214 +0,0 @@ - - - - - - - - -Transform Data into Row-Column-Value Format — tidy_eurostat • eurostat - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - -
    - -
    -
    - - -
    -

    Transform raw Eurostat data table into the row-column-value -format (RCV).

    -
    - -
    tidy_eurostat(dat, time_format = "date", select_time = NULL,
    -  stringsAsFactors = default.stringsAsFactors(), keepFlags = FALSE)
    - -

    Arguments

    - - - - - - - - - - - - - - - - - - - - - - -
    dat

    a data_frame from get_eurostat_raw.

    time_format

    a string giving a type of the conversion of the - time column from the eurostat format. - A "date" (default) convers to a Date - with a first date of the period. A "date_last" - convers to a Date with -a last date of the period. A "num" convers to a numeric and "raw" -does not do conversion. See eurotime2date and -eurotime2num.

    select_time

    a character symbol for a time frequence or NULL -(default).

    stringsAsFactors

    if TRUE (the default) variables are -converted to factors in original Eurostat order. If FALSE -they are returned as strings.

    keepFlags

    a logical whether the flags (e.g. "confidential", -"provisional") should be kept in a separate column or if they -can be removed. Default is FALSE

    - -

    Value

    - -

    tibble in the molten format with the last column 'values'.

    -

    References

    - -

    See citation("eurostat").

    -

    See also

    - - - -
    - -
    - -
    - - -
    -

    Site built with pkgdown.

    -
    - -
    -
    - - - - - - diff --git a/index.Rmd b/index.Rmd deleted file mode 100755 index 58c5dda5..00000000 --- a/index.Rmd +++ /dev/null @@ -1,112 +0,0 @@ ---- -output: - html_document: - keep_md: yes - home: - links: - - text: eurostat homepage - href: http://ropengov.github.io/eurostat/ ---- - - -
    - -[![license](https://img.shields.io/github/license/mashape/apistatus.svg)]() - -[![PRs Welcome][prs-badge]][prs] -[![Code of Conduct][coc-badge]][coc] - -[![Build Status](https://travis-ci.org/rOpenGov/eurostat.svg?branch=master)](https://travis-ci.org/rOpenGov/eurostat) -[![AppVeyor Status](https://ci.appveyor.com/api/projects/status/github/rOpenGov/eurostat?branch=master&svg=true)](https://ci.appveyor.com/project/rOpenGov/eurostat) -[![codecov.io](https://codecov.io/github/rOpenGov/eurostat/coverage.svg?branch=master)](https://codecov.io/github/rOpenGov/eurostat?branch=master) -[![Downloads](http://cranlogs.r-pkg.org/badges/grand-total/eurostat)](https://cran.r-project.org/package=eurostat) -[![Downloads](http://cranlogs.r-pkg.org/badges/eurostat)](https://cran.r-project.org/package=eurostat) - -[![Gitter](https://badges.gitter.im/rOpenGov/eurostat.svg)](https://gitter.im/rOpenGov/eurostat?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) -[![Watch on GitHub][github-watch-badge]][github-watch] -[![Star on GitHub][github-star-badge]][github-star] -[![Follow](https://img.shields.io/twitter/follow/ropengov.svg?style=social)](https://twitter.com/intent/follow?screen_name=ropengov) - -
    - -# eurostat R package - -R tools to access open data from [Eurostat](http://ec.europa.eu/eurostat). Data search, download, manipulation and visualization. - - -### Installation - -To install the CRAN release version, use: - -```{r install, eval=FALSE} -install.packages("eurostat") -``` - - -For the latest github development version, use: - -```{r installdev, eval=FALSE} -install_github("ropengov/eurostat") -``` -```{r lib, include=FALSE, echo=FALSE, warning=FALSE, message=FALSE} -library(eurostat) -``` - -### Using the package - -The [R Journal manuscript](https://journal.r-project.org/archive/2017/RJ-2017-019/index.html) provides an overview of the package. Various tutorials [are available](http://ropengov.github.io/eurostat/articles/index.html) and provide more detailed demonstrations. Check the following: - - * [Cheat sheet: eurostat R package](http://ropengov.github.io/eurostat/articles/cheatsheet.html) - * [Tutorial (vignette) for the eurostat R package](http://ropengov.github.io/eurostat/articles/eurostat_tutorial.html) - * [Blog posts](http://ropengov.github.io/eurostat/articles/blogposts.html) - * [Detailed function documentation](http://ropengov.github.io/eurostat/reference/index.html) - - - -### Contribute - -Check the Github page for [source code](https://github.com/rOpenGov/eurostat/). - -Contributions are very welcome: - - * [Use issue tracker](https://github.com/ropengov/eurostat/issues) for feedback and bug reports. - * [Send pull requests](https://github.com/ropengov/eurostat/) - * [Star us on the Github page](https://github.com/ropengov/eurostat) - * [Join the discussion in Gitter](https://gitter.im/rOpenGov/eurostat) - -### Acknowledgements - -**Kindly cite this work** as follows: [Leo Lahti](https://github.com/antagomir), Przemyslaw Biecek, Markus Kainu and Janne Huovari. Retrieval and analysis of Eurostat open data with the eurostat package. [R Journal 9(1):385-392, 2017](https://journal.r-project.org/archive/2017/RJ-2017-019/index.html)). R package version `r sessionInfo()$otherPkgs$eurostat$Version`. URL: [http://ropengov.github.io/eurostat](http://ropengov.github.io/eurostat) - -We are greatful to all [contributors](https://github.com/rOpenGov/eurostat/graphs/contributors), including Joona Lehtomäki, Francois Briatte, and Oliver Reiter, and for the [Eurostat](http://ec.europa.eu/eurostat/) open data portal! This project is part of [rOpenGov](http://ropengov.github.io). - - -### Disclaimer - -This package is in no way officially related to or endorsed by Eurostat. - - -[chat-badge]: https://img.shields.io/badge/chat-on%20gitter-46BC99.svg?style=flat-square -[chat]: https://gitter.im/ropengov/eurostat?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge -[build-badge]: https://img.shields.io/travis/ropengov/eurostat.svg?style=flat-square -[build]: https://travis-ci.org/ropengov/eurostat -[version-badge]: https://img.shields.io/npm/v/eurostat.svg?style=flat-square -[package]: https://www.npmjs.com/package/eurostat -[license-badge]: https://img.shields.io/npm/l/eurostat.svg?style=flat-square -[license]: https://github.com/ropengov/eurostat/blob/master/LICENSE -[prs-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square -[prs]: http://makeapullrequest.com -[donate-badge]: https://img.shields.io/badge/$-support-green.svg?style=flat-square -[donate]: http://kcd.im/donate -[coc-badge]: https://img.shields.io/badge/code%20of-conduct-ff69b4.svg?style=flat-square -[coc]: https://github.com/ropengov/eurostat/blob/master/other/CODE_OF_CONDUCT.md -[implementations-badge]: https://img.shields.io/badge/%F0%9F%92%A1-implementations-8C8E93.svg?style=flat-square -[implementations]: https://github.com/ropengov/eurostat/blob/master/other/IMPLEMENTATIONS.md -[github-watch-badge]: https://img.shields.io/github/watchers/ropengov/eurostat.svg?style=social -[github-watch]: https://github.com/ropengov/eurostat/watchers -[github-star-badge]: https://img.shields.io/github/stars/ropengov/eurostat.svg?style=social -[github-star]: https://github.com/ropengov/eurostat/stargazers -[twitter]: https://twitter.com/intent/tweet?text=Check%20out%20eurostat!%20%E2%9C%A8%20Recognize%20all%20contributors,%20not%20just%20the%20ones%20who%20commit%20code%20%E2%9C%A8%20https://github.com/ropengov/eurostat%20%F0%9F%A4%97 -[twitter-badge]: https://img.shields.io/twitter/url/https/github.com/ropengov/eurostat.svg?style=social -[emojis]: https://github.com/ropengov/eurostat#emoji-key -[eurostat]: https://github.com/ropengov/eurostat diff --git a/inst/CITATION b/inst/CITATION index b06947df..ca7e261b 100755 --- a/inst/CITATION +++ b/inst/CITATION @@ -1,31 +1,54 @@ citHeader("Kindly cite the eurostat R package as follows:") +year <- sub("-.*", "", meta$Date) +vers <- paste("R package version", meta$Version) -note <- sprintf("Version %s", meta$Version) - -citEntry(entry="misc", - title = "eurostat R package", - author = personList( - person(given ="Leo", family="Lahti", email = "leo.lahti@iki.fi"), - person(given = "Janne", family="Huovari"), - person(given = "Markus", family="Kainu"), - person(given = "Przemyslaw", family="Biecek") - ), - journal = "R Journal", - volume = "9", - number = "1", - pages = "385-392", - year = "2017", - url = "https://journal.r-project.org/archive/2017/RJ-2017-019/index.html", - note = note, - textVersion = - paste("(C) Leo Lahti, Janne Huovari, Markus Kainu, Przemyslaw Biecek.", - "Retrieval and analysis of Eurostat open data with the eurostat package. R Journal 9(1):385-392, 2017.", - note, - "Package URL: http://ropengov.github.io/eurostat", - "Manuscript URL: https://journal.r-project.org/archive/2017/RJ-2017-019/index.html", - - sep=" ") - ) - +bibentry("Article", + key = "10.32614/RJ-2017-019", + title = "Retrieval and Analysis of Eurostat Open Data with the eurostat Package", + author = c( + person("Leo", "Lahti"), + person("Janne", "Huovari"), + person("Markus", "Kainu"), + person("Przemyslaw", "Biecek") + ), + journal = "The R Journal", + volume = 9, + number = 1, + pages = "385--392", + year = "2017", + doi = "10.32614/RJ-2017-019", + url = "https://doi.org/10.32614/RJ-2017-019", + textVersion = + paste("Lahti L., Huovari J., Kainu M., and Biecek P. (2017).", + "Retrieval and analysis of Eurostat open data with the eurostat package. The R Journal 9(1), pp. 385-392.", + "doi: 10.32614/RJ-2017-019", + sep = " " + ) +) +bibentry(bibtype = "Misc", + key = "eurostat", + title = "eurostat: Tools for Eurostat Open Data", + author = c( + person("Leo", "Lahti"), + person("Janne", "Huovari"), + person("Markus", "Kainu"), + person("Przemyslaw", "Biecek"), + person("Diego", "Hernangomez"), + person("Daniel", "Antal"), + person("Pyry", "Kantanen") + ), + url = "https://github.com/rOpenGov/eurostat", + type = "Computer software", + year = year, + note = vers, + textVersion = + paste0( + "Lahti, L., Huovari J., Kainu M., Biecek P., Hernangomez D., Antal D., and Kantanen P. (", + sub("-.*", "", meta$Date), + "). eurostat: Tools for Eurostat Open Data [Computer software]. ", + vers, + ". https://github.com/rOpenGov/eurostat" + ) +) \ No newline at end of file diff --git a/inst/WORDLIST b/inst/WORDLIST new file mode 100644 index 00000000..4db0c91c --- /dev/null +++ b/inst/WORDLIST @@ -0,0 +1,130 @@ +Acknowledgements +Analytics +Biblatex +Bibtex +CNTRY +Categorises +Choropleth +DOI +Dol +EEA +EFTA +EL +EPSG +ETRS +EuroGeographics +Eurostat's +Eurozone +FID +FTE +GISCO +GeoJSON +Geospatial +Gisco +Github +Gitter +Hernangómez +JSON +Kenett +LAEA +LEVL +LazyLoad +Lehtomäki +RCV +RJ +RStudio +Recode +Recoding +Renviron +SDMX +Shmueli +SpatialPolygonDataFrame +TOC +WGS +Wietse +avia +bclust +behaviour +bibentry +codecov +codename +comext +comformity +comparativity +countrycode +countycodes +de +dieghernan +dir +dpih +eXchange +ec +efta +eg +enps +eu +europa +europe +eurozone +facto +fi +geo +geospatial +ggplot +giscoR +github +gmail +googlegroups +hclust +headtails +hostname +http +https +huovari +hv +iki +io +janne +jenks +json +kable +kainu +kapsi +kilometres +kmeans +labelled +lahti +lastTimePeriod +leo +lifecycle +markus +markuskainu +mln +num +paoa +paoc +paocc +persreg +pkm +pre +preprocessed +psmod +pstra +ptt +rOG +rOpenGov +rds +reaggregate +recode +recoding +relabelled +restatapi +rjsdmx +ropengov +rsdmx +sd +sinceTimePeriod +spplot +tibble +tmap +tran diff --git a/inst/extdata/sdmx_to_http_error_mapping.csv b/inst/extdata/sdmx_to_http_error_mapping.csv new file mode 100644 index 00000000..303fdf49 --- /dev/null +++ b/inst/extdata/sdmx_to_http_error_mapping.csv @@ -0,0 +1,11 @@ +type;sdmx.faultcode;sdmx.faultstring;http.status_code;http.status_code.label;detail +Client error;100;No results found;400;Bad request;The result from the query is empty +Client error;100;No results found;404;Not found;The requested resource is not available +Client error;140;Syntax error;400;Bad request;The query is invalid +Client error;150;Semantic error;400;Bad request;The request is syntactically correct but fails a semantic validation or violates agreed business rules +Client error;110;Unauthorized;401;Unauthorized;Authentication is needed but has failed or has not yet been provided +Client error;130;Response too large due to client request;413;Request entity too large;The request results in a response that is larger than the client is willing or able to process +Server error;500;Internal server error;500;Internal server error;The webservice returns this error code when none of the other error codes better describe the reason for the failure of the service to provide a meaningful response +Server error;501;Not implemented;501;Not implemented;The webservice has not yet implemented one of the methods defined in the API +Server error;503;Service unavailable;503;Service unavailable;The web service is temporarily unavailable because of maintenance or for some other similar reason +Server error;510;Response size exceeds service limit;413;Request entity too large;The request results in a response that is larger than the server is willing or able to process \ No newline at end of file diff --git a/inst/extras/build.cran.sh b/inst/extras/build.cran.sh index 0cc70c01..4855a53b 100755 --- a/inst/extras/build.cran.sh +++ b/inst/extras/build.cran.sh @@ -1,5 +1,4 @@ #/usr/bin/R CMD BATCH document.R -~/bin/R-3.5.1/bin/R CMD build ../../ #--no-build-vignettes -~/bin/R-3.5.1/bin/R CMD check --as-cran eurostat_3.2.93.tar.gz #--no-build-vignettes -~/bin/R-3.5.1/bin/R CMD INSTALL eurostat_3.2.93.tar.gz - +~/bin/R-4.2.2/bin/R CMD build ../../ # --no-build-vignettes +~/bin/R-4.2.2/bin/R CMD check --as-cran eurostat_3.8.2.tar.gz # --no-build-vignettes +~/bin/R-4.2.2/bin/R CMD INSTALL eurostat_3.8.2.tar.gz diff --git a/inst/extras/cheatsheet/barplot.pdf b/inst/extras/cheatsheet/barplot.pdf new file mode 100755 index 00000000..269bb7a9 Binary files /dev/null and b/inst/extras/cheatsheet/barplot.pdf differ diff --git a/inst/extras/cheatsheet/by.png b/inst/extras/cheatsheet/by.png new file mode 100755 index 00000000..c8473a24 Binary files /dev/null and b/inst/extras/cheatsheet/by.png differ diff --git a/inst/extras/cheatsheet/cheat_sheet_background.png b/inst/extras/cheatsheet/cheat_sheet_background.png new file mode 100755 index 00000000..d57ae97f Binary files /dev/null and b/inst/extras/cheatsheet/cheat_sheet_background.png differ diff --git a/inst/extras/cheatsheet/cheat_sheet_content.Rmd b/inst/extras/cheatsheet/cheat_sheet_content.Rmd new file mode 100755 index 00000000..9565edf0 --- /dev/null +++ b/inst/extras/cheatsheet/cheat_sheet_content.Rmd @@ -0,0 +1,172 @@ +--- +output: html_document +editor_options: + chunk_output_type: console +--- + +```{r} +here_path <- here::here() +library(extrafont) +loadfonts() +library(ggplot2) +theme_set(theme_minimal(base_family = "PT Sans")) +``` + + +R tools to access open data from Eurostat database +========================================= + +# Search and download + +Data in the Eurostat database is stored in tables. +Each table has an identifier, a short table_code, and +a description (e.g. tps00199 - Total fertility rate). + +Key eurostat functions allow to find the table_code, +download the eurostat table and polish labels in the table. + +## Find the table code + +The search_eurostat(pattern, ...) function scans the directory +of Eurostat tables and returns codes and descriptions of +tables that match pattern. + +```{r} +library("eurostat") +query <- search_eurostat(pattern = "fertility rate", + type = "table", fixed = FALSE) +query[,1:2] +## title code +## +## Total fertility rate by NUTS 2 region tgs00100 +## Total fertility rate tps00199 +## Total fertility rate by NUTS 2 region tgs00100 +``` + + +## Download the table + +The get_eurostat(id, time_format = "date", filters = "none", +type = "code", cache = TRUE, ...) function downloads the +requested table from the Eurostat bulk download facility or +from The Eurostat Web Services JSON API (if filters are defined). +Downloaded data is cached (if cache=TRUE). +Additional arguments define how to read the time column +(time_format) and if table dimensions shall be kept as +codes or converted to labels (type). + +```{r} +ct <- c("AT","BE","BG","CH","CY","CZ","DE","DK","EE","EL","ES", + "FI","FR","HR","HU","IE","IS","IT","LI","LT","LU","LV", + "MT","NL","NO","PL","PT","RO","SE","SI","SK","UK") +dat <- get_eurostat(id="tps00199", time_format="num", + filters = list(geo = ct)) +dat[1:2,] +## indic_de geo time values +## TOTFERRT AT 2006 1.41 +## TOTFERRT AT 2007 1.38 +``` + +## Add labels + +The label_eurostat(x, lang = "en", ...) gets definitions for Eurostat +codes and replace them with labels in given language ("en", "fr" or "de") + +```{r} +dat <- label_eurostat(dat) +dat[1:3,] +## indic_de geo time values +## +## Total fertility rate Austria 2006 1.41 +## Total fertility rate Austria 2007 1.38 +## Total fertility rate Austria 2008 1.42 +``` + + +## eurostat and plots + +The get_eurostat() function returns tibbles in the long format. Packages +dplyr and tidyr are well suited to transform these objects. The ggplot2 +package is well suited to plot these objects. + +```{r} +dat <- get_eurostat(id="tps00199", filters = list(geo = ct)) +library(ggplot2) +library(dplyr) +ggplot(dat, + aes(x = time, y = values, color = geo, label = geo)) + + geom_line(alpha = .5) + + geom_text(data = dat %>% group_by(geo) %>% + filter(time == max(time)), + size = 2.6) + + theme(legend.position = "none") + + labs(title = "Total fertility rate, 2006-2017", + x = "Year", y = "%") -> p +# save plot +ggsave(filename = glue::glue("{here_path}/inst/extras/cheatsheet/lineplot.pdf"),plot = p, width = 4.84, height = 3.26, device = cairo_pdf) +``` + +```{r} +dat_2015 <- dat %>% + filter(time == "2015-01-01") +ggplot(dat_2015, aes(x = reorder(geo, values), y = values)) + + geom_col(color = "white", fill = "grey80") + + theme(axis.text.x = element_text(size = 6)) + + labs(title = "Total fertility rate, 2015", + y = "%", x = NULL) -> p +# save plot +ggsave(filename = glue::glue("{here_path}/inst/extras/cheatsheet/barplot.pdf"),plot = p, width = 4.84, height = 3.26, device = cairo_pdf) +``` + + +# eurostat and maps + +## Fetch and process data + +There are three function to work with geospatial data from GISCO. The +get_eurostat_geospatial() returns spatial data as sf-object. +Object can me merged with data.frames using dplyr::*_join()-functions. +The cut_to_classes() is a wrapper for cut() - function and +is used for categorizing data for maps with tidy labels. + +```{r} +mapdata <- get_eurostat_geospatial(nuts_level = 0) %>% + right_join(dat_2015) %>% + mutate(cat = cut_to_classes(values, n=4, decimals=1)) +head(select(mapdata,geo,values,cat), 3) +## geo values cat geometry +## AT 1.49 1.5 ~< 1.6 MULTIPOLYGON (((15.54245 48... +## BE 1.70 1.6 ~< 1.8 MULTIPOLYGON (((5.10218 51.... +## BG 1.53 1.5 ~< 1.6 MULTIPOLYGON (((22.99717 43... +``` + + +## Plot a map + +The sf-object returned are ready to be plotted with +ggplot::geom_sf()-function. + +```{r} +ggplot(mapdata, aes(fill = cat)) + + scale_fill_brewer(palette = "RdYlBu") + + geom_sf(color = alpha("white",1/3), alpha = .6) + + xlim(c(-12,37)) + ylim(c(35,70)) + + labs(title = "Total fertility rate, 2015", + subtitle = "Avg. number of life births per woman", + fill = "%") -> p +# save plot +ggsave(filename = glue::glue("{here_path}/inst/extras/cheatsheet/mapplot.pdf"),plot = p, width = 5.14, height = 4.26, device = cairo_pdf) +``` + +******* + +This onepager presents the eurostat package 2014-2019 +Leo Lahti, Janne Huovari, Markus Kainu, Przemyslaw Biecek +package version 3.3.55 URL: https://github.com/rOpenGov/eurostat + +Retrieval and Analysis of Eurostat Open Data with the eurostat Package. +Leo Lahti, Janne Huovari, Markus Kainu, and Przemysław Biecek. +The R Journal, 9(1):385–392, 2017. + +CC BY Przemyslaw Biecek & Markus Kainu +https://creativecommons.org/licenses/by/4.0/ diff --git a/inst/extras/cheatsheet/cheatsheet2019.pdf b/inst/extras/cheatsheet/cheatsheet2019.pdf new file mode 100755 index 00000000..137d50a2 Binary files /dev/null and b/inst/extras/cheatsheet/cheatsheet2019.pdf differ diff --git a/inst/extras/cheatsheet/cheatsheet2019.svg b/inst/extras/cheatsheet/cheatsheet2019.svg new file mode 100755 index 00000000..d45741b6 --- /dev/null +++ b/inst/extras/cheatsheet/cheatsheet2019.svg @@ -0,0 +1,40733 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 35 + + + ° + + + N + 40 + + + ° + + + N + 45 + + + ° + + + N + 50 + + + ° + + + N + 55 + + + ° + + + N + 60 + + + ° + + + N + 65 + + + ° + + + N + 70 + + + ° + + + N + 10 + + + ° + + + W0 + + + ° + + + 10 + + + ° + + + E20 + + + ° + + + E30 + + + ° + + + E + + + % + + + + + + + + + + + 1.3 ~< 1.5 + 1.5 ~< 1.6 + 1.6 ~< 1.8 + 1.8 ~< 2 + + + Avg. number of life births per woman + + + Total fertility rate, 2015 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + AT + + + BE + + + BG + + + CH + + + CY + + + CZ + + + DE + + + DK + + + EE + + + EL + + + ES + + + FI + + + FR + + + HR + + + HU + + + IE + + + IS + + + IT + + + LI + + + LT + + + LU + + + LV + + + MT + + + NL + + + NO + + + PL + + + PT + + + RO + + + SE + + + SI + + + SK + + + UK + + + 1.25 + 1.50 + 1.75 + 2.00 + 2.25 + 200620082010201220142016 + + + Year + + + % + + + Total fertility rate, 2006-2017 + + + + + + + + + + Access Eurostat data with eurostat::cheat sheet + Data in the Eurostat database is stored in tables.Each table has an identifier, a short table_code, and a description (e.g. tps00199 - Total fertility rate).Key eurostat functions allow to find the table_code, download the eurostat table and polish labels in the table.Find the table codeThe search_eurostat(pattern, ...) function scans the directory of Eurostat tables and returns codes and descriptions of tables that match pattern. + library("eurostat")query <- search_eurostat(pattern = "fertility rate", type = "table", fixed = FALSE)query[,1:2]## title code ## <chr> <chr> ## Total fertility rate by NUTS 2 region tgs00100## Total fertility rate tps00199## Total fertility rate by NUTS 2 region tgs00100 + Download the tableThe get_eurostat(id, time_format = "date", filters = "none", type = "code", cache = TRUE, ...) function downloads the requested table from the Eurostat bulk download facility orfrom The Eurostat Web Services JSON API (if filters are defined). Downloaded data is cached (if cache=TRUE). Additional arguments define how to read the time column(time_format) and if table dimensions shall be kept as codes or converted to labels (type). + ct <- c("AT","BE","BG","CH","CY","CZ","DE","DK","EE","EL","ES", "FI","FR","HR","HU","IE","IS","IT","LI","LT","LU","LV", "MT","NL","NO","PL","PT","RO","SE","SI","SK","UK")dat <- get_eurostat(id="tps00199", time_format="num", filters = list(geo = ct))dat[1:2,]## indic_de geo time values## TOTFERRT AT 2006 1.41## TOTFERRT AT 2007 1.38 + Add labelsThe label_eurostat(x, lang = "en", ...) gets definitions for Eurostatcodes and replace them with labels in given language ("en", "fr" or "de") + dat <- label_eurostat(dat)dat[1:3,]## indic_de geo time values## <fct> <fct> <dbl> <dbl>## Total fertility rate Andorra 2006 1.24## Total fertility rate Albania 2006 1.67## Total fertility rate Armenia 2006 1.34 + Search and download + eurostat and plots + The get_eurostat() function returns tibbles in the long format. Packagesdplyr and tidyr are well suited to transform these objects. The ggplot2-package is well suited to plot these objects. + dat <- get_eurostat(id="tps00199", filters = list(geo = ct))library(ggplot2)library(dplyr)ggplot(dat, aes(x = time, y = values, color = geo, label = geo)) + geom_line(alpha = .5) + geom_text(data = dat %>% group_by(geo) %>% filter(time == max(time)), size = 2.6) + theme(legend.position = "none") + labs(title = "Total fertility rate, 2006-2017", x = "Year", y = "%") + dat_2015 <- dat %>% filter(time == "2015-01-01") ggplot(dat_2015, aes(x = reorder(geo, values), y = values)) + geom_col(color = "white", fill = "grey80") + theme(axis.text.x = element_text(size = 6)) + labs(title = "Total fertility rate, 2015", y = "%", x = NULL) + eurostat and maps + There are two function to work with geospatial data from GISCO. Theget_eurostat_geospatial() returns spatial data as sf-object. Object can me merged with data.frames using dplyr::*_join()-functions.The cut_to_classes() is a wrapper for cut() - function and is used for categorizing data for maps with tidy labels. + mapdata <- get_eurostat_geospatial(nuts_level = 0) %>% right_join(dat_2015) %>% mutate(cat = cut_to_classes(values, n=4, decimals=1))head(select(mapdata,geo,values,cat), 3)## geo values cat geometry## AT 1.49 1.5 ~< 1.6 MULTIPOLYGON (((15.54245 48...## BE 1.70 1.6 ~< 1.8 MULTIPOLYGON (((5.10218 51....## BG 1.53 1.5 ~< 1.6 MULTIPOLYGON (((22.99717 43... + Plot a Map The sf-object returned are ready to be plotted with ggplot::geom_sf()-function. + ggplot(mapdata, aes(fill = cat)) + scale_fill_brewer(palette = "RdYlBu") + geom_sf(color = alpha("white",1/3), alpha = .6) + xlim(c(-12,44)) + ylim(c(35,70)) + labs(title = "Total fertility rate, 2015", subtitle = "Avg. number of life births per woman", fill = "%") + CC BY Przemyslaw Biecek & Markus Kainu 2019-11-06https://creativecommons.org/licenses/by/4.0/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0.0 + 0.5 + 1.0 + 1.5 + 2.0 + + + PTCYPLELESITMTHRLISKHULUATDEBGCHCZSIEEROFINLBELTLVDKNOISUKIESEFR + + + % + + + Total fertility rate, 2015 + + + + This onepager presents the eurostat package 2014-2019 Leo Lahti, Janne Huovari, Markus Kainu, Przemyslaw Biecek package version 3.3.55 URL: https://github.com/rOpenGov/eurostatRetrieval and Analysis of Eurostat Open Data with the eurostat Package. Leo Lahti, Janne Huovari, Markus Kainu, and Przemysław Biecek. The R Journal, 9(1):385–392, 2017. + + + + diff --git a/inst/extras/cheatsheet/lineplot.pdf b/inst/extras/cheatsheet/lineplot.pdf new file mode 100755 index 00000000..b616b373 Binary files /dev/null and b/inst/extras/cheatsheet/lineplot.pdf differ diff --git a/inst/extras/cheatsheet/logo.png b/inst/extras/cheatsheet/logo.png new file mode 100755 index 00000000..f785f2f8 Binary files /dev/null and b/inst/extras/cheatsheet/logo.png differ diff --git a/inst/extras/cheatsheet/mapplot.pdf b/inst/extras/cheatsheet/mapplot.pdf new file mode 100755 index 00000000..ec42f50d Binary files /dev/null and b/inst/extras/cheatsheet/mapplot.pdf differ diff --git a/inst/extras/document.R b/inst/extras/document.R index 84505df0..73a3bfe1 100755 --- a/inst/extras/document.R +++ b/inst/extras/document.R @@ -5,25 +5,29 @@ library(devtools) document("../../") #build("../../") #build(vignettes = FALSE) +# devtools::install(build_vignettes = TRUE) #check("../../", vignettes = FALSE) #install() -library(knitr) -knit(input = "../../README.Rmd", output = "../../README.md") +library(rmarkdown) +render(input = "../../README.Rmd", output_format = "md_document") # build the ../../docs directory as a pkg website -library(pkgdown) -setwd("../../") -build_site() +#library(pkgdown) +#setwd("../../") +#build_site() +# devtools::build_vignettes() + # Submissions: # # release() # Submit to CRAN +# devtools::check_win_devel("../../") # Windows check # submit_cran() # Submit to CRAN without all release() questions +# use_cran_comments() # Utilities: # -# build_win("../../") # Windows check # revdep_check("../../") # add_rstudio_project("../../") # use_build_ignore("../NEWS.md", pkg = "../../") # NEWS.md not supported by CRAN @@ -32,14 +36,20 @@ build_site() # test() # Run tests # run_examples() +# Add Github actions (Travis replacement) +#usethis::use_github_action_check_standard() +# -> .github/workflows/.. +# See https://github.com/r-lib/actions + # Vignettes: # # library(knitr) # knit("../../vignettes/eurostat_tutorial.Rmd", "../../vignettes/eurostat_tutorial.md") # or run main.R in vignettes -setwd("vignettes/") -source("main.R") -tools::compactPDF("./", gs_quality = "ebook") +#setwd("vignettes/") +#source("main.R") +# system("cp vignette.html ../inst/doc/") +# tools::compactPDF("./", gs_quality = "ebook") diff --git a/inst/extras/eurostat_description.md b/inst/extras/eurostat_description.md new file mode 100755 index 00000000..47f9759d --- /dev/null +++ b/inst/extras/eurostat_description.md @@ -0,0 +1,5 @@ +The eurostat R package is a mature collection of algorithms that facilitate efficient retrieval, analysis and visualization of data from Eurostat open data portal. The package has emerged from international non-profit collaboration between academic researchers and R developers. + +While we are backing up our work by pragmatic case studies and demonstrations, the overall scope of our contribution is wider and it opens up new opportunities for data scientists. R is one of the most popular open statistical programming and data science environments currently and it is widely used in research, government, data journalism, and industry. Our proposed eurostat R package is facilitating access to the European open data resources. Its popularity among the data science community has been steadily growing, with 50% increase in annual downloads since the first version in 2015. The present mature version of the package was formally published in R Journal in 2018. It is now available in the CRAN software repository and has found a considerable number of users in research and government, with roughly 20,000 downloads in 2018. + +The package provides practically tested open source tools that allow seamless integration of the eurostat open data resources and complementary data sources in open statistical environments where the data can be analyzed with the latest research algorithms. We have developed various case studies that demonstrate how these tools can facilitate the development and sharing of reproducible and transparent statistical workflows and provide insights into European demographics. Therefore, instead of a particular case study or demonstration, our main proposed innovation is the development of general-purpose algorithmic tools that provide enhanced opportunities for the utilization of European open data resources. diff --git a/inst/extras/sticker.R b/inst/extras/sticker.R new file mode 100755 index 00000000..88b90d54 --- /dev/null +++ b/inst/extras/sticker.R @@ -0,0 +1,15 @@ +# https://github.com/GuangchuangYu/hexSticker + +library(hexSticker) +library(ggplot2) + +#p <- ggplot(aes(x = mpg, y = wt), data = mtcars) + geom_point() +#p <- p + theme_void() + theme_transparent() +#png("estat.png"); print(p); dev.off() + +imgurl <- "estat.png" + +sticker(imgurl, package="eurostat", + p_size=8, s_x=1, s_y=.75, s_width=1.3, s_height=1, + filename="eurostat.png") + diff --git a/man/add_nuts_level.Rd b/man/add_nuts_level.Rd new file mode 100755 index 00000000..a231b31f --- /dev/null +++ b/man/add_nuts_level.Rd @@ -0,0 +1,54 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/deprecated_regions_functions.R +\name{add_nuts_level} +\alias{add_nuts_level} +\title{Add the statistical aggregation level to data frame} +\usage{ +add_nuts_level(dat, geo_labels = "geo") +} +\arguments{ +\item{dat}{A data frame or tibble returned by \code{\link[=get_eurostat]{get_eurostat()}}.} + +\item{geo_labels}{A geographical label, defaults to \code{geo}.} +} +\value{ +a new numeric variable nuts_level with the numeric value of +NUTS level 0 (country), 1 (greater region), +2 (region), 3 (small region). +} +\description{ +Eurostat regional statistics contain country, and various +regional level information. In many cases, for example, when mapping, +it is useful to filter out national level data from NUTS2 level regional +data, for example. + +This function will be deprecated. Use the more comprehensive +\verb{[regions::validate_nuts_regions()]} instead. +} +\details{ +DEPRECATED FUNCTIONS FOR BACKWARD COMPATIBILITY +FUNCTIONS GIVE WARNING AND CALL APPROPRIATE regions FUNCTIONS +} +\examples{ + +dat <- data.frame( + geo = c("FR", "IE04", "DEB1C"), + values = c(1000, 23, 12) +) + +add_nuts_level(dat) +} +\seealso{ +\code{\link[regions:validate_nuts_regions]{regions::validate_nuts_regions()}} + +Other regions functions: +\code{\link{harmonize_geo_code}()}, +\code{\link{recode_to_nuts_2013}()}, +\code{\link{recode_to_nuts_2016}()}, +\code{\link{reexports}} +} +\author{ +Daniel Antal +} +\concept{regions functions} +\keyword{internal} diff --git a/man/check_access_to_data.Rd b/man/check_access_to_data.Rd new file mode 100755 index 00000000..836794f6 --- /dev/null +++ b/man/check_access_to_data.Rd @@ -0,0 +1,23 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/check_access_to_data.R +\name{check_access_to_data} +\alias{check_access_to_data} +\title{Check access to ec.europe.eu} +\usage{ +check_access_to_data() +} +\value{ +a logical. +} +\description{ +Check if R has access to resources at http://ec.europa.eu +} +\examples{ +\donttest{ +check_access_to_data() +} + +} +\author{ +Markus Kainu \href{mailto:markus.kainu@kapsi.fi}{markus.kainu@kapsi.fi} +} diff --git a/man/clean_eurostat_cache.Rd b/man/clean_eurostat_cache.Rd index 18d87996..7c6b1418 100755 --- a/man/clean_eurostat_cache.Rd +++ b/man/clean_eurostat_cache.Rd @@ -4,19 +4,29 @@ \alias{clean_eurostat_cache} \title{Clean Eurostat Cache} \usage{ -clean_eurostat_cache(cache_dir = NULL) +clean_eurostat_cache(cache_dir = NULL, config = FALSE) } \arguments{ \item{cache_dir}{A path to cache directory. If \code{NULL} (default) tries to clean default temporary cache directory.} + +\item{config}{Logical \code{TRUE/FALSE}. Should the cached path be deleted?} } \description{ Delete all .rds files from the eurostat cache directory. - See \code{\link{get_eurostat}} for more on cache. +See \code{\link[=get_eurostat]{get_eurostat()}} for more on cache. } \examples{ -clean_eurostat_cache() +\dontrun{ +clean_eurostat_cache() +} +} +\seealso{ +Other cache utilities: +\code{\link{set_eurostat_cache_dir}()} } \author{ -Przemyslaw Biecek, Leo Lahti, Janne Huovari and Markus Kainu \email{ropengov-forum@googlegroups.com} \url{http://github.com/ropengov/eurostat} +Przemyslaw Biecek, Leo Lahti, Janne Huovari, Markus Kainu and +Diego Hernangómez } +\concept{cache utilities} diff --git a/man/convert_time_col.Rd b/man/convert_time_col.Rd index 8cdd0ddf..5f48f6e0 100755 --- a/man/convert_time_col.Rd +++ b/man/convert_time_col.Rd @@ -2,14 +2,15 @@ % Please edit documentation in R/tidy_eurostat.R \name{convert_time_col} \alias{convert_time_col} -\title{Time Column Conversions} +\title{Time Column Conversions for data from new dissemination API} \usage{ convert_time_col(x, time_format) } \arguments{ -\item{x}{A time column (vector)} +\item{x}{A time column (vector) from a downloaded dataset} -\item{time_format}{see \code{\link{tidy_eurostat}}} +\item{time_format}{one of the following: \code{date}, \code{date_last}, or \code{num}. +See \code{\link[=tidy_eurostat]{tidy_eurostat()}} for more information.} } \description{ Internal function to convert time column. diff --git a/man/cut_to_classes.Rd b/man/cut_to_classes.Rd index 7e9d5770..eb34cc09 100755 --- a/man/cut_to_classes.Rd +++ b/man/cut_to_classes.Rd @@ -4,16 +4,23 @@ \alias{cut_to_classes} \title{Cuts the Values Column into Classes and Polishes the Labels} \usage{ -cut_to_classes(x, n = 5, style = "equal", manual = FALSE, - manual_breaks = NULL, decimals = 0, nodata_label = "No data") +cut_to_classes( + x, + n = 5, + style = "equal", + manual = FALSE, + manual_breaks = NULL, + decimals = 0, + nodata_label = "No data" +) } \arguments{ -\item{x}{A numeric vector, eg. \code{values} variable in data returned by \code{get_eurostat}} +\item{x}{A numeric vector, eg. \code{values} variable in data returned by +\code{\link[=get_eurostat]{get_eurostat()}}.} \item{n}{A numeric. number of classes/categories} -\item{style}{Chosen style: one of "fixed", "sd", "equal", "pretty", "quantile", "kmeans", "hclust", -"bclust", "fisher", or "jenks"} +\item{style}{chosen style: one of "fixed", "sd", "equal", "pretty", "quantile", "kmeans", "hclust", "bclust", "fisher", "jenks", "dpih", "headtails", "maximum", or "box"} \item{manual}{Logical. If manual breaks are being used} @@ -27,15 +34,29 @@ cut_to_classes(x, n = 5, style = "equal", manual = FALSE, a factor. } \description{ -Categorises a numeric vector into automatic or manually defined categories. -and polishes the labels ready for used in mapping with \code{merge_with_geodata} function and ggplot2. +Categorises a numeric vector into automatic or manually defined +categories and polishes the labels ready for used in mapping with \code{ggplot2}. } \examples{ - \dontrun{ - lp <- get_eurostat("nama_aux_lp") - lp$class <- cut_to_classes(lp$values, n=5, style="equal", decimals=1) - } +\dontshow{if (check_access_to_data()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\donttest{ +# lp <- get_eurostat("nama_aux_lp") +lp <- get_eurostat("nama_10_lp_ulc") +lp$class <- cut_to_classes(lp$values, n = 5, style = "equal", decimals = 1) +} +\dontshow{\}) # examplesIf} +} +\seealso{ +\code{\link[classInt:classIntervals]{classInt::classIntervals()}} + +Other helpers: +\code{\link{dic_order}()}, +\code{\link{eurotime2date}()}, +\code{\link{eurotime2num}()}, +\code{\link{harmonize_country_code}()}, +\code{\link{label_eurostat}()} } \author{ -Markus Kainu +Markus Kainu \href{mailto:markuskainu@gmail.com}{markuskainu@gmail.com} } +\concept{helpers} diff --git a/man/dic_order.Rd b/man/dic_order.Rd index 0744be59..3ba550f8 100755 --- a/man/dic_order.Rd +++ b/man/dic_order.Rd @@ -9,9 +9,9 @@ dic_order(x, dic, type) \arguments{ \item{x}{a variable (code or labelled) to get order for.} -\item{dic}{a name of the dictionary. Correspond a variable name in the -data_frame from \code{\link{get_eurostat}}. Can be also data_frame from -\code{\link{get_eurostat_dic}}.} +\item{dic}{a name of the dictionary. Correspond a variable name in the +data_frame from \code{\link[=get_eurostat]{get_eurostat()}}. Can be also data_frame from +\code{\link[=get_eurostat_dic]{get_eurostat_dic()}}.} \item{type}{a type of the x. Could be \code{code} or \code{label}.} } @@ -22,8 +22,21 @@ A numeric vector of orders. Orders the factor levels. } \details{ -Some variables, like classifications, have logical or conventional ordering. Eurostat data tables are nor neccessary ordered in this order. The function \code{dic_order} get the ordering from Eurostat classifications dictionaries. The function \code{\link{label_eurostat}} can also order factor levels of labels with argument \code{eu_order = TRUE}. +Some variables, like classifications, have logical or conventional +ordering. Eurostat data tables are nor necessary ordered in this order. +The function \code{\link[=dic_order]{dic_order()}} get the ordering from Eurostat classifications +dictionaries. The function \code{\link[=label_eurostat]{label_eurostat()}} can also order factor levels +of labels with argument \code{eu_order = TRUE}. +} +\seealso{ +Other helpers: +\code{\link{cut_to_classes}()}, +\code{\link{eurotime2date}()}, +\code{\link{eurotime2num}()}, +\code{\link{harmonize_country_code}()}, +\code{\link{label_eurostat}()} } \author{ -Przemyslaw Biecek, Leo Lahti, Janne Huovari and Markus Kainu \email{ropengov-forum@googlegroups.com} \url{http://github.com/ropengov/eurostat} +Przemyslaw Biecek, Leo Lahti, Janne Huovari and Markus Kainu } +\concept{helpers} diff --git a/man/eu_countries.Rd b/man/eu_countries.Rd index a82498dd..e7112547 100755 --- a/man/eu_countries.Rd +++ b/man/eu_countries.Rd @@ -7,14 +7,23 @@ \alias{efta_countries} \alias{eu_candidate_countries} \title{Countries and Country Codes} -\format{A data_frame: -\describe{ - \item{code}{Country code in the Eurostat database} - \item{name}{Country name in English} -}} +\format{ +A data_frame: +\itemize{ +\item \strong{code}: Country code in the Eurostat database. +\item \strong{name}: Country name in English. +\item \strong{label}: Country name in the Eurostat database. +} + +An object of class \code{tbl_df} (inherits from \code{tbl}, \code{data.frame}) with 19 rows and 3 columns. + +An object of class \code{tbl_df} (inherits from \code{tbl}, \code{data.frame}) with 4 rows and 3 columns. + +An object of class \code{tbl_df} (inherits from \code{tbl}, \code{data.frame}) with 7 rows and 3 columns. +} \source{ -\url{http://ec.europa.eu/eurostat/statistics-explained/index.php/Tutorial:Country_codes_and_protocol_order}, - \url{http://ec.europa.eu/eurostat/statistics-explained/index.php/Glossary:Euro_area} +\url{https://ec.europa.eu/eurostat/statistics-explained/index.php/Tutorial:Country_codes_and_protocol_order}, +\url{https://ec.europa.eu/eurostat/statistics-explained/index.php/Glossary:Euro_area} } \usage{ eu_countries @@ -29,4 +38,10 @@ eu_candidate_countries Countries and country codes in EU, Euro area, EFTA and EU candidate countries. } +\seealso{ +Other datasets: +\code{\link{eurostat_geodata_60_2016}}, +\code{\link{tgs00026}} +} +\concept{datasets} \keyword{datasets} diff --git a/man/eurostat-defunct.Rd b/man/eurostat-defunct.Rd new file mode 100644 index 00000000..ac0e69e1 --- /dev/null +++ b/man/eurostat-defunct.Rd @@ -0,0 +1,23 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/eurostat-defunct.R +\name{eurostat-defunct} +\alias{eurostat-defunct} +\alias{grepEurostatTOC} +\title{Defunct functions in eurostat} +\usage{ +grepEurostatTOC(...) +} +\arguments{ +\item{...}{Generic representation of old arguments} +} +\description{ +This list of defunct functions is maintained to document changes to eurostat functions in a +transparent manner. +} +\details{ +The following functions are defunct: + +\itemize{ +\item \code{\link{grepEurostatTOC}}: Use \code{search_eurostat} instead +} +} diff --git a/man/eurostat-package.Rd b/man/eurostat-package.Rd index f20ae381..19643fc5 100755 --- a/man/eurostat-package.Rd +++ b/man/eurostat-package.Rd @@ -6,28 +6,392 @@ \alias{eurostat} \title{R Tools for Eurostat open data} \description{ -Brief summary of the eurostat package +Tools to download data from the Eurostat database +\url{https://ec.europa.eu/eurostat} together with search and manipulation +utilities. } \details{ \tabular{ll}{ -Package: \tab eurostat\cr -Type: \tab Package\cr -Version: \tab See sessionInfo() or DESCRIPTION file\cr -Date: \tab 2014-2017\cr -License: \tab BSD_2_clause + LICENSE\cr -LazyLoad: \tab yes\cr + \tab \cr + \strong{Package} \tab eurostat \cr + \strong{Type} \tab Package \cr + \strong{Version} \tab 4.0.0 \cr + \strong{Date} \tab 2014-2023 \cr + \strong{License} \tab BSD_2_clause + file LICENSE \cr + \strong{LazyLoad} \tab yes \cr } +} +\section{Eurostat}{ +Eurostat website: \url{https://ec.europa.eu/eurostat} +Eurostat database: \url{https://ec.europa.eu/eurostat/web/main/data/database} + +Information about the data update schedule from Eurostat: +"Eurostat datasets are updated twice a day at 11:00 and 23:00 CET, if newer +data is available or for structural changes, for example for the +dimensions in the dataset. + +The Eurostat database always contains the latest version of the datasets, +meaning that there is no versioning or documentation of past versions of +the data." +} + +\section{Data source: Eurostat SDMX 2.1 Dissemination API}{ +Data is downloaded from Eurostat SDMX 2.1 API endpoint +as compressed TSV files that are transformed into tabular format. +See Eurostat documentation for more information: +\url{https://wikis.ec.europa.eu/display/EUROSTATHELP/API+SDMX+2.1+-+data+query} + +The new dissemination API replaces the old bulk download facility that was +used by Eurostat before October 2023 and by the eurostat R package versions +before 4.0.0. +See Eurostat documentation about the transition from Bulk Download to API +for more information about the differences between the old bulk download +facility and the data provided by the new API connection: +\url{https://wikis.ec.europa.eu/display/EUROSTATHELP/Transition+-+from+Eurostat+Bulk+Download+to+API} + +See especially the document Migrating_to_API_TSV.pdf that describes the +changes in TSV file format in new applications. + +For more information about SDMX 2.1, see SDMX standards: Section 7: +Guidelines for the use of web services, Version 2.1: +\url{https://sdmx.org/wp-content/uploads/SDMX_2-1_SECTION_7_WebServicesGuidelines.pdf} +} + +\section{Disclaimer: Availability of filtering functionalities}{ +Currently it only possible to download filtered data through API Statistics +(JSON API) when using \code{eurostat} package, although technically filtering +datasets downloaded through the SDMX Dissemination API is also supported by +Eurostat. We may support this feature in the future. In the meantime, if you +are interested in filtering Dissemination API data queries manually, please +consult the following Eurostat documentation: +\url{https://wikis.ec.europa.eu/display/EUROSTATHELP/API+SDMX+2.1+-+data+filtering} +} + +\section{Data source: Eurostat API Statistics (JSON API)}{ +Data is downloaded from Eurostat API Statistics. See Eurostat documentation +for more information about data queries in API Statistics +\url{https://wikis.ec.europa.eu/display/EUROSTATHELP/API+Statistics+-+data+query} + +This replaces the old JSON Web Services that was used by Eurostat before +February 2023 and by the eurostat R package versions before 3.7.13. +See Eurostat documentation about the migration from JSON web service to API +Statistics for more information about the differences between the old and +the new service: +\url{https://wikis.ec.europa.eu/display/EUROSTATHELP/API+Statistics+-+migrating+from+JSON+web+service+to+API+Statistics} + +For easily viewing which filtering options are available - in addition to +the default ones, time and language - Eurostat Web services Query builder +tool may be useful: +\url{https://ec.europa.eu/eurostat/web/query-builder} +} + +\section{Filtering datasets}{ +When using Eurostat API Statistics (JSON API), datasets can be filtered +before they are downloaded and saved in local memory. The general format +for filter parameters is \verb{=}. + +Filter parameters are optional but the used dimension codes must be present +in the data product that is being queried. Dimension codes can +vary between different data products so it may be useful to examine new +datasets in Eurostat data browser beforehand. However, most if not all +Eurostat datasets concern European countries and contain information that +was gathered at some point in time, so \code{geo} and \code{time} dimension codes +can usually be used. + +\verb{} and \verb{} are case-insensitive and they can be written +in lowercase or uppercase in the query. + +Parameters are passed onto the \code{eurostat} package functions \code{\link[=get_eurostat]{get_eurostat()}} +and \code{\link[=get_eurostat_json]{get_eurostat_json()}} as a list item. If an individual item contains +multiple items, as it often can be in the case of \code{geo} parameters and +other optional items, they must be in the form of a vector: \code{c("FI", "SE")}. +For examples on how to use these parameters, see function examples below. +\subsection{Time parameters}{ + +\code{time} and \code{time_period} address the same \code{TIME_PERIOD} dimension in the +dataset and can be used interchangeably. In the Eurostat documentation +it is stated that "Using more than one Time parameter in the same query +is not accepted", but practice has shown that actually Eurostat API allows +multiple \code{time} parameters in the same query. This makes it possible to +use R colon operator when writing queries, so \code{time = c(2015:2018)} +translates to \verb{&time=2015&time=2016&time=2017&time=2018}. + +The only exception +to this is when the queried dataset contains e.g. quarterly data and +\code{TIME_PERIOD} is saved as \code{2015-Q1}, \code{2015-Q2} etc. Then it is possible +to use \code{time=2015-Q1&time=2015-Q2} style in the query URL, but this makes it +unfeasible to use the colon operator and requires a lot of manual typing. + +Because of this, it is useful to know about other time parameters as well: +\itemize{ +\item \code{untilTimePeriod}: return dataset items from the oldest record up until the +set time, for example "all data until 2000": \code{untilTimePeriod = 2000} +\item \code{sinceTimePeriod}: return dataset items starting from set time, for example +"all datastarting from 2008": \code{sinceTimePeriod = 2008} +\item \code{lastTimePeriod}: starting from the most recent time period, how many +preceding time periods should be returned? For example 10 most +recent observations: \code{lastTimePeriod = 10} +} + +Using both \code{untilTimePeriod} and \code{sinceTimePeriod} parameters in the same +query is allowed, making the usage of the R colon operator unnecessary. +In the case of quarterly data, using \code{untilTimePeriod} and \code{sinceTimePeriod} +parameters also works, as opposed to the colon operator, so it is generally +safer to use them as well. +} + +\subsection{Other dimensions}{ + +In \code{\link[=get_eurostat_json]{get_eurostat_json()}} examples \code{nama_10_gdp} dataset is filtered with +two additional filter parameters: +\itemize{ +\item \code{na_item = "B1GQ"} +\item \code{unit = "CLV_I10"} +} + +Filters like these are most likely unique to the \code{nama_10_gdp} dataset +(or other datasets within the same domain) and should +not be used with others dataset without user discretion. +By using \code{\link[=label_eurostat]{label_eurostat()}} we know that \code{"B1GQ"} stands for +"Gross domestic product at market prices" and +\code{"CLV_I10"} means "Chain linked volumes, index 2010=100". + +Different dimension codes can be translated to a natural language by using +the \code{\link[=get_eurostat_dic]{get_eurostat_dic()}} function, which returns labels for individual +dimension items such as \code{na_item} and \code{unit}, as opposed to +\code{\link[=label_eurostat]{label_eurostat()}} which does it for whole datasets. For example, the +parameter \code{na_item} stands for "National accounts indicator (ESA 2010)" and +\code{unit} stands for "Unit of measure". +} + +\subsection{Language}{ + +All datasets have metadata available in English, French and German. If no +parameter is given, the labels are returned in English. + +Example: +\itemize{ +\item \code{lang = "fr"} +} +} + +\subsection{More information}{ + +For more information about data filtering see Eurostat documentation +on API Statistics: +\url{https://wikis.ec.europa.eu/display/EUROSTATHELP/API+Statistics+-+data+query#APIStatisticsdataquery-TheparametersdefinedintheRESTrequest} +} +} + +\section{Data source: Eurostat Table of Contents}{ +The Eurostat Table of Contents (TOC) is downloaded from +\url{https://ec.europa.eu/eurostat/api/dissemination/catalogue/toc/txt?lang=en} +(default) or from French or German language variants: +\url{https://ec.europa.eu/eurostat/api/dissemination/catalogue/toc/txt?lang=fr} +\url{https://ec.europa.eu/eurostat/api/dissemination/catalogue/toc/txt?lang=de} + +See Eurostat documentation on TOC items: +\url{https://wikis.ec.europa.eu/display/EUROSTATHELP/API+-+Detailed+guidelines+-+Catalogue+API+-+TOC} +} + +\section{Data source: GISCO - General Copyright}{ +"Eurostat's general copyright notice and licence policy is applicable and +can be consulted here: +\url{https://ec.europa.eu/eurostat/about-us/policies/copyright} -R Tools for Eurostat Open Data +Please also be aware of the European Commission's general conditions: +\url{https://commission.europa.eu/legal-notice_en} + +Moreover, there are specific provisions applicable to some of the following +datasets available for downloading. The download and usage of these data +is subject to their acceptance: +\itemize{ +\item Administrative Units / Statistical Units +\item Population distribution / Demography +\item Transport Networks +\item Land Cover +\item Elevation (DEM)" +} + +Of the abovementioned datasets, Administrative Units / Statistical Units +is applicable if the user wants to draw maps with borders provided by +GISCO / EuroGeographics. +} + +\section{Data source: GISCO - Administrative Units / Statistical Units}{ +The following copyright notice is provided for end user convenience. +Please check up-to-date copyright information from the GISCO website: +\href{https://ec.europa.eu/eurostat/web/gisco/geodata/reference-data/administrative-units-statistical-units}{GISCO: Geographical information and maps - Administrative units/statistical units} + +"In addition to the \href{https://ec.europa.eu/eurostat/web/main/about/policies/copyright}{general copyright and licence policy} applicable to the whole Eurostat website, the following +specific provisions apply to the datasets you are downloading. The download +and usage of these data is subject to the acceptance of the following +clauses: +\enumerate{ +\item The Commission agrees to grant the non-exclusive and not transferable +right to use and process the Eurostat/GISCO geographical data downloaded +from this page (the "data"). +\item The permission to use the data is granted on condition that: +\enumerate{ +\item the data will not be used for commercial purposes; +\item the source will be acknowledged. A copyright notice, as specified +below, will have to be visible on any printed or electronic publication +using the data downloaded from this page." +} +} +\subsection{Copyright notice}{ + +When data downloaded from this page is used in any printed or electronic +publication, in addition to any other provisions applicable to the whole +Eurostat website, data source will have to be acknowledged in the legend of +the map and in the introductory page of the publication with the following +copyright notice: + +EN: © EuroGeographics for the administrative boundaries + +FR: © EuroGeographics pour les limites administratives + +DE: © EuroGeographics bezüglich der Verwaltungsgrenzen + +For publications in languages other than English, French or German, the +translation of the copyright notice in the language of the publication shall +be used. + +If you intend to use the data commercially, please contact EuroGeographics +for information regarding their licence agreements." +} +} + +\section{Eurostat: Copyright notice and free re-use of data}{ +The following copyright notice is provided for end user convenience. +Please check up-to-date copyright information from the eurostat website: +\url{https://ec.europa.eu/eurostat/about-us/policies/copyright} + +"(c) European Union, 1995 - today + +Eurostat has a policy of encouraging free re-use of its data, both for +non-commercial and commercial purposes. All statistical data, metadata, +content of web pages or other dissemination tools, official publications +and other documents published on its website, with the exceptions listed +below, can be reused without any payment or written licence provided that: +\itemize{ +\item the source is indicated as Eurostat; +\item when re-use involves modifications to the data or text, this must be +stated clearly to the end user of the information." +} + +For exceptions to the abovementioned principles see +\href{https://ec.europa.eu/eurostat/about-us/policies/copyright}{Eurostat website} +} + +\section{Citing Eurostat data}{ +For citing datasets, use \code{\link[=get_bibentry]{get_bibentry()}} to build a bibliography that +is suitable for your reference manager of choice. + +When using Eurostat data in other contexts than academic publications that +in-text citations or footnotes/endnotes, the following guidelines may be +helpful: +\itemize{ +\item The origin of the data should always be mentioned as "Source: Eurostat". +\item The online dataset codes(s) should also be provided in order to ensure +transparency and facilitate access to the Eurostat data and related +methodological information. For example: +"Source: Eurostat (online data code: namq_10_gdp)" +\item Online publications (e.g. web pages, PDF) should include a clickable +link to the dataset using the bookmark functionality available in the +Eurostat data browser. +} + +It should be avoided to associate different entities (e.g. Eurostat, +National Statistical Offices, other data providers) to the same dataset or +indicator without specifying the role of each of them in the treatment of +data. + +See also section "Eurostat: Copyright notice and free re-use of data" +in \code{\link[=get_eurostat]{get_eurostat()}} documentation. +} + +\section{Strategies for handling large datasets more efficiently}{ +Most Eurostat datasets are relatively manageable, at least on a machine +with 16 GB of RAM. The largest dataset in Eurostat database, at the time +of writing this, had 148362539 (148 million) values, which results in an +object with 148 million rows in tidy data (long) format. The test machine +with 16 GB of RAM was able to handle the second largest dataset in the +database with 91 million values (rows). + +There are still some methods to make data fetching +functions perform faster: +\itemize{ +\item turn caching off: \code{get_eurostat(cache = FALSE)} +\item turn cache compression off (may result in rather large cache files!): +\code{get_eurostat(compress_file = FALSE)} +\item if you want faster caching with manageable file sizes, use stringsAsFactors: +\code{get_eurostat(cache = TRUE, compress_file = TRUE, stringsAsFactors = TRUE)} +\item Use faster data.table functions: \code{get_eurostat(use.data.table = TRUE)} +\item Keep column processing to a minimum: +\code{get_eurostat(time_format = "raw", type = "code")} etc. +\item Read \code{get_eurostat()} function documentation carefully so you understand +what different arguments do +\item Filter the dataset so that you fetch only the parts you need! +} +} + +\section{regions functions}{ + +For working with sub-national statistics the basic functions of the +regions package are imported \url{https://regions.dataobservatory.eu/}. } + \examples{ library(eurostat) } \references{ -See citation("eurostat") -\url{https://ropengov.github.io/eurostat} +See \code{citation("eurostat")}: + +\if{html}{\out{
    }}\preformatted{Kindly cite the eurostat R package as follows: + + Lahti L., Huovari J., Kainu M., and Biecek P. (2017). Retrieval and + analysis of Eurostat open data with the eurostat package. The R + Journal 9(1), pp. 385-392. doi: 10.32614/RJ-2017-019 + +A BibTeX entry for LaTeX users is + + @Article\{10.32614/RJ-2017-019, + title = \{Retrieval and Analysis of Eurostat Open Data with the eurostat Package\}, + author = \{Leo Lahti and Janne Huovari and Markus Kainu and Przemyslaw Biecek\}, + journal = \{The R Journal\}, + volume = \{9\}, + number = \{1\}, + pages = \{385--392\}, + year = \{2017\}, + doi = \{10.32614/RJ-2017-019\}, + url = \{https://doi.org/10.32614/RJ-2017-019\}, + \} + + Lahti, L., Huovari J., Kainu M., Biecek P., Hernangomez D., Antal D., + and Kantanen P. (2023). eurostat: Tools for Eurostat Open Data + [Computer software]. R package version 4.0.0. + https://github.com/rOpenGov/eurostat + +A BibTeX entry for LaTeX users is + + @Misc\{eurostat, + title = \{eurostat: Tools for Eurostat Open Data\}, + author = \{Leo Lahti and Janne Huovari and Markus Kainu and Przemyslaw Biecek and Diego Hernangomez and Daniel Antal and Pyry Kantanen\}, + url = \{https://github.com/rOpenGov/eurostat\}, + type = \{Computer software\}, + year = \{2023\}, + note = \{R package version 4.0.0\}, + \} +}\if{html}{\out{
    }} + +When citing data downloaded from Eurostat, see section "Citing Eurostat data" +in \code{\link[=get_eurostat]{get_eurostat()}} documentation. +} +\seealso{ +\code{help("regions")}, \url{https://regions.dataobservatory.eu/} } \author{ -Leo Lahti, Janne Huovari, Markus Kainu, Przemyslaw Biecek \email{ropengov-forum@googlegroups.com} \url{https://ropengov.github.io/eurostat} +Leo Lahti, Janne Huovari, Markus Kainu, Przemyslaw Biecek } \keyword{package} diff --git a/man/eurostat_geodata_60_2016.Rd b/man/eurostat_geodata_60_2016.Rd index 9c75d75e..fcce0288 100755 --- a/man/eurostat_geodata_60_2016.Rd +++ b/man/eurostat_geodata_60_2016.Rd @@ -3,25 +3,147 @@ \docType{data} \name{eurostat_geodata_60_2016} \alias{eurostat_geodata_60_2016} -\title{Geospatial data of Europe from Gisco in 1:60 million scale from year 2016} -\format{sf -\describe{ - \item{id}{Country code in the Eurostat database} - \item{CNTRY_CODE}{Country code} - \item{NUTS_NAME}{NUTS name in local language} - \item{LEVL_CODE}{NUTS code} - \item{FID}{Country code} - \item{NUTS_ID}{NUTS code} - \item{geometry}{geospatial information} - \item{geo}{NUTS code} -}} -\source{ -\url{http://ec.europa.eu/eurostat/web/gisco/geodata/reference-data/administrative-units-statistical-units} +\title{Geospatial data of Europe from GISCO in 1:60 million scale from +year 2016} +\format{ +sf object } -\usage{ -eurostat_geodata_60_2016 +\source{ +Data source: Eurostat via \code{\link[giscoR:gisco_get_nuts]{giscoR::gisco_get_nuts()}}. + +© EuroGeographics for the administrative boundaries + +Data downloaded from: +\url{https://ec.europa.eu/eurostat/web/gisco/geodata/reference-data/administrative-units-statistical-units} } \description{ -Geospatial data of Europe from Gisco in 1:60 million scale from year 2016 +Geospatial data of Europe from GISCO in 1:60 million scale +from year 2016 +} +\details{ +The dataset contains 2016 observations (rows) and 12 variables (columns). + +The object contains the following columns: +\itemize{ +\item \strong{id}: JSON id code, the same as \strong{NUTS_ID}. See \strong{NUTS_ID} below for +further clarification. +\item \strong{LEVL_CODE}: NUTS level code: 0 (national level), 1 (major +socio-economic regions), 2 (basic regions for the application of regional +policies) or 3 (small regions). +\item \strong{NUTS_ID}: NUTS ID code, consisting of country code and numbers (1 for +NUTS 1, 2 for NUTS 2 and 3 for NUTS 3) +\item \strong{CNTR_CODE}: Country code: two-letter ISO code (ISO 3166 alpha-2), except +in the case of Greece (EL). +\item \strong{NAME_LATN}: NUTS name in local language, transliterated to Latin script +\item \strong{NUTS_NAME}: NUTS name in local language, in local script. +\item \strong{MOUNT_TYPE}: Mountain typology for NUTS 3 regions. +\itemize{ +\item 1: "where more than 50 \% of the surface is covered by topographic +mountain areas" +\item 2: "in which more than 50 \% of the regional population lives in +topographic mountain areas" +\item 3: "where more than 50 \% of the surface is covered by topographic +mountain areas and where more than 50 \% of the regional population lives +in these mountain areas" +\item 4: non-mountain region / other region +\item 0: no classification provided (e.g. in the case of NUTS 1 and NUTS 2 and +non-EU countries) +} +\item \strong{URBN_TYPE}: Urban-rural typology for NUTS 3 regions. +\itemize{ +\item 1: predominantly urban region +\item 2: intermediate region +\item 3: predominantly rural region +\item 0: no classification provided (e.g. in the case of NUTS 1 and NUTS 2 +regions) +} +\item \strong{COAST_TYPE}: Coastal typology for NUTS 3 regions. +\itemize{ +\item 1: coastal (on coast) +\item 2: coastal (>= 50\% of population living within 50km of the coastline) +\item 3: non-coastal region +\item 0: no classification provided (e.g. in the case of NUTS 1 and NUTS 2 +regions) +} +\item \strong{FID}: Same as NUTS_ID. +\item \strong{geo}: Same as NUTS_ID, added for for easier joins with dplyr. However, +it is recommended to use other identical fields for this purpose. +\item \strong{geometry}: geospatial information. +} + +Dataset updated: 2023-06-29. For a more recent version, please use +\code{\link[giscoR:gisco_get_nuts]{giscoR::gisco_get_nuts()}} function. +} +\examples{ + +eurostat_geodata_60_2016 <- eurostat::eurostat_geodata_60_2016 + +# Manipulate and plot +if (require(sf)) { + library(sf) + # Filter NUTS3 from select countries like in a regular data frame + example_nuts <- subset(eurostat_geodata_60_2016, LEVL_CODE == 3 & + CNTR_CODE \%in\% c("DK", "DE", "PL")) + + plot(example_nuts["CNTR_CODE"]) +} + +} +\references{ +The following copyright notice is provided for end user convenience. +Please check up-to-date copyright information from the eurostat website: +\href{https://ec.europa.eu/eurostat/web/gisco/geodata/reference-data/administrative-units-statistical-units}{GISCO: Geographical information and maps - Administrative units/statistical units} + +"In addition to the +\href{https://ec.europa.eu/eurostat/web/main/about/policies/copyright}{general copyright and licence policy} +applicable to the whole Eurostat website, the following +specific provisions apply to the datasets you are downloading. The download +and usage of these data is subject to the acceptance of the following +clauses: +\enumerate{ +\item The Commission agrees to grant the non-exclusive and not transferable +right to use and process the Eurostat/GISCO geographical data downloaded +from this page (the "data"). +\item The permission to use the data is granted on condition that: +\enumerate{ +\item the data will not be used for commercial purposes; +\item the source will be acknowledged. A copyright notice, as specified +below, will have to be visible on any printed or electronic publication +using the data downloaded from this page. +} +} +\subsection{Copyright notice}{ + +When data downloaded from this page is used in any printed or electronic +publication, in addition to any other provisions applicable to the whole +Eurostat website, data source will have to be acknowledged in the legend of +the map and in the introductory page of the publication with the following +copyright notice: + +EN: © EuroGeographics for the administrative boundaries + +FR: © EuroGeographics pour les limites administratives + +DE: © EuroGeographics bezüglich der Verwaltungsgrenzen + +For publications in languages other than English, French or German, the +translation of the copyright notice in the language of the publication shall +be used. + +If you intend to use the data commercially, please contact EuroGeographics +for information regarding their licence agreements." +} +} +\seealso{ +\code{\link[giscoR:gisco_get_nuts]{giscoR::gisco_get_nuts()}} and +\href{https://ec.europa.eu/eurostat/web/products-manuals-and-guidelines/-/ks-gq-18-008}{Eurostat. (2019). Methodological manual on territorial typologies -- 2018 edition. Manuals and guidelines.} + +Other datasets: +\code{\link{eu_countries}}, +\code{\link{tgs00026}} + +Other geospatial: +\code{\link{get_eurostat_geospatial}()} } -\keyword{datasets} +\concept{datasets} +\concept{geospatial} diff --git a/man/eurotime2date.Rd b/man/eurotime2date.Rd index 35e31903..06a925c7 100755 --- a/man/eurotime2date.Rd +++ b/man/eurotime2date.Rd @@ -2,40 +2,98 @@ % Please edit documentation in R/eurotime2date.R \name{eurotime2date} \alias{eurotime2date} -\title{Date Conversion from Eurostat Time Format} +\title{Date Conversion from New Eurostat Time Format} \usage{ eurotime2date(x, last = FALSE) } \arguments{ \item{x}{a charter string with time information in Eurostat time format.} -\item{last}{a logical. If \code{FALsE} (default) the date is -the first date of the period (month, quarter or year). If \code{TRUE} +\item{last}{a logical. If \code{FALSE} (default) the date is +the first date of the period (month, quarter or year). If \code{TRUE} the date is the last date of the period.} } \value{ -an object of class \code{\link{Date}}. +an object of class \code{\link[=Date]{Date()}}. } \description{ Date conversion from Eurostat time format. A function to -convert Eurostat time values to objects of class \code{\link{Date}} +convert Eurostat time values to objects of class \code{\link[=Date]{Date()}} representing calendar dates. } +\details{ +Available patterns are YYYY (year), YYYY-SN (semester), YYYY-QN (quarter), +YYYY-MM (month), YYYY-WNN (week) and YYYY-MM-DD (day). +} \examples{ +\dontshow{if (check_access_to_data()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\donttest{ +na_q <- get_eurostat("namq_10_pc", time_format = "raw") +na_q$TIME_PERIOD <- eurotime2date(x = na_q$TIME_PERIOD) +unique(na_q$TIME_PERIOD) +} + \dontrun{ - na_q <- get_eurostat("namq_10_pc", time_format = "raw") - na_q$time <- eurotime2date(x = na_q$time) - - un <- get_eurostat("une_rt_m", time_format = "raw") - un$time <- eurotime2date(x = un$time) - - na_a <- get_eurostat("nama_10_pc", time_format = "raw") - na_a$time <- eurotime2date(x = na_a$time) - - eur_d <- get_eurostat("ert_bil_eur_d", time_format = "raw") - eur_d$time <- eurotime2date(x = eur_d$time) - } +# Test for weekly data +get_eurostat( + id = "lfsi_abs_w", + select_time = c("W"), + time_format = "date" + ) +} +\dontshow{\}) # examplesIf} +} +\references{ +See \code{citation("eurostat")}: + +\if{html}{\out{
    }}\preformatted{# Kindly cite the eurostat R package as follows: +# +# Lahti L., Huovari J., Kainu M., and Biecek P. (2017). Retrieval and +# analysis of Eurostat open data with the eurostat package. The R +# Journal 9(1), pp. 385-392. doi: 10.32614/RJ-2017-019 +# +# A BibTeX entry for LaTeX users is +# +# @Article\{10.32614/RJ-2017-019, +# title = \{Retrieval and Analysis of Eurostat Open Data with the eurostat Package\}, +# author = \{Leo Lahti and Janne Huovari and Markus Kainu and Przemyslaw Biecek\}, +# journal = \{The R Journal\}, +# volume = \{9\}, +# number = \{1\}, +# pages = \{385--392\}, +# year = \{2017\}, +# doi = \{10.32614/RJ-2017-019\}, +# url = \{https://doi.org/10.32614/RJ-2017-019\}, +# \} +# +# Lahti, L., Huovari J., Kainu M., Biecek P., Hernangomez D., Antal D., +# and Kantanen P. (2023). eurostat: Tools for Eurostat Open Data +# [Computer software]. R package version 4.0.0. +# https://github.com/rOpenGov/eurostat +# +# A BibTeX entry for LaTeX users is +# +# @Misc\{eurostat, +# title = \{eurostat: Tools for Eurostat Open Data\}, +# author = \{Leo Lahti and Janne Huovari and Markus Kainu and Przemyslaw Biecek and Diego Hernangomez and Daniel Antal and Pyry Kantanen\}, +# url = \{https://github.com/rOpenGov/eurostat\}, +# type = \{Computer software\}, +# year = \{2023\}, +# note = \{R package version 4.0.0\}, +# \} +}\if{html}{\out{
    }} +} +\seealso{ +\code{\link[lubridate:ymd]{lubridate::ymd()}} + +Other helpers: +\code{\link{cut_to_classes}()}, +\code{\link{dic_order}()}, +\code{\link{eurotime2num}()}, +\code{\link{harmonize_country_code}()}, +\code{\link{label_eurostat}()} } \author{ -Janne Huovari \email{janne.huovari@ptt.fi} +Janne Huovari \href{mailto:janne.huovari@ptt.fi}{janne.huovari@ptt.fi} } +\concept{helpers} diff --git a/man/eurotime2num.Rd b/man/eurotime2num.Rd index a5f01768..5e408d4d 100755 --- a/man/eurotime2num.Rd +++ b/man/eurotime2num.Rd @@ -10,28 +10,35 @@ eurotime2num(x) \item{x}{a charter string with time information in Eurostat time format.} } \value{ -see \code{\link{as.numeric}}. +see \code{\link[=as.numeric]{as.numeric()}}. } \description{ A conversion of a Eurostat time format to numeric. } \details{ -Bi-annual, quarterly and monthly data is presented as fraction of - the year in beginning of the period. Conversion of daily data is not - supported. +Bi-annual (semester), quarterly, monthly and weekly data can be presented as +a fraction of the year in beginning of the period. Conversion of daily data +is not supported. } \examples{ -\dontrun{ - na_q <- get_eurostat("namq_10_pc", time_format = "raw") - na_q$time <- eurotime2num(x = na_q$time) - - un <- get_eurostat("une_rt_m", time_format = "raw") - un$time <- eurotime2num(x = un$time) - - na_a <- get_eurostat("nama_10_pc", time_format = "raw") - na_a$time <- eurotime2num(x = na_a$time) - } +\dontshow{if (check_access_to_data()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\donttest{ +na_q <- get_eurostat("namq_10_pc", time_format = "raw") +na_q$TIME_PERIOD <- eurotime2num(x = na_q$TIME_PERIOD) + +unique(na_q$TIME_PERIOD) +} +\dontshow{\}) # examplesIf} +} +\seealso{ +Other helpers: +\code{\link{cut_to_classes}()}, +\code{\link{dic_order}()}, +\code{\link{eurotime2date}()}, +\code{\link{harmonize_country_code}()}, +\code{\link{label_eurostat}()} } \author{ -Janne Huovari \email{janne.huovari@ptt.fi} +Janne Huovari \href{mailto:janne.huovari@ptt.fi}{janne.huovari@ptt.fi}, Pyry Kantanen } +\concept{helpers} diff --git a/man/figures/logo.png b/man/figures/logo.png new file mode 100644 index 00000000..4b554470 Binary files /dev/null and b/man/figures/logo.png differ diff --git a/man/fixity_checksum.Rd b/man/fixity_checksum.Rd new file mode 100644 index 00000000..74b426b2 --- /dev/null +++ b/man/fixity_checksum.Rd @@ -0,0 +1,57 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utils.R +\name{fixity_checksum} +\alias{fixity_checksum} +\title{Calculate a fixity checksum for an object} +\source{ +https://www.dpconline.org/handbook/technical-solutions-and-tools/fixity-and-checksums +} +\usage{ +fixity_checksum(data_object, algorithm = "md5") +} +\arguments{ +\item{data_object}{A dataset downloaded with some eurostat package function.} + +\item{algorithm}{Algorithm to use when calculating a checksum for a dataset. +Default is 'md5', but can be any supported algorithm in digest function.} +} +\description{ +Uses a hash function (md5) on an object and calculates a digest of the object +in the form of a character string. +} +\details{ +“Fixity, in the preservation sense, means the assurance that a digital file +has remained unchanged, i.e. fixed.” (Bailey, 2014). In practice, fixity +can most easily be established by calculating a checksum for the data object +that changes if anything in the data object has changed. What we use as a +checksum here is by default calculated with md5 hash algorithm. It is +possible to use other algorithms supported by the imported digest function, +see function documentation. + +In the case of big objects with millions of rows of data calculating a +checksum can take a bit longer and require some amount of RAM to be +available. Selecting another algorithm might perform faster and/or more +efficiently. Whichever algorithm you are using, please make sure to report +it transparently in your work for transparency and ensuring replicability. + +This function takes the whole data object as an input, meaning that +everything counts when calculating the fixity checksum. If the dataset +column names are labeled, if the data itself is labeled, if stringsAsFactors +is TRUE, if flags are removed or kept, if data is somehow edited... all these +affect the calculated checksum. It is advisable to calculate the checksum +immediately after downloading the data, before adding any labels or doing +other mutating operations. If you are using other arguments than the default +ones when downloading data, it is also good to report the exact arguments +used. + +This implementation fulfills the level 1 requirement of National Digital +Stewardship Alliance (NDSA) preservation levels by creating "fixity info +if it wasn’t provided with the content". In the current version of the +package, fixity information has to be created manually and is at the +responsibility of the user. +} +\seealso{ +\code{\link[digest:digest]{digest::digest()}} +} +\keyword{internal} +\keyword{utilities} diff --git a/man/get_bibentry.Rd b/man/get_bibentry.Rd new file mode 100755 index 00000000..76a800be --- /dev/null +++ b/man/get_bibentry.Rd @@ -0,0 +1,77 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/get_bibentry.R +\name{get_bibentry} +\alias{get_bibentry} +\title{Create A Data Bibliography} +\usage{ +get_bibentry(code, keywords = NULL, format = "Biblatex", lang = "en") +} +\arguments{ +\item{code}{A Eurostat data code or a vector of Eurostat data codes as +character or factor.} + +\item{keywords}{A list of keywords to be added to the entries. Defaults +to \code{NULL}.} + +\item{format}{Default is \code{'Biblatex'}, alternatives are \code{'bibentry'} +or \code{'Bibtex'} (not case sensitive)} + +\item{lang}{2-letter language code, default is "\code{en}" (English), other +options are "\code{fr}" (French) and "\code{de}" (German). Used for labeling datasets.} +} +\value{ +a bibentry, Bibtex or Biblatex object. +} +\description{ +Creates a bibliography from selected Eurostat data files, +including last Eurostat update, URL access data, and optional keywords +set by the user. +} +\section{Citing Eurostat data}{ +For citing datasets, use \code{\link[=get_bibentry]{get_bibentry()}} to build a bibliography that +is suitable for your reference manager of choice. + +When using Eurostat data in other contexts than academic publications that +in-text citations or footnotes/endnotes, the following guidelines may be +helpful: +\itemize{ +\item The origin of the data should always be mentioned as "Source: Eurostat". +\item The online dataset codes(s) should also be provided in order to ensure +transparency and facilitate access to the Eurostat data and related +methodological information. For example: +"Source: Eurostat (online data code: namq_10_gdp)" +\item Online publications (e.g. web pages, PDF) should include a clickable +link to the dataset using the bookmark functionality available in the +Eurostat data browser. +} + +It should be avoided to associate different entities (e.g. Eurostat, +National Statistical Offices, other data providers) to the same dataset or +indicator without specifying the role of each of them in the treatment of +data. + +See also section "Eurostat: Copyright notice and free re-use of data" +in \code{\link[=get_eurostat]{get_eurostat()}} documentation. +} + +\examples{ +\dontshow{if (check_access_to_data()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\dontrun{ + my_bibliography <- get_bibentry( + code = c("tran_hv_frtra", "tec00001"), + keywords = list( + c("transport", "freight", "multimodal data", "GDP"), + c("economy and finance", "annual", "national accounts", "GDP") + ), + format = "Biblatex" + ) + my_bibliography +} +\dontshow{\}) # examplesIf} +} +\seealso{ +\link[utils:bibentry]{utils::bibentry} \link[RefManageR:toBiblatex]{RefManageR::toBiblatex} +} +\author{ +Daniel Antal, Przemyslaw Biecek +} diff --git a/man/get_eurostat.Rd b/man/get_eurostat.Rd index 4a09f41d..1e0ee2a8 100755 --- a/man/get_eurostat.Rd +++ b/man/get_eurostat.Rd @@ -2,144 +2,416 @@ % Please edit documentation in R/get_eurostat.R \name{get_eurostat} \alias{get_eurostat} -\title{Read Eurostat Data} +\title{Get Eurostat Data} \usage{ -get_eurostat(id, time_format = "date", filters = "none", - type = "code", select_time = NULL, cache = TRUE, - update_cache = FALSE, cache_dir = NULL, compress_file = TRUE, - stringsAsFactors = default.stringsAsFactors(), keepFlags = FALSE, - ...) +get_eurostat( + id, + time_format = "date", + filters = NULL, + type = "code", + select_time = NULL, + lang = "en", + cache = TRUE, + update_cache = FALSE, + cache_dir = NULL, + compress_file = TRUE, + stringsAsFactors = FALSE, + keepFlags = FALSE, + use.data.table = FALSE, + ... +) } \arguments{ -\item{id}{A code name for the dataset of interest. -See \code{\link{search_eurostat}} or details for how to get code.} - -\item{time_format}{a string giving a type of the conversion of the time -column from the eurostat format. A "date" (default) convers to -a \code{\link{Date}} with a first date of the period. -A "date_last" convers to a \code{\link{Date}} with - a last date of the period. A "num" convers to a numeric and "raw" - does not do conversion. See \code{\link{eurotime2date}} and - \code{\link{eurotime2num}}.} - -\item{filters}{a "none" (default) to get a whole dataset or a named list of -filters to get just part of the table. Names of list objects are -Eurostat variable codes and values are vectors of observation codes. -If \code{NULL} the whole -dataset is returned via API. More on details. See more on filters and -limitations per query via API from for -\code{\link{get_eurostat_json}}.} - -\item{type}{A type of variables, "code" (default) or "label".} - -\item{select_time}{a character symbol for a time frequence or NULL, +\item{id}{A unique identifier / code for the dataset of interest. If code is not +known \code{\link[=search_eurostat]{search_eurostat()}} function can be used to search Eurostat table +of contents.} + +\item{time_format}{a string giving a type of the conversion of the time column from the +eurostat format. The default argument "\code{date}" converts to a \code{\link[=Date]{Date()}} class +with the date being the first day of the period. A "\code{date_last}" argument +converts the dataset date to a \code{\link[=Date]{Date()}} class object with the difference +that the exact date is the last date of the period. Period can be year, +semester (half year), quarter, month, or week (See \code{\link[=eurotime2date]{eurotime2date()}} for +more information). +Argument "\code{num}" converts the date into a numeric (integer) meaning that +the first day of the year 2000 is close to 2000.01 and the last day of the +year is close to 2000.99 (see \code{\link[=eurotime2num]{eurotime2num()}} for more information). +Using the argument "\code{raw}" preserves the dates as they were in the original +Eurostat data.} + +\item{filters}{A named list of filters. Names of list objects are Eurostat +variable codes and values are vectors of observation codes. If \code{NULL} +(default) the whole dataset is returned. See details for more information +on filters and limitations per query.} + +\item{type}{A type of variables, "\code{code}" (default), "\code{label}" or "\code{both}". +The parameter "\code{both}" will return a data_frame with named vectors, +labels as values and codes as names.} + +\item{select_time}{a character symbol for a time frequency or \code{NULL}, which is used by default as most datasets have just one time frequency. For datasets with multiple time -frequencies, select the desired time format with: - Y = annual, S = semi-annual, Q = quarterly, M = monthly. -For all frequencies in same data frame \code{time_format = "raw"} -should be used.} +frequencies, select one or more of the desired frequencies with: +"Y" (or "A") = annual, "S" = semi-annual / semester, "Q" = quarterly, +"M" = monthly, "W" = weekly. For all frequencies in same data +frame \code{time_format = "raw"} should be used.} + +\item{lang}{2-letter language code, default is "\code{en}" (English), other +options are "\code{fr}" (French) and "\code{de}" (German). Used for labeling datasets.} -\item{cache}{a logical whether to do caching. Default is \code{TRUE}. Affects -only queries from the bulk download facility.} +\item{cache}{a logical whether to do caching. Default is \code{TRUE}.} -\item{update_cache}{a locigal whether to update cache. Can be set also with -options(eurostat_update = TRUE)} +\item{update_cache}{a logical whether to update cache. Can be set also with +\code{options(eurostat_update = TRUE)}} -\item{cache_dir}{a path to a cache directory. The directory have to exist. -The \code{NULL} (default) uses and creates -'eurostat' directory in the temporary directory from -\code{\link{tempdir}}. Directory can also be set with -\code{option} eurostat_cache_dir.} +\item{cache_dir}{a path to a cache directory. \code{NULL} (default) uses and creates +'eurostat' directory in the temporary directory defined by base R +\code{\link[=tempdir]{tempdir()}} function. The user can set the cache directory to an existing +directory by using this argument. The cache directory can also be set with +\code{\link[=set_eurostat_cache_dir]{set_eurostat_cache_dir()}} function.} -\item{compress_file}{a logical whether to compress the -RDS-file in caching. Default is \code{TRUE}.} +\item{compress_file}{a logical whether to compress the RDS-file in caching. Default is \code{TRUE}.} -\item{stringsAsFactors}{if \code{TRUE} (the default) variables are -converted to factors in original Eurostat order. If \code{FALSE} -they are returned as a character.} +\item{stringsAsFactors}{if \code{TRUE} (the default) variables are converted to factors in the original +Eurostat order. If \code{FALSE} they are returned as strings.} \item{keepFlags}{a logical whether the flags (e.g. "confidential", "provisional") should be kept in a separate column or if they -can be removed. Default is \code{FALSE}. For flag values see: -\url{http://ec.europa.eu/eurostat/data/database/information}. -Also possible non-real zero "0n" is indicated in flags column. +can be removed. Default is \code{FALSE}. For flag values see: +\url{https://ec.europa.eu/eurostat/data/database/information}. +Also possible non-real zero "0n" is indicated in flags column. Flags are not available for eurostat API, so \code{keepFlags} can not be used with a \code{filters}.} -\item{...}{further argument for \code{\link{get_eurostat_json}}.} +\item{use.data.table}{Use faster data.table functions? Default is FALSE. +On Windows requires that RTools is installed.} + +\item{...}{ + Arguments passed on to \code{\link[=get_eurostat_json]{get_eurostat_json}} + \describe{ + \item{\code{proxy}}{Use proxy, TRUE or FALSE (default).} + }} } \value{ -a tibble. One column for each dimension in the data, - the time column for a time dimension and - the values column for numerical values. - Eurostat data does not include all missing values and a treatment of - missing values depend on source. In bulk download - facility missing values are dropped if all dimensions are missing - on particular time. In JSON API missing values are dropped - only if all dimensions are missing on all times. The data from - bulk download facility can be completed for example with - \code{\link[tidyr]{complete}}. +a tibble. + +One column for each dimension in the data, the time column for a time +dimension and the values column for numerical values. Eurostat data does +not include all missing values and a treatment of missing values depend +on source. In bulk download facility missing values are dropped if all +dimensions are missing on particular time. In JSON API missing values are +dropped only if all dimensions are missing on all times. The data from +bulk download facility can be completed for example with \code{\link[tidyr:complete]{tidyr::complete()}}. } \description{ -Download data sets from Eurostat \url{ec.europa.eu/eurostat}. +Download data sets from Eurostat \url{https://ec.europa.eu/eurostat} } \details{ -Data sets are downloaded from -\href{http://ec.europa.eu/eurostat/estat-navtree-portlet-prod/BulkDownloadListing}{the Eurostat bulk download facility} or from The Eurostat Web Services -\href{http://ec.europa.eu/eurostat/web/json-and-unicode-web-services}{JSON API}. +Datasets are downloaded from +\href{https://wikis.ec.europa.eu/display/EUROSTATHELP/Transition+-+from+Eurostat+Bulk+Download+to+API}{the Eurostat SDMX 2.1 API} +in TSV format or from The Eurostat +\href{https://wikis.ec.europa.eu/display/EUROSTATHELP/API+Statistics+-+data+query}{API Statistics JSON API}. If only the table \code{id} is given, the whole table is downloaded from the -bulk download facility. If also \code{filters} are defined the JSON API is -used. +SDMX API. If any \code{filters} are given JSON API is used instead. The bulk download facility is the fastest method to download whole datasets. -It is also often the only way as the JSON API has limitation of maximum -50 sub-indicators at time and whole datasets usually exceeds that. Also, -it seems that multi frequency datasets can only be retrived via -bulk download facility and the \code{select_time} is not available for +It is also often the only way as the JSON API has limitation of maximum +50 sub-indicators at time and whole datasets usually exceeds that. Also, +it seems that multi frequency datasets can only be retrieved via +bulk download facility and the \code{select_time} is not available for JSON API method. -If your connection is thru a proxy, you probably have to set proxy parameters -to use JSON API, see \code{\link{get_eurostat_json}}. +If your connection is through a proxy, you may have to set proxy parameters +to use JSON API, see \code{\link[=get_eurostat_json]{get_eurostat_json()}}. -By default datasets from the bulk download facility are cached as they are -often rather large. Caching is not (currently) possible for datasets from -JSON API. +By default datasets are cached to reduce load on Eurostat services and +because some datasets can be quite large. Cache files are stored in a temporary directory by default or in -a named directory if cache_dir or option eurostat_cache_dir is defined. -The cache can be emptied with \code{\link{clean_eurostat_cache}}. +a named directory (See \code{\link[=set_eurostat_cache_dir]{set_eurostat_cache_dir()}}). +The cache can be emptied with \code{\link[=clean_eurostat_cache]{clean_eurostat_cache()}}. The \code{id}, a code, for the dataset can be searched with -the \code{\link{search_eurostat}} or from the Eurostat database -\url{http://ec.europa.eu/eurostat/data/database}. The Eurostat +the \code{\link[=search_eurostat]{search_eurostat()}} or from the Eurostat database +\url{https://ec.europa.eu/eurostat/data/database}. The Eurostat database gives codes in the Data Navigation Tree after every dataset in parenthesis. } +\section{Eurostat: Copyright notice and free re-use of data}{ +The following copyright notice is provided for end user convenience. +Please check up-to-date copyright information from the eurostat website: +\url{https://ec.europa.eu/eurostat/about-us/policies/copyright} + +"(c) European Union, 1995 - today + +Eurostat has a policy of encouraging free re-use of its data, both for +non-commercial and commercial purposes. All statistical data, metadata, +content of web pages or other dissemination tools, official publications +and other documents published on its website, with the exceptions listed +below, can be reused without any payment or written licence provided that: +\itemize{ +\item the source is indicated as Eurostat; +\item when re-use involves modifications to the data or text, this must be +stated clearly to the end user of the information." +} + +For exceptions to the abovementioned principles see +\href{https://ec.europa.eu/eurostat/about-us/policies/copyright}{Eurostat website} +} + +\section{Filtering datasets}{ +When using Eurostat API Statistics (JSON API), datasets can be filtered +before they are downloaded and saved in local memory. The general format +for filter parameters is \verb{=}. + +Filter parameters are optional but the used dimension codes must be present +in the data product that is being queried. Dimension codes can +vary between different data products so it may be useful to examine new +datasets in Eurostat data browser beforehand. However, most if not all +Eurostat datasets concern European countries and contain information that +was gathered at some point in time, so \code{geo} and \code{time} dimension codes +can usually be used. + +\verb{} and \verb{} are case-insensitive and they can be written +in lowercase or uppercase in the query. + +Parameters are passed onto the \code{eurostat} package functions \code{\link[=get_eurostat]{get_eurostat()}} +and \code{\link[=get_eurostat_json]{get_eurostat_json()}} as a list item. If an individual item contains +multiple items, as it often can be in the case of \code{geo} parameters and +other optional items, they must be in the form of a vector: \code{c("FI", "SE")}. +For examples on how to use these parameters, see function examples below. +\subsection{Time parameters}{ + +\code{time} and \code{time_period} address the same \code{TIME_PERIOD} dimension in the +dataset and can be used interchangeably. In the Eurostat documentation +it is stated that "Using more than one Time parameter in the same query +is not accepted", but practice has shown that actually Eurostat API allows +multiple \code{time} parameters in the same query. This makes it possible to +use R colon operator when writing queries, so \code{time = c(2015:2018)} +translates to \verb{&time=2015&time=2016&time=2017&time=2018}. + +The only exception +to this is when the queried dataset contains e.g. quarterly data and +\code{TIME_PERIOD} is saved as \code{2015-Q1}, \code{2015-Q2} etc. Then it is possible +to use \code{time=2015-Q1&time=2015-Q2} style in the query URL, but this makes it +unfeasible to use the colon operator and requires a lot of manual typing. + +Because of this, it is useful to know about other time parameters as well: +\itemize{ +\item \code{untilTimePeriod}: return dataset items from the oldest record up until the +set time, for example "all data until 2000": \code{untilTimePeriod = 2000} +\item \code{sinceTimePeriod}: return dataset items starting from set time, for example +"all datastarting from 2008": \code{sinceTimePeriod = 2008} +\item \code{lastTimePeriod}: starting from the most recent time period, how many +preceding time periods should be returned? For example 10 most +recent observations: \code{lastTimePeriod = 10} +} + +Using both \code{untilTimePeriod} and \code{sinceTimePeriod} parameters in the same +query is allowed, making the usage of the R colon operator unnecessary. +In the case of quarterly data, using \code{untilTimePeriod} and \code{sinceTimePeriod} +parameters also works, as opposed to the colon operator, so it is generally +safer to use them as well. +} + +\subsection{Other dimensions}{ + +In \code{\link[=get_eurostat_json]{get_eurostat_json()}} examples \code{nama_10_gdp} dataset is filtered with +two additional filter parameters: +\itemize{ +\item \code{na_item = "B1GQ"} +\item \code{unit = "CLV_I10"} +} + +Filters like these are most likely unique to the \code{nama_10_gdp} dataset +(or other datasets within the same domain) and should +not be used with others dataset without user discretion. +By using \code{\link[=label_eurostat]{label_eurostat()}} we know that \code{"B1GQ"} stands for +"Gross domestic product at market prices" and +\code{"CLV_I10"} means "Chain linked volumes, index 2010=100". + +Different dimension codes can be translated to a natural language by using +the \code{\link[=get_eurostat_dic]{get_eurostat_dic()}} function, which returns labels for individual +dimension items such as \code{na_item} and \code{unit}, as opposed to +\code{\link[=label_eurostat]{label_eurostat()}} which does it for whole datasets. For example, the +parameter \code{na_item} stands for "National accounts indicator (ESA 2010)" and +\code{unit} stands for "Unit of measure". +} + +\subsection{Language}{ + +All datasets have metadata available in English, French and German. If no +parameter is given, the labels are returned in English. + +Example: +\itemize{ +\item \code{lang = "fr"} +} +} + +\subsection{More information}{ + +For more information about data filtering see Eurostat documentation +on API Statistics: +\url{https://wikis.ec.europa.eu/display/EUROSTATHELP/API+Statistics+-+data+query#APIStatisticsdataquery-TheparametersdefinedintheRESTrequest} +} +} + +\section{Citing Eurostat data}{ +For citing datasets, use \code{\link[=get_bibentry]{get_bibentry()}} to build a bibliography that +is suitable for your reference manager of choice. + +When using Eurostat data in other contexts than academic publications that +in-text citations or footnotes/endnotes, the following guidelines may be +helpful: +\itemize{ +\item The origin of the data should always be mentioned as "Source: Eurostat". +\item The online dataset codes(s) should also be provided in order to ensure +transparency and facilitate access to the Eurostat data and related +methodological information. For example: +"Source: Eurostat (online data code: namq_10_gdp)" +\item Online publications (e.g. web pages, PDF) should include a clickable +link to the dataset using the bookmark functionality available in the +Eurostat data browser. +} + +It should be avoided to associate different entities (e.g. Eurostat, +National Statistical Offices, other data providers) to the same dataset or +indicator without specifying the role of each of them in the treatment of +data. + +See also section "Eurostat: Copyright notice and free re-use of data" +in \code{\link[=get_eurostat]{get_eurostat()}} documentation. +} + +\section{Disclaimer: Availability of filtering functionalities}{ +Currently it only possible to download filtered data through API Statistics +(JSON API) when using \code{eurostat} package, although technically filtering +datasets downloaded through the SDMX Dissemination API is also supported by +Eurostat. We may support this feature in the future. In the meantime, if you +are interested in filtering Dissemination API data queries manually, please +consult the following Eurostat documentation: +\url{https://wikis.ec.europa.eu/display/EUROSTATHELP/API+SDMX+2.1+-+data+filtering} +} + +\section{Strategies for handling large datasets more efficiently}{ +Most Eurostat datasets are relatively manageable, at least on a machine +with 16 GB of RAM. The largest dataset in Eurostat database, at the time +of writing this, had 148362539 (148 million) values, which results in an +object with 148 million rows in tidy data (long) format. The test machine +with 16 GB of RAM was able to handle the second largest dataset in the +database with 91 million values (rows). + +There are still some methods to make data fetching +functions perform faster: +\itemize{ +\item turn caching off: \code{get_eurostat(cache = FALSE)} +\item turn cache compression off (may result in rather large cache files!): +\code{get_eurostat(compress_file = FALSE)} +\item if you want faster caching with manageable file sizes, use stringsAsFactors: +\code{get_eurostat(cache = TRUE, compress_file = TRUE, stringsAsFactors = TRUE)} +\item Use faster data.table functions: \code{get_eurostat(use.data.table = TRUE)} +\item Keep column processing to a minimum: +\code{get_eurostat(time_format = "raw", type = "code")} etc. +\item Read \code{get_eurostat()} function documentation carefully so you understand +what different arguments do +\item Filter the dataset so that you fetch only the parts you need! +} +} + \examples{ +\dontshow{if (check_access_to_data()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} \dontrun{ k <- get_eurostat("nama_10_lp_ulc") k <- get_eurostat("nama_10_lp_ulc", time_format = "num") k <- get_eurostat("nama_10_lp_ulc", update_cache = TRUE) -dir.create(file.path(tempdir(), "r_cache")) -k <- get_eurostat("nama_10_lp_ulc", - cache_dir = file.path(tempdir(), "r_cache")) + +k <- get_eurostat("nama_10_lp_ulc", + cache_dir = file.path(tempdir(), "r_cache") +) options(eurostat_update = TRUE) k <- get_eurostat("nama_10_lp_ulc") options(eurostat_update = FALSE) -options(eurostat_cache_dir = file.path(tempdir(), "r_cache")) + +set_eurostat_cache_dir(file.path(tempdir(), "r_cache2")) k <- get_eurostat("nama_10_lp_ulc") k <- get_eurostat("nama_10_lp_ulc", cache = FALSE) k <- get_eurostat("avia_gonc", select_time = "Y", cache = FALSE) -dd <- get_eurostat("nama_10_gdp", - filters = list(geo = "FI", - na_item = "B1GQ", - unit = "CLV_I10")) +dd <- get_eurostat("nama_10_gdp", + filters = list( + geo = "FI", + na_item = "B1GQ", + unit = "CLV_I10" + ) +) + +# A dataset with multiple time series in one +dd2 <- get_eurostat("AVIA_GOR_ME", + select_time = c("A", "M", "Q"), + time_format = "date_last" +) + +# An example of downloading whole dataset from JSON API +dd3 <- get_eurostat("AVIA_GOR_ME", + filters = list() +) + +# Filtering a dataset from a local file +dd3_filter <- get_eurostat("AVIA_GOR_ME", + filters = list( + tra_meas = "FRM_BRD" + ) +) + +} +\dontshow{\}) # examplesIf} } +\references{ +See \code{citation("eurostat")}: + +\if{html}{\out{
    }}\preformatted{Kindly cite the eurostat R package as follows: + + Lahti L., Huovari J., Kainu M., and Biecek P. (2017). Retrieval and + analysis of Eurostat open data with the eurostat package. The R + Journal 9(1), pp. 385-392. doi: 10.32614/RJ-2017-019 + +A BibTeX entry for LaTeX users is + + @Article\{10.32614/RJ-2017-019, + title = \{Retrieval and Analysis of Eurostat Open Data with the eurostat Package\}, + author = \{Leo Lahti and Janne Huovari and Markus Kainu and Przemyslaw Biecek\}, + journal = \{The R Journal\}, + volume = \{9\}, + number = \{1\}, + pages = \{385--392\}, + year = \{2017\}, + doi = \{10.32614/RJ-2017-019\}, + url = \{https://doi.org/10.32614/RJ-2017-019\}, + \} + + Lahti, L., Huovari J., Kainu M., Biecek P., Hernangomez D., Antal D., + and Kantanen P. (2023). eurostat: Tools for Eurostat Open Data + [Computer software]. R package version 4.0.0. + https://github.com/rOpenGov/eurostat + +A BibTeX entry for LaTeX users is + + @Misc\{eurostat, + title = \{eurostat: Tools for Eurostat Open Data\}, + author = \{Leo Lahti and Janne Huovari and Markus Kainu and Przemyslaw Biecek and Diego Hernangomez and Daniel Antal and Pyry Kantanen\}, + url = \{https://github.com/rOpenGov/eurostat\}, + type = \{Computer software\}, + year = \{2023\}, + note = \{R package version 4.0.0\}, + \} +}\if{html}{\out{
    }} + +When citing data downloaded from Eurostat, see section "Citing Eurostat data" +in \code{\link[=get_eurostat]{get_eurostat()}} documentation. } \seealso{ -\code{\link{search_eurostat}}, \code{\link{label_eurostat}} +\code{\link[=search_eurostat]{search_eurostat()}}, \code{\link[=label_eurostat]{label_eurostat()}} } \author{ -Przemyslaw Biecek, Leo Lahti, Janne Huovari and Markus Kainu \email{ropengov-forum@googlegroups.com} \url{http://github.com/ropengov/eurostat} +Przemyslaw Biecek, Leo Lahti, Janne Huovari, Markus Kainu and Pyry Kantanen } diff --git a/man/get_eurostat_dic.Rd b/man/get_eurostat_dic.Rd index c13dd183..c236e422 100755 --- a/man/get_eurostat_dic.Rd +++ b/man/get_eurostat_dic.Rd @@ -9,7 +9,7 @@ get_eurostat_dic(dictname, lang = "en") \arguments{ \item{dictname}{A character, dictionary for the variable to be downloaded.} -\item{lang}{A character, language code. Options: "en" (default) / "fr" / "de".} +\item{lang}{A character, language code. Options: "en" (default), "fr", "de".} } \value{ tibble with two columns: code names and full names. @@ -18,26 +18,69 @@ tibble with two columns: code names and full names. Download a Eurostat dictionary. } \details{ -For given coded variable from Eurostat \url{ec.europa.eu/eurostat}. - The dictionaries link codes with human-readable labels. - To translate codes to labels, use \code{\link{label_eurostat}}. +For given coded variable from Eurostat +\url{https://ec.europa.eu/eurostat/}. The dictionaries link codes with +human-readable labels. To translate codes to labels, use +\code{\link[=label_eurostat]{label_eurostat()}}. } \examples{ -\dontrun{ - tmp <- get_eurostat_dic("crop_pro") - head(tmp) - tmp <- get_eurostat_dic("crop_pro", lang = "fr") - } +\dontshow{if (check_access_to_data()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\donttest{ +get_eurostat_dic("crop_pro") + +# Try another language +get_eurostat_dic("crop_pro", lang = "fr") +} +\dontshow{\}) # examplesIf} } \references{ -See citation("eurostat"). +See \code{citation("eurostat")}: + +\if{html}{\out{
    }}\preformatted{# Kindly cite the eurostat R package as follows: +# +# Lahti L., Huovari J., Kainu M., and Biecek P. (2017). Retrieval and +# analysis of Eurostat open data with the eurostat package. The R +# Journal 9(1), pp. 385-392. doi: 10.32614/RJ-2017-019 +# +# A BibTeX entry for LaTeX users is +# +# @Article\{10.32614/RJ-2017-019, +# title = \{Retrieval and Analysis of Eurostat Open Data with the eurostat Package\}, +# author = \{Leo Lahti and Janne Huovari and Markus Kainu and Przemyslaw Biecek\}, +# journal = \{The R Journal\}, +# volume = \{9\}, +# number = \{1\}, +# pages = \{385--392\}, +# year = \{2017\}, +# doi = \{10.32614/RJ-2017-019\}, +# url = \{https://doi.org/10.32614/RJ-2017-019\}, +# \} +# +# Lahti, L., Huovari J., Kainu M., Biecek P., Hernangomez D., Antal D., +# and Kantanen P. (2023). eurostat: Tools for Eurostat Open Data +# [Computer software]. R package version 4.0.0. +# https://github.com/rOpenGov/eurostat +# +# A BibTeX entry for LaTeX users is +# +# @Misc\{eurostat, +# title = \{eurostat: Tools for Eurostat Open Data\}, +# author = \{Leo Lahti and Janne Huovari and Markus Kainu and Przemyslaw Biecek and Diego Hernangomez and Daniel Antal and Pyry Kantanen\}, +# url = \{https://github.com/rOpenGov/eurostat\}, +# type = \{Computer software\}, +# year = \{2023\}, +# note = \{R package version 4.0.0\}, +# \} +}\if{html}{\out{
    }} } \seealso{ -\code{\link{label_eurostat}}, \code{\link{get_eurostat}}, - \code{\link{search_eurostat}}. +\code{\link[=label_eurostat]{label_eurostat()}}, \code{\link[=get_eurostat]{get_eurostat()}}, +\code{\link[=search_eurostat]{search_eurostat()}}. } \author{ -Przemyslaw Biecek and Leo Lahti \email{leo.lahti@iki.fi}. Thanks to Wietse Dol for contributions. +Przemyslaw Biecek and Leo Lahti \href{mailto:leo.lahti@iki.fi}{leo.lahti@iki.fi}. Thanks to +Wietse Dol for contributions. Updated by Pyry Kantanen to support XML +codelists. } \keyword{database} \keyword{utilities} diff --git a/man/get_eurostat_folder.Rd b/man/get_eurostat_folder.Rd new file mode 100644 index 00000000..4551e0db --- /dev/null +++ b/man/get_eurostat_folder.Rd @@ -0,0 +1,70 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/get_eurostat.R +\name{get_eurostat_folder} +\alias{get_eurostat_folder} +\title{Get all datasets in a folder} +\usage{ +get_eurostat_folder(code, env = .EurostatEnv) +} +\arguments{ +\item{code}{Folder code from Eurostat Table of Contents.} + +\item{env}{Name of the environment where downloaded datasets are assigned. +Default is .EurostatEnv. If NULL, datasets are returned as a list object.} +} +\description{ +Loops over all files in a Eurostat database folder, downloads the data and +assigns the datasets to environment. +} +\details{ +The datasets are assigned into .EurostatEnv by default, using dataset codes +as object names. The datasets are downloaded from SDMX API as TSV files, +meaning that they are returned without filtering. No filters can be +provided using this function. + +Please do not attempt to download too many datasets or the whole database +at once. The number of datasets that can be downloaded at once is hardcoded +to 20. The function also asks the user for confirmation if the number of +datasets in a folder is more than 10. This is by design to discourage +straining Eurostat API. +} +\section{Data source: Eurostat Table of Contents}{ +The Eurostat Table of Contents (TOC) is downloaded from +\url{https://ec.europa.eu/eurostat/api/dissemination/catalogue/toc/txt?lang=en} +(default) or from French or German language variants: +\url{https://ec.europa.eu/eurostat/api/dissemination/catalogue/toc/txt?lang=fr} +\url{https://ec.europa.eu/eurostat/api/dissemination/catalogue/toc/txt?lang=de} + +See Eurostat documentation on TOC items: +\url{https://wikis.ec.europa.eu/display/EUROSTATHELP/API+-+Detailed+guidelines+-+Catalogue+API+-+TOC} +} + +\section{Data source: Eurostat SDMX 2.1 Dissemination API}{ +Data is downloaded from Eurostat SDMX 2.1 API endpoint +as compressed TSV files that are transformed into tabular format. +See Eurostat documentation for more information: +\url{https://wikis.ec.europa.eu/display/EUROSTATHELP/API+SDMX+2.1+-+data+query} + +The new dissemination API replaces the old bulk download facility that was +used by Eurostat before October 2023 and by the eurostat R package versions +before 4.0.0. +See Eurostat documentation about the transition from Bulk Download to API +for more information about the differences between the old bulk download +facility and the data provided by the new API connection: +\url{https://wikis.ec.europa.eu/display/EUROSTATHELP/Transition+-+from+Eurostat+Bulk+Download+to+API} + +See especially the document Migrating_to_API_TSV.pdf that describes the +changes in TSV file format in new applications. + +For more information about SDMX 2.1, see SDMX standards: Section 7: +Guidelines for the use of web services, Version 2.1: +\url{https://sdmx.org/wp-content/uploads/SDMX_2-1_SECTION_7_WebServicesGuidelines.pdf} +} + +\seealso{ +\code{\link[=get_eurostat_toc]{get_eurostat_toc()}} \code{\link[=toc_count_children]{toc_count_children()}} \code{\link[=toc_determine_hierarchy]{toc_determine_hierarchy()}} +\code{\link[=toc_list_children]{toc_list_children()}} \code{\link[=toc_count_whitespace]{toc_count_whitespace()}} +} +\author{ +Pyry Kantanen +} diff --git a/man/get_eurostat_geospatial.Rd b/man/get_eurostat_geospatial.Rd index 5672ab41..8634fa4c 100755 --- a/man/get_eurostat_geospatial.Rd +++ b/man/get_eurostat_geospatial.Rd @@ -2,60 +2,264 @@ % Please edit documentation in R/get_eurostat_geospatial.R \name{get_eurostat_geospatial} \alias{get_eurostat_geospatial} -\title{Download Geospatial Data from GISGO} +\title{Download Geospatial Data from GISCO} +\source{ +Data source: Eurostat + +© EuroGeographics for the administrative boundaries + +Data downloaded using \pkg{giscoR} +} \usage{ -get_eurostat_geospatial(output_class = "sf", resolution = "60", - nuts_level = "all", year = "2016", cache = TRUE, - update_cache = FALSE, cache_dir = NULL) +get_eurostat_geospatial( + output_class = "sf", + resolution = "60", + nuts_level = "all", + year = "2016", + cache = TRUE, + update_cache = FALSE, + cache_dir = NULL, + crs = "4326", + make_valid = "DEPRECATED", + ... +) } \arguments{ -\item{output_class}{A string. Class of object returned, -either \code{sf} \code{simple features}, \code{df} (\code{data_frame}) or - \code{spdf} (\code{SpatialPolygonDataFrame})} +\item{output_class}{Class of object returned, +either \code{sf} \verb{simple features} or \code{df} (\code{data_frame}). \code{spdf} output has +been soft-deprecated, the function would switch to \code{sf}.} \item{resolution}{Resolution of the geospatial data. One of -"60" (1:60million), "20" (1:20million), "10" (1:10million), "03" (1:3million) or "01" (1:1million).} +\itemize{ +\item "60" (1:60million), +\item "20" (1:20million) +\item "10" (1:10million) +\item "03" (1:3million) or +\item "01" (1:1million). +}} \item{nuts_level}{Level of NUTS classification of the geospatial data. One of "0", "1", "2", "3" or "all" (mimics the original behaviour)} \item{year}{NUTS release year. One of -"2003", "2006", "2010", "2013" or "2016"} +"2003", "2006", "2010", "2013", "2016" or "2021"} + +\item{cache}{a logical whether to do caching. Default is \code{TRUE}.} + +\item{update_cache}{a logical whether to update cache. Can be set also with +\code{options(eurostat_update = TRUE)}} -\item{cache}{a logical whether to do caching. Default is \code{TRUE}. Affects -only queries from the bulk download facility.} +\item{cache_dir}{a path to a cache directory. See +\code{\link[=set_eurostat_cache_dir]{set_eurostat_cache_dir()}}. If \code{NULL} and the cache dir has not been set +globally the file would be stored in the \code{\link[=tempdir]{tempdir()}}.} -\item{update_cache}{a locigal whether to update cache. Can be set also with -options(eurostat_update = TRUE)} +\item{crs}{projection of the map: 4-digit +\href{https://spatialreference.org/ref/epsg/}{EPSG code}. One of: +\itemize{ +\item "4326" - WGS84 +\item "3035" - ETRS89 / ETRS-LAEA +\item "3857" - Pseudo-Mercator +}} -\item{cache_dir}{a path to a cache directory. The directory have to exist. -The \code{NULL} (default) uses and creates -'eurostat' directory in the temporary directory from -\code{\link{tempdir}}. Directory can also be set with -\code{option} eurostat_cache_dir.} +\item{make_valid}{Deprecated} + +\item{...}{ + Arguments passed on to \code{\link[giscoR:gisco_get_nuts]{giscoR::gisco_get_nuts}} + \describe{ + \item{\code{verbose}}{Logical, displays information. Useful for debugging, +default is \code{FALSE}.} + \item{\code{spatialtype}}{Type of geometry to be returned: +\itemize{ +\item \strong{"BN"}: Boundaries - \code{LINESTRING} object. +\item \strong{"LB"}: Labels - \code{POINT} object. +\item \strong{"RG"}: Regions - \code{MULTIPOLYGON/POLYGON} object. +}} + \item{\code{country}}{Optional. A character vector of country codes. It could be +either a vector of country names, a vector of ISO3 country codes or a +vector of Eurostat country codes. Mixed types (as \code{c("Turkey","US","FRA")}) +would not work. See also \code{\link[countrycode:countrycode]{countrycode::countrycode()}}.} + \item{\code{nuts_id}}{Optional. A character vector of NUTS IDs.} + }} } \value{ -a sf, data_frame or SpatialPolygonDataFrame. +a sf or data_frame } \description{ -Downloads either a simple features (sf), SpatialPolygonDataFrame or a data_frame preprocessed using - \code{broom::tidy()}. +Downloads either a simple features (sf) or a data_frame +of NUTS regions. This function is a wrapper of \code{\link[giscoR:gisco_get_nuts]{giscoR::gisco_get_nuts()}}. +This function requires to have installed the packages \CRANpkg{sf} and +\CRANpkg{giscoR}. } \details{ -The data source URL is \url{http://ec.europa.eu/eurostat/web/gisco/geodata/reference-data/administrative-units-statistical-units}. +The objects downloaded from GISCO should contain all or some of the +following variable columns: +\itemize{ +\item \strong{id}: JSON id code, the same as \strong{NUTS_ID}. See \strong{NUTS_ID} below for +further clarification. +\item \strong{LEVL_CODE}: NUTS level code: 0 (national level), 1 (major +socio-economic regions), 2 (basic regions for the application of regional +policies) or 3 (small regions). +\item \strong{NUTS_ID}: NUTS ID code, consisting of country code and numbers (1 for +NUTS 1, 2 for NUTS 2 and 3 for NUTS 3) +\item \strong{CNTR_CODE}: Country code: two-letter ISO code (ISO 3166 alpha-2), except +in the case of Greece (EL). +\item \strong{NAME_LATN}: NUTS name in local language, transliterated to Latin script +\item \strong{NUTS_NAME}: NUTS name in local language, in local script. +\item \strong{MOUNT_TYPE}: Mountain typology for NUTS 3 regions. +\itemize{ +\item 1: "where more than 50 \% of the surface is covered by topographic +mountain areas" +\item 2: "in which more than 50 \% of the regional population lives in +topographic mountain areas" +\item 3: "where more than 50 \% of the surface is covered by topographic +mountain areas and where more than 50 \% of the regional population lives +in these mountain areas" +\item 4: non-mountain region / other region +\item 0: no classification provided (e.g. in the case of NUTS 1 and NUTS 2 and +non-EU countries) +} +\item \strong{URBN_TYPE}: Urban-rural typology for NUTS 3 regions. +\itemize{ +\item 1: predominantly urban region +\item 2: intermediate region +\item 3: predominantly rural region +\item 0: no classification provided (e.g. in the case of NUTS 1 and NUTS 2 +regions) +} +\item \strong{COAST_TYPE}: Coastal typology for NUTS 3 regions. +\itemize{ +\item 1: coastal (on coast) +\item 2: coastal (>= 50\% of population living within 50km of the coastline) +\item 3: non-coastal region +\item 0: no classification provided (e.g. in the case of NUTS 1 and NUTS 2 +regions) +} +\item \strong{FID}: Same as NUTS_ID. +\item \strong{geo}: Same as NUTS_ID, added for for easier joins with dplyr. Consider +the status of this column "questioning" and use other columns for joins +when possible. +\item \strong{geometry}: geospatial information. +} +} +\section{Eurostat: Copyright notice and free re-use of data}{ +The following copyright notice is provided for end user convenience. +Please check up-to-date copyright information from the eurostat website: +\url{https://ec.europa.eu/eurostat/about-us/policies/copyright} + +"(c) European Union, 1995 - today + +Eurostat has a policy of encouraging free re-use of its data, both for +non-commercial and commercial purposes. All statistical data, metadata, +content of web pages or other dissemination tools, official publications +and other documents published on its website, with the exceptions listed +below, can be reused without any payment or written licence provided that: +\itemize{ +\item the source is indicated as Eurostat; +\item when re-use involves modifications to the data or text, this must be +stated clearly to the end user of the information." +} + +For exceptions to the abovementioned principles see +\href{https://ec.europa.eu/eurostat/about-us/policies/copyright}{Eurostat website} +} + +\section{Data source: GISCO - General Copyright}{ +"Eurostat's general copyright notice and licence policy is applicable and +can be consulted here: +\url{https://ec.europa.eu/eurostat/about-us/policies/copyright} + +Please also be aware of the European Commission's general conditions: +\url{https://commission.europa.eu/legal-notice_en} + +Moreover, there are specific provisions applicable to some of the following +datasets available for downloading. The download and usage of these data +is subject to their acceptance: +\itemize{ +\item Administrative Units / Statistical Units +\item Population distribution / Demography +\item Transport Networks +\item Land Cover +\item Elevation (DEM)" } + +Of the abovementioned datasets, Administrative Units / Statistical Units +is applicable if the user wants to draw maps with borders provided by +GISCO / EuroGeographics. +} + +\section{Data source: GISCO - Administrative Units / Statistical Units}{ +The following copyright notice is provided for end user convenience. +Please check up-to-date copyright information from the GISCO website: +\href{https://ec.europa.eu/eurostat/web/gisco/geodata/reference-data/administrative-units-statistical-units}{GISCO: Geographical information and maps - Administrative units/statistical units} + +"In addition to the \href{https://ec.europa.eu/eurostat/web/main/about/policies/copyright}{general copyright and licence policy} applicable to the whole Eurostat website, the following +specific provisions apply to the datasets you are downloading. The download +and usage of these data is subject to the acceptance of the following +clauses: +\enumerate{ +\item The Commission agrees to grant the non-exclusive and not transferable +right to use and process the Eurostat/GISCO geographical data downloaded +from this page (the "data"). +\item The permission to use the data is granted on condition that: +\enumerate{ +\item the data will not be used for commercial purposes; +\item the source will be acknowledged. A copyright notice, as specified +below, will have to be visible on any printed or electronic publication +using the data downloaded from this page." +} +} +\subsection{Copyright notice}{ + +When data downloaded from this page is used in any printed or electronic +publication, in addition to any other provisions applicable to the whole +Eurostat website, data source will have to be acknowledged in the legend of +the map and in the introductory page of the publication with the following +copyright notice: + +EN: © EuroGeographics for the administrative boundaries + +FR: © EuroGeographics pour les limites administratives + +DE: © EuroGeographics bezüglich der Verwaltungsgrenzen + +For publications in languages other than English, French or German, the +translation of the copyright notice in the language of the publication shall +be used. + +If you intend to use the data commercially, please contact EuroGeographics +for information regarding their licence agreements." +} +} + \examples{ - \dontrun{ - lp <- get_eurostat_geospatial(output_class = "sf", resolution = "60", nuts_level = "all") - lp \%>\% select(NUTS_ID) \%>\% plot() - lp <- get_eurostat_geospatial(output_class = "spdf", resolution = "60", nuts_level = "all") - spplot(lp, "STAT_LEVL_") - # or - lp <- get_eurostat_geospatial(output_class = "df", resolution = "60", nuts_level = "all") - ggplot(lp, aes(x=long,y=lat,group=group,fill=STAT_LEVL_),color="white") + geom_polygon() - } - +\donttest{ +# Uses cached dataset +sf <- get_eurostat_geospatial( + output_class = "sf", + resolution = "60", + nuts_level = "all" +) +# Downloads dataset from server +sf2 <- get_eurostat_geospatial( + output_class = "sf", + resolution = "20", + nuts_level = "all" +) +df <- get_eurostat_geospatial( + output_class = "df", + nuts_level = "0" +) +} + +} +\seealso{ +\code{\link[giscoR:gisco_get_nuts]{giscoR::gisco_get_nuts()}} + +Other geospatial: +\code{\link{eurostat_geodata_60_2016}} } \author{ -Markus Kainu +Markus Kainu \href{mailto:markuskainu@gmail.com}{markuskainu@gmail.com}, Diego Hernangomez +\url{https://github.com/dieghernan/} } +\concept{geospatial} diff --git a/man/get_eurostat_interactive.Rd b/man/get_eurostat_interactive.Rd new file mode 100644 index 00000000..0d5816cb --- /dev/null +++ b/man/get_eurostat_interactive.Rd @@ -0,0 +1,34 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/get_eurostat.R +\name{get_eurostat_interactive} +\alias{get_eurostat_interactive} +\title{Get Eurostat data interactive} +\usage{ +get_eurostat_interactive(code = NULL) +} +\arguments{ +\item{code}{A unique identifier / code for the dataset of interest. If code is not +known \code{\link[=search_eurostat]{search_eurostat()}} function can be used to search Eurostat table +of contents.} +} +\description{ +A simple interactive helper function to go through the steps of downloading +and/or finding suitable eurostat datasets. +} +\details{ +This function is intended to enable easy exploration of different eurostat +package functionalities and functions. In order to not drown the end user +in endless menus this function does not allow for setting +all possible \code{\link[=get_eurostat]{get_eurostat()}} function arguments. It is possible to set +\code{time_format}, \code{type}, \code{lang}, \code{stringsAsFactors}, \code{keepFlags}, and +\code{use.data.table} in the interactive menus. + +In some datasets setting these parameters may result in a +"Error in label_eurostat" error, for example: +"labels for XXXXXX includes duplicated labels in the Eurostat dictionary". +In these cases, and with other more complex queries, please +use \code{\link[=get_eurostat]{get_eurostat()}} function directly. +} +\seealso{ +\code{\link[=get_eurostat]{get_eurostat()}} +} diff --git a/man/get_eurostat_json.Rd b/man/get_eurostat_json.Rd index 73d7086e..83583600 100755 --- a/man/get_eurostat_json.Rd +++ b/man/get_eurostat_json.Rd @@ -4,69 +4,340 @@ \alias{get_eurostat_json} \title{Get Data from Eurostat API in JSON} \usage{ -get_eurostat_json(id, filters = NULL, type = c("code", "label", - "both"), lang = c("en", "fr", "de"), - stringsAsFactors = default.stringsAsFactors(), ...) +get_eurostat_json( + id, + filters = NULL, + type = "code", + lang = "en", + stringsAsFactors = FALSE, + proxy = FALSE, + ... +) } \arguments{ -\item{id}{A code name for the dataset of interested. See the table of -contents of eurostat datasets for more details.} +\item{id}{A unique identifier / code for the dataset of interest. If code is not +known \code{\link[=search_eurostat]{search_eurostat()}} function can be used to search Eurostat table +of contents.} \item{filters}{A named list of filters. Names of list objects are Eurostat variable codes and values are vectors of observation codes. If \code{NULL} -(default) the whole dataset is returned. See details for more on filters -and limitations per query.} +(default) the whole dataset is returned. See details for more information +on filters and limitations per query.} -\item{type}{A type of variables, "code" (default), "label" or "both". The -"both" will return a data_frame with named vectors, labels as values and -codes as names.} +\item{type}{A type of variables, "\code{code}" (default), "\code{label}" or "\code{both}". +The parameter "\code{both}" will return a data_frame with named vectors, +labels as values and codes as names.} -\item{lang}{A language used for metadata (en/fr/de).} +\item{lang}{2-letter language code, default is "\code{en}" (English), other +options are "\code{fr}" (French) and "\code{de}" (German). Used for labeling datasets.} -\item{stringsAsFactors}{if \code{TRUE} (the default) variables are converted -to factors in original Eurostat order. If \code{FALSE} they are returned as -a character.} +\item{stringsAsFactors}{if \code{TRUE} (the default) variables are converted to factors in the original +Eurostat order. If \code{FALSE} they are returned as strings.} -\item{...}{Other arguments passed on to \code{\link[httr]{GET}}. For example -a proxy parameters, see details. -.} +\item{proxy}{Use proxy, TRUE or FALSE (default).} + +\item{...}{ + Arguments passed on to \code{\link[httr2:req_proxy]{httr2::req_proxy}} + \describe{ + \item{\code{req}}{A \link[httr2]{request}.} + \item{\code{url,port}}{Location of proxy.} + \item{\code{username,password}}{Login details for proxy, if needed.} + \item{\code{auth}}{Type of HTTP authentication to use. Should be one of the +following: \code{basic}, digest, digest_ie, gssnegotiate, ntlm, any.} + }} } \value{ -A dataset as a data_frame. +A dataset as an object of \code{data.frame} class. } \description{ Retrieve data from Eurostat API in JSON format. } \details{ Data to retrieve from - \href{http://ec.europa.eu/eurostat/web/json-and-unicode-web-services}{The - Eurostat Web Services} can be specified with filters. Normally, it is - better to use JSON query through \code{\link{get_eurostat}}, than to use - \code{\link{get_eurostat_json}} directly. - - Queries are limited to 50 sub-indicators at a time. A time can be - filtered with fixed "time" filter or with "sinceTimePeriod" and - "lastTimePeriod" filters. A \code{sinceTimePeriod = 2000} returns - observations from 2000 to a last available. A \code{lastTimePeriod = 10} - returns a 10 last observations. - - To use a proxy to connect, a \code{\link[httr]{use_proxy}} can be - passed to \code{\link[httr]{GET}}. For example - \code{get_eurostat_json(id, filters, - config = httr::use_proxy(url, port, username, password))}. +\href{https://ec.europa.eu/eurostat/web/main/data/web-services}{The Eurostat Web Services} +can be specified with filters. Normally, it is +better to use JSON query through \code{\link[=get_eurostat]{get_eurostat()}}, than to use +\code{\link[=get_eurostat_json]{get_eurostat_json()}} directly. + +Queries are limited to 50 sub-indicators at a time. A time can be +filtered with fixed "time" filter or with "sinceTimePeriod" and +"lastTimePeriod" filters. A \code{sinceTimePeriod = 2000} returns +observations from 2000 to a last available. A \code{lastTimePeriod = 10} +returns a 10 last observations. See "Filtering datasets" section below +for more detailed information about filters. + +To use a proxy to connect, proxy arguments can be +passed to \code{\link[httr2:req_perform]{httr2::req_perform()}} via \code{\link[httr2:req_proxy]{httr2::req_proxy()}} - see latter +function documentation for parameter names that can be passed with \code{...}. +A non-functional example: +\code{get_eurostat_json(id, filters, proxy = TRUE, url = "127.0.0.1", port = 80)}. + +When retrieving data from Eurostat JSON API the user may encounter errors. +For end user convenience, we have provided a ready-made internal dataset +\code{sdmx_http_errors} that contains descriptive labels and descriptions about +the possible interpretation or cause of each error. These messages are +returned if the API returns a status indicating a HTTP error +(400 or greater). + +The Eurostat implementation seems to be based on SDMX 2.1, which is the +reason we've used SDMX Standards guidelines as a supplementary source +that we have included in the dataset. What this means in practice is that +the dataset contains error codes and their mappings that are not mentioned +in the Eurostat website. We hope you never encounter them. +} +\section{Data source: Eurostat API Statistics (JSON API)}{ +Data is downloaded from Eurostat API Statistics. See Eurostat documentation +for more information about data queries in API Statistics +\url{https://wikis.ec.europa.eu/display/EUROSTATHELP/API+Statistics+-+data+query} + +This replaces the old JSON Web Services that was used by Eurostat before +February 2023 and by the eurostat R package versions before 3.7.13. +See Eurostat documentation about the migration from JSON web service to API +Statistics for more information about the differences between the old and +the new service: +\url{https://wikis.ec.europa.eu/display/EUROSTATHELP/API+Statistics+-+migrating+from+JSON+web+service+to+API+Statistics} + +For easily viewing which filtering options are available - in addition to +the default ones, time and language - Eurostat Web services Query builder +tool may be useful: +\url{https://ec.europa.eu/eurostat/web/query-builder} +} + +\section{Filtering datasets}{ +When using Eurostat API Statistics (JSON API), datasets can be filtered +before they are downloaded and saved in local memory. The general format +for filter parameters is \verb{=}. + +Filter parameters are optional but the used dimension codes must be present +in the data product that is being queried. Dimension codes can +vary between different data products so it may be useful to examine new +datasets in Eurostat data browser beforehand. However, most if not all +Eurostat datasets concern European countries and contain information that +was gathered at some point in time, so \code{geo} and \code{time} dimension codes +can usually be used. + +\verb{} and \verb{} are case-insensitive and they can be written +in lowercase or uppercase in the query. + +Parameters are passed onto the \code{eurostat} package functions \code{\link[=get_eurostat]{get_eurostat()}} +and \code{\link[=get_eurostat_json]{get_eurostat_json()}} as a list item. If an individual item contains +multiple items, as it often can be in the case of \code{geo} parameters and +other optional items, they must be in the form of a vector: \code{c("FI", "SE")}. +For examples on how to use these parameters, see function examples below. +\subsection{Time parameters}{ + +\code{time} and \code{time_period} address the same \code{TIME_PERIOD} dimension in the +dataset and can be used interchangeably. In the Eurostat documentation +it is stated that "Using more than one Time parameter in the same query +is not accepted", but practice has shown that actually Eurostat API allows +multiple \code{time} parameters in the same query. This makes it possible to +use R colon operator when writing queries, so \code{time = c(2015:2018)} +translates to \verb{&time=2015&time=2016&time=2017&time=2018}. + +The only exception +to this is when the queried dataset contains e.g. quarterly data and +\code{TIME_PERIOD} is saved as \code{2015-Q1}, \code{2015-Q2} etc. Then it is possible +to use \code{time=2015-Q1&time=2015-Q2} style in the query URL, but this makes it +unfeasible to use the colon operator and requires a lot of manual typing. + +Because of this, it is useful to know about other time parameters as well: +\itemize{ +\item \code{untilTimePeriod}: return dataset items from the oldest record up until the +set time, for example "all data until 2000": \code{untilTimePeriod = 2000} +\item \code{sinceTimePeriod}: return dataset items starting from set time, for example +"all datastarting from 2008": \code{sinceTimePeriod = 2008} +\item \code{lastTimePeriod}: starting from the most recent time period, how many +preceding time periods should be returned? For example 10 most +recent observations: \code{lastTimePeriod = 10} +} + +Using both \code{untilTimePeriod} and \code{sinceTimePeriod} parameters in the same +query is allowed, making the usage of the R colon operator unnecessary. +In the case of quarterly data, using \code{untilTimePeriod} and \code{sinceTimePeriod} +parameters also works, as opposed to the colon operator, so it is generally +safer to use them as well. +} + +\subsection{Other dimensions}{ + +In \code{\link[=get_eurostat_json]{get_eurostat_json()}} examples \code{nama_10_gdp} dataset is filtered with +two additional filter parameters: +\itemize{ +\item \code{na_item = "B1GQ"} +\item \code{unit = "CLV_I10"} +} + +Filters like these are most likely unique to the \code{nama_10_gdp} dataset +(or other datasets within the same domain) and should +not be used with others dataset without user discretion. +By using \code{\link[=label_eurostat]{label_eurostat()}} we know that \code{"B1GQ"} stands for +"Gross domestic product at market prices" and +\code{"CLV_I10"} means "Chain linked volumes, index 2010=100". + +Different dimension codes can be translated to a natural language by using +the \code{\link[=get_eurostat_dic]{get_eurostat_dic()}} function, which returns labels for individual +dimension items such as \code{na_item} and \code{unit}, as opposed to +\code{\link[=label_eurostat]{label_eurostat()}} which does it for whole datasets. For example, the +parameter \code{na_item} stands for "National accounts indicator (ESA 2010)" and +\code{unit} stands for "Unit of measure". +} + +\subsection{Language}{ + +All datasets have metadata available in English, French and German. If no +parameter is given, the labels are returned in English. + +Example: +\itemize{ +\item \code{lang = "fr"} +} +} + +\subsection{More information}{ + +For more information about data filtering see Eurostat documentation +on API Statistics: +\url{https://wikis.ec.europa.eu/display/EUROSTATHELP/API+Statistics+-+data+query#APIStatisticsdataquery-TheparametersdefinedintheRESTrequest} +} +} + +\section{Eurostat: Copyright notice and free re-use of data}{ +The following copyright notice is provided for end user convenience. +Please check up-to-date copyright information from the eurostat website: +\url{https://ec.europa.eu/eurostat/about-us/policies/copyright} + +"(c) European Union, 1995 - today + +Eurostat has a policy of encouraging free re-use of its data, both for +non-commercial and commercial purposes. All statistical data, metadata, +content of web pages or other dissemination tools, official publications +and other documents published on its website, with the exceptions listed +below, can be reused without any payment or written licence provided that: +\itemize{ +\item the source is indicated as Eurostat; +\item when re-use involves modifications to the data or text, this must be +stated clearly to the end user of the information." +} + +For exceptions to the abovementioned principles see +\href{https://ec.europa.eu/eurostat/about-us/policies/copyright}{Eurostat website} +} + +\section{Citing Eurostat data}{ +For citing datasets, use \code{\link[=get_bibentry]{get_bibentry()}} to build a bibliography that +is suitable for your reference manager of choice. + +When using Eurostat data in other contexts than academic publications that +in-text citations or footnotes/endnotes, the following guidelines may be +helpful: +\itemize{ +\item The origin of the data should always be mentioned as "Source: Eurostat". +\item The online dataset codes(s) should also be provided in order to ensure +transparency and facilitate access to the Eurostat data and related +methodological information. For example: +"Source: Eurostat (online data code: namq_10_gdp)" +\item Online publications (e.g. web pages, PDF) should include a clickable +link to the dataset using the bookmark functionality available in the +Eurostat data browser. +} + +It should be avoided to associate different entities (e.g. Eurostat, +National Statistical Offices, other data providers) to the same dataset or +indicator without specifying the role of each of them in the treatment of +data. + +See also section "Eurostat: Copyright notice and free re-use of data" +in \code{\link[=get_eurostat]{get_eurostat()}} documentation. } + +\section{Disclaimer: Availability of filtering functionalities}{ +Currently it only possible to download filtered data through API Statistics +(JSON API) when using \code{eurostat} package, although technically filtering +datasets downloaded through the SDMX Dissemination API is also supported by +Eurostat. We may support this feature in the future. In the meantime, if you +are interested in filtering Dissemination API data queries manually, please +consult the following Eurostat documentation: +\url{https://wikis.ec.europa.eu/display/EUROSTATHELP/API+SDMX+2.1+-+data+filtering} +} + \examples{ - \dontrun{ - tmp <- get_eurostat_json("cdh_e_fos") - yy <- get_eurostat_json(id = "nama_gdp_c", filters = list(geo=c("EU28", "FI"), - unit="EUR_HAB", - indic_na="B1GM")) +\dontrun{ +# Generally speaking these queries would be done through get_eurostat +tmp <- get_eurostat_json("nama_10_gdp") +yy <- get_eurostat_json("nama_10_gdp", filters = list( + geo = c("FI", "SE", "EU28"), + time = c(2015:2023), + lang = "FR", + na_item = "B1GQ", + unit = "CLV_I10" +)) + +# TIME_PERIOD filter works also with the new JSON API +yy2 <- get_eurostat_json("nama_10_gdp", filters = list( + geo = c("FI", "SE", "EU28"), + TIME_PERIOD = c(2015:2023), + lang = "FR", + na_item = "B1GQ", + unit = "CLV_I10" +)) + +# An example from get_eurostat +dd <- get_eurostat("nama_10_gdp", + filters = list( + geo = "FI", + na_item = "B1GQ", + unit = "CLV_I10" +)) +} +} +\references{ +See \code{citation("eurostat")}: + +\if{html}{\out{
    }}\preformatted{Kindly cite the eurostat R package as follows: + + Lahti L., Huovari J., Kainu M., and Biecek P. (2017). Retrieval and + analysis of Eurostat open data with the eurostat package. The R + Journal 9(1), pp. 385-392. doi: 10.32614/RJ-2017-019 + +A BibTeX entry for LaTeX users is + + @Article\{10.32614/RJ-2017-019, + title = \{Retrieval and Analysis of Eurostat Open Data with the eurostat Package\}, + author = \{Leo Lahti and Janne Huovari and Markus Kainu and Przemyslaw Biecek\}, + journal = \{The R Journal\}, + volume = \{9\}, + number = \{1\}, + pages = \{385--392\}, + year = \{2017\}, + doi = \{10.32614/RJ-2017-019\}, + url = \{https://doi.org/10.32614/RJ-2017-019\}, + \} + + Lahti, L., Huovari J., Kainu M., Biecek P., Hernangomez D., Antal D., + and Kantanen P. (2023). eurostat: Tools for Eurostat Open Data + [Computer software]. R package version 4.0.0. + https://github.com/rOpenGov/eurostat + +A BibTeX entry for LaTeX users is + + @Misc\{eurostat, + title = \{eurostat: Tools for Eurostat Open Data\}, + author = \{Leo Lahti and Janne Huovari and Markus Kainu and Przemyslaw Biecek and Diego Hernangomez and Daniel Antal and Pyry Kantanen\}, + url = \{https://github.com/rOpenGov/eurostat\}, + type = \{Computer software\}, + year = \{2023\}, + note = \{R package version 4.0.0\}, + \} +}\if{html}{\out{
    }} + +When citing data downloaded from Eurostat, see section "Citing Eurostat data" +in \code{\link[=get_eurostat]{get_eurostat()}} documentation. } +\seealso{ +\code{\link[httr2:req_proxy]{httr2::req_proxy()}} } \author{ -Przemyslaw Biecek, Leo Lahti, Janne Huovari and Markus Kainu - \email{ropengov-forum@googlegroups.com} - \url{http://github.com/ropengov/eurostat} +Przemyslaw Biecek, Leo Lahti, Janne Huovari Markus Kainu and Pyry Kantanen } \keyword{database} \keyword{utilities} diff --git a/man/get_eurostat_raw.Rd b/man/get_eurostat_raw.Rd index 8b4c0943..d3aca865 100755 --- a/man/get_eurostat_raw.Rd +++ b/man/get_eurostat_raw.Rd @@ -2,42 +2,162 @@ % Please edit documentation in R/get_eurostat_raw.R \name{get_eurostat_raw} \alias{get_eurostat_raw} -\title{Download Data from Eurostat Database} +\title{Download Data from Eurostat Dissemination API} \usage{ -get_eurostat_raw(id) +get_eurostat_raw(id, use.data.table = FALSE) } \arguments{ -\item{id}{A code name for the dataset of interested. See the table of -contents of eurostat datasets for more details.} +\item{id}{A unique identifier / code for the dataset of interest. If code is not +known \code{\link[=search_eurostat]{search_eurostat()}} function can be used to search Eurostat table +of contents.} + +\item{use.data.table}{Use faster data.table functions? Default is FALSE. +On Windows requires that RTools is installed.} } \value{ -A dataset in tibble format. First column contains comma - separated codes of cases. Other columns usually corresponds to - years and column names are years with preceding X. Data is in - character format as it contains values together with eurostat - flags for data. +A dataset in tibble format. First column contains comma +separated codes of cases. Other columns usually corresponds to +years and column names are years with preceding X. Data is in +character format as it contains values together with eurostat +flags for data. } \description{ -Download data from the eurostat database. +Download data from the eurostat database through the new +dissemination API. } -\details{ -Data is downloaded from - \url{http://ec.europa.eu/eurostat/estat-navtree-portlet-prod/BulkDownloadListing} and transformed into tabular format. +\section{Data source: Eurostat SDMX 2.1 Dissemination API}{ +Data is downloaded from Eurostat SDMX 2.1 API endpoint +as compressed TSV files that are transformed into tabular format. +See Eurostat documentation for more information: +\url{https://wikis.ec.europa.eu/display/EUROSTATHELP/API+SDMX+2.1+-+data+query} + +The new dissemination API replaces the old bulk download facility that was +used by Eurostat before October 2023 and by the eurostat R package versions +before 4.0.0. +See Eurostat documentation about the transition from Bulk Download to API +for more information about the differences between the old bulk download +facility and the data provided by the new API connection: +\url{https://wikis.ec.europa.eu/display/EUROSTATHELP/Transition+-+from+Eurostat+Bulk+Download+to+API} + +See especially the document Migrating_to_API_TSV.pdf that describes the +changes in TSV file format in new applications. + +For more information about SDMX 2.1, see SDMX standards: Section 7: +Guidelines for the use of web services, Version 2.1: +\url{https://sdmx.org/wp-content/uploads/SDMX_2-1_SECTION_7_WebServicesGuidelines.pdf} } + +\section{Eurostat: Copyright notice and free re-use of data}{ +The following copyright notice is provided for end user convenience. +Please check up-to-date copyright information from the eurostat website: +\url{https://ec.europa.eu/eurostat/about-us/policies/copyright} + +"(c) European Union, 1995 - today + +Eurostat has a policy of encouraging free re-use of its data, both for +non-commercial and commercial purposes. All statistical data, metadata, +content of web pages or other dissemination tools, official publications +and other documents published on its website, with the exceptions listed +below, can be reused without any payment or written licence provided that: +\itemize{ +\item the source is indicated as Eurostat; +\item when re-use involves modifications to the data or text, this must be +stated clearly to the end user of the information." +} + +For exceptions to the abovementioned principles see +\href{https://ec.europa.eu/eurostat/about-us/policies/copyright}{Eurostat website} +} + +\section{Citing Eurostat data}{ +For citing datasets, use \code{\link[=get_bibentry]{get_bibentry()}} to build a bibliography that +is suitable for your reference manager of choice. + +When using Eurostat data in other contexts than academic publications that +in-text citations or footnotes/endnotes, the following guidelines may be +helpful: +\itemize{ +\item The origin of the data should always be mentioned as "Source: Eurostat". +\item The online dataset codes(s) should also be provided in order to ensure +transparency and facilitate access to the Eurostat data and related +methodological information. For example: +"Source: Eurostat (online data code: namq_10_gdp)" +\item Online publications (e.g. web pages, PDF) should include a clickable +link to the dataset using the bookmark functionality available in the +Eurostat data browser. +} + +It should be avoided to associate different entities (e.g. Eurostat, +National Statistical Offices, other data providers) to the same dataset or +indicator without specifying the role of each of them in the treatment of +data. + +See also section "Eurostat: Copyright notice and free re-use of data" +in \code{\link[=get_eurostat]{get_eurostat()}} documentation. +} + +\section{Disclaimer: Availability of filtering functionalities}{ +Currently it only possible to download filtered data through API Statistics +(JSON API) when using \code{eurostat} package, although technically filtering +datasets downloaded through the SDMX Dissemination API is also supported by +Eurostat. We may support this feature in the future. In the meantime, if you +are interested in filtering Dissemination API data queries manually, please +consult the following Eurostat documentation: +\url{https://wikis.ec.europa.eu/display/EUROSTATHELP/API+SDMX+2.1+-+data+filtering} +} + \examples{ -\dontrun{ - tmp <- eurostat:::get_eurostat_raw("educ_iste") - head(tmp) - } +\dontshow{if (check_access_to_data()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\donttest{ +eurostat:::get_eurostat_raw("educ_iste") +} +\dontshow{\}) # examplesIf} } \references{ -see citation("eurostat") +See \code{citation("eurostat")}: + +\if{html}{\out{
    }}\preformatted{# Kindly cite the eurostat R package as follows: +# +# Lahti L., Huovari J., Kainu M., and Biecek P. (2017). Retrieval and +# analysis of Eurostat open data with the eurostat package. The R +# Journal 9(1), pp. 385-392. doi: 10.32614/RJ-2017-019 +# +# A BibTeX entry for LaTeX users is +# +# @Article\{10.32614/RJ-2017-019, +# title = \{Retrieval and Analysis of Eurostat Open Data with the eurostat Package\}, +# author = \{Leo Lahti and Janne Huovari and Markus Kainu and Przemyslaw Biecek\}, +# journal = \{The R Journal\}, +# volume = \{9\}, +# number = \{1\}, +# pages = \{385--392\}, +# year = \{2017\}, +# doi = \{10.32614/RJ-2017-019\}, +# url = \{https://doi.org/10.32614/RJ-2017-019\}, +# \} +# +# Lahti, L., Huovari J., Kainu M., Biecek P., Hernangomez D., Antal D., +# and Kantanen P. (2023). eurostat: Tools for Eurostat Open Data +# [Computer software]. R package version 4.0.0. +# https://github.com/rOpenGov/eurostat +# +# A BibTeX entry for LaTeX users is +# +# @Misc\{eurostat, +# title = \{eurostat: Tools for Eurostat Open Data\}, +# author = \{Leo Lahti and Janne Huovari and Markus Kainu and Przemyslaw Biecek and Diego Hernangomez and Daniel Antal and Pyry Kantanen\}, +# url = \{https://github.com/rOpenGov/eurostat\}, +# type = \{Computer software\}, +# year = \{2023\}, +# note = \{R package version 4.0.0\}, +# \} +}\if{html}{\out{
    }} } \seealso{ -\code{\link{get_eurostat}}. +\code{\link[=get_eurostat]{get_eurostat()}} } \author{ -Przemyslaw Biecek, Leo Lahti and Janne Huovari \email{ropengov-forum@googlegroups.com} +Przemyslaw Biecek, Leo Lahti, Janne Huovari and Pyry Kantanen } \keyword{database} \keyword{utilities} diff --git a/man/get_eurostat_toc.Rd b/man/get_eurostat_toc.Rd index cc142b58..1efe3545 100755 --- a/man/get_eurostat_toc.Rd +++ b/man/get_eurostat_toc.Rd @@ -4,34 +4,130 @@ \alias{get_eurostat_toc} \title{Download Table of Contents of Eurostat Data Sets} \usage{ -get_eurostat_toc() +get_eurostat_toc(lang = "en") +} +\arguments{ +\item{lang}{2-letter language code, default is "\code{en}" (English), other +options are "\code{fr}" (French) and "\code{de}" (German). Used for labeling datasets.} } \value{ -A tibble with eight columns - \itemize{ - \item{title}{The name of dataset of theme} - \item{code}{The codename of dataset of theme, will be used by the eurostat and get_eurostat_raw functions.} - \item{type}{Is it a dataset, folder or table.} - \item{last.update.of.data, last.table.structure.change, data.start, data.end}{Dates.} - } +A tibble with nine columns: +\describe{ +\item{title}{Dataset title in English (default)} +\item{code}{ Each item (dataset, table and folder) of the TOC has a +unique code which allows it to be identified in the API. Used in the +\code{\link[=get_eurostat]{get_eurostat()}} and \code{\link[=get_eurostat_raw]{get_eurostat_raw()}} functions to retrieve datasets.} +\item{type}{dataset, folder or table} +\item{last.update.of.data}{Date, indicates the last time the +dataset/table was updated (format \code{DD.MM.YYYY} or \verb{\%d.\%m.\%Y})} +\item{last.table.structure.change}{Date, indicates the last time the +dataset/table structure was modified (format \code{DD.MM.YYYY} or \verb{\%d.\%m.\%Y})} +\item{data.start}{Date of the oldest value included in the dataset +(if available) (format usually \code{YYYY} or \verb{\%Y} but can also be \code{YYYY-MM}, +\code{YYYY-MM-DD}, \code{YYYY-SN}, \code{YYYY-QN} etc.)} +\item{data.end}{Date of the most recent value included in the dataset +(if available) (format usually \code{YYYY} or \verb{\%Y} but can also be \code{YYYY-MM}, +\code{YYYY-MM-DD}, \code{YYYY-SN}, \code{YYYY-QN} etc.)} +\item{values}{Number of actual values included in the dataset} +\item{hierarchy}{Hierarchy of the data navigation tree, represented +in the original txt file by a 4-spaces indentation prefix in the title} +} } \description{ Download table of contents (TOC) of eurostat datasets. } \details{ -The TOC is downloaded from \url{http://ec.europa.eu/eurostat/estat-navtree-portlet-prod/BulkDownloadListing?sort=1&file=table_of_contents_en.txt}. The values in column 'code' should be used to download a selected dataset. +In the downloaded Eurostat Table of Contents the 'code' column +values are refer to the function 'id' that is used as an argument in certain +functions when downloading datasets. } +\section{Data source: Eurostat Table of Contents}{ +The Eurostat Table of Contents (TOC) is downloaded from +\url{https://ec.europa.eu/eurostat/api/dissemination/catalogue/toc/txt?lang=en} +(default) or from French or German language variants: +\url{https://ec.europa.eu/eurostat/api/dissemination/catalogue/toc/txt?lang=fr} +\url{https://ec.europa.eu/eurostat/api/dissemination/catalogue/toc/txt?lang=de} + +See Eurostat documentation on TOC items: +\url{https://wikis.ec.europa.eu/display/EUROSTATHELP/API+-+Detailed+guidelines+-+Catalogue+API+-+TOC} +} + \examples{ -\dontrun{tmp <- get_eurostat_toc(); head(tmp)} +\dontshow{if (check_access_to_data()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\donttest{ +tmp <- get_eurostat_toc() +head(tmp) + +# Convert columns containing dates as character into Date class +# Last update of data +tmp[[4]] <- as.Date(tmp[[4]], format = c("\%d.\%m.\%Y")) +# Last table structure change +tmp[[5]] <- as.Date(tmp[[5]], format = c("\%d.\%m.\%Y")) +# Data start, contains several formats (date, week, month quarter, semester) +# Unfortunately semesters are not directly supported so they need to be +# changed into quarters +tmp$data.start <- gsub("S2", "Q3", tmp$data.start) +tmp$data.start <- lubridate::as_date( + x = tmp$data.start, + format = c("\%Y", "\%Y-Q\%q", "\%Y-W\%W", "\%Y-S\%q", "\%Y-\%m-\%d", "\%Y-\%m") + ) +# Data end, same as data start +tmp$data.end <- gsub("S2", "Q3", tmp$data.end) +tmp$data.end <- lubridate::as_date( + x = tmp$data.end, + format = c("\%Y", "\%Y-Q\%q", "\%Y-W\%W", "\%Y-S\%q", "\%Y-\%m-\%d", "\%Y-\%m") + ) +} +\dontshow{\}) # examplesIf} } \references{ -See citation("eurostat"). +See \code{citation("eurostat")}: + +\if{html}{\out{
    }}\preformatted{Kindly cite the eurostat R package as follows: + + Lahti L., Huovari J., Kainu M., and Biecek P. (2017). Retrieval and + analysis of Eurostat open data with the eurostat package. The R + Journal 9(1), pp. 385-392. doi: 10.32614/RJ-2017-019 + +A BibTeX entry for LaTeX users is + + @Article\{10.32614/RJ-2017-019, + title = \{Retrieval and Analysis of Eurostat Open Data with the eurostat Package\}, + author = \{Leo Lahti and Janne Huovari and Markus Kainu and Przemyslaw Biecek\}, + journal = \{The R Journal\}, + volume = \{9\}, + number = \{1\}, + pages = \{385--392\}, + year = \{2017\}, + doi = \{10.32614/RJ-2017-019\}, + url = \{https://doi.org/10.32614/RJ-2017-019\}, + \} + + Lahti, L., Huovari J., Kainu M., Biecek P., Hernangomez D., Antal D., + and Kantanen P. (2023). eurostat: Tools for Eurostat Open Data + [Computer software]. R package version 4.0.0. + https://github.com/rOpenGov/eurostat + +A BibTeX entry for LaTeX users is + + @Misc\{eurostat, + title = \{eurostat: Tools for Eurostat Open Data\}, + author = \{Leo Lahti and Janne Huovari and Markus Kainu and Przemyslaw Biecek and Diego Hernangomez and Daniel Antal and Pyry Kantanen\}, + url = \{https://github.com/rOpenGov/eurostat\}, + type = \{Computer software\}, + year = \{2023\}, + note = \{R package version 4.0.0\}, + \} +}\if{html}{\out{
    }} + +When citing data downloaded from Eurostat, see section "Citing Eurostat data" +in \code{\link[=get_eurostat]{get_eurostat()}} documentation. } \seealso{ -\code{\link{get_eurostat}}, \code{\link{search_eurostat}}. +\code{\link[=get_eurostat]{get_eurostat()}}, \code{\link[=search_eurostat]{search_eurostat()}} } \author{ -Przemyslaw Biecek and Leo Lahti \email{ropengov-forum@googlegroups.com} +Przemyslaw Biecek, Leo Lahti and Pyry Kantanen \href{mailto:ropengov-forum@googlegroups.com}{ropengov-forum@googlegroups.com} } \keyword{database} \keyword{utilities} diff --git a/man/harmonize_country_code.Rd b/man/harmonize_country_code.Rd index c0c3302c..27e58eb5 100755 --- a/man/harmonize_country_code.Rd +++ b/man/harmonize_country_code.Rd @@ -14,17 +14,28 @@ a vector. } \description{ The European Commission and the Eurostat generally uses ISO - 3166-1 alpha-2 codes with two exceptions: EL (not GR) is used to - represent Greece, and UK (not GB) is used to represent the - United Kingdom. This function turns country codes into to ISO - 3166-1 alpha-2. +3166-1 alpha-2 codes with two exceptions: EL (not GR) is used to +represent Greece, and UK (not GB) is used to represent the +United Kingdom. This function turns country codes into to ISO +3166-1 alpha-2. } \examples{ - \dontrun{ - lp <- get_eurostat("nama_aux_lp") - lp$geo <- harmonize_country_code(lp$geo) - } +\dontshow{if (check_access_to_data()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\donttest{ +lp <- get_eurostat("nama_10_lp_ulc") +lp$geo <- harmonize_country_code(lp$geo) +} +\dontshow{\}) # examplesIf} +} +\seealso{ +Other helpers: +\code{\link{cut_to_classes}()}, +\code{\link{dic_order}()}, +\code{\link{eurotime2date}()}, +\code{\link{eurotime2num}()}, +\code{\link{label_eurostat}()} } \author{ -Janne Huovari \email{janne.huovari@ptt.fi} +Janne Huovari \href{mailto:janne.huovari@ptt.fi}{janne.huovari@ptt.fi} } +\concept{helpers} diff --git a/man/harmonize_geo_code.Rd b/man/harmonize_geo_code.Rd new file mode 100755 index 00000000..8c9d99a7 --- /dev/null +++ b/man/harmonize_geo_code.Rd @@ -0,0 +1,43 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/deprecated_regions_functions.R +\name{harmonize_geo_code} +\alias{harmonize_geo_code} +\title{Harmonize NUTS region codes that changed with the \code{NUTS2016} +definition} +\usage{ +harmonize_geo_code(dat) +} +\arguments{ +\item{dat}{A Eurostat data frame downloaded with \code{\link[=get_eurostat]{get_eurostat()}}} +} +\value{ +An augmented data frame that explains potential problems and +possible solutions. +} +\description{ +Eurostat mixes \code{NUTS2013} and \code{NUTS2016} geographic +label codes in the \code{'geo'} column, which creates time-wise comparativity +issues. This deprecated function checked if you data is affected by this +problem and gives information on what to do. + +This function is deprecated, and a more general function was moved to +\code{\link[regions:validate_nuts_regions]{regions::validate_nuts_regions()}}. +} +\examples{ +dat <- eurostat::tgs00026 +regions::validate_nuts_regions(dat) +} +\seealso{ +\code{\link[regions:validate_nuts_regions]{regions::validate_nuts_regions()}} + +Other regions functions: +\code{\link{add_nuts_level}()}, +\code{\link{recode_to_nuts_2013}()}, +\code{\link{recode_to_nuts_2016}()}, +\code{\link{reexports}} +} +\author{ +Daniel Antal +} +\concept{regions functions} +\keyword{internal} diff --git a/man/label_eurostat.Rd b/man/label_eurostat.Rd old mode 100644 new mode 100755 index ab9ba103..21e9d855 --- a/man/label_eurostat.Rd +++ b/man/label_eurostat.Rd @@ -4,13 +4,21 @@ \alias{label_eurostat} \alias{label_eurostat_vars} \alias{label_eurostat_tables} -\title{Get Eurostat Codes} +\title{Get Eurostat Codes for data downloaded from new dissemination API} \usage{ -label_eurostat(x, dic = NULL, code = NULL, eu_order = FALSE, - lang = "en", countrycode = NULL, countrycode_nomatch = NULL, - custom_dic = NULL, fix_duplicated = FALSE) +label_eurostat( + x, + dic = NULL, + code = NULL, + eu_order = FALSE, + lang = "en", + countrycode = NULL, + countrycode_nomatch = NULL, + custom_dic = NULL, + fix_duplicated = FALSE +) -label_eurostat_vars(x, lang = "en") +label_eurostat_vars(x = NULL, id, lang = "en") label_eurostat_tables(x, lang = "en") } @@ -18,7 +26,7 @@ label_eurostat_tables(x, lang = "en") \item{x}{A character or a factor vector or a data_frame.} \item{dic}{A string (vector) naming eurostat dictionary or dictionaries. -If \code{NULL} (default) dictionry names taken from column names of +If \code{NULL} (default) dictionary names taken from column names of the data_frame.} \item{code}{For data_frames names of the column for which also code columns @@ -27,28 +35,33 @@ should be retained. The suffix "_code" is added to code column names.} \item{eu_order}{Logical. Should Eurostat ordering used for label levels. Affects only factors.} -\item{lang}{A character, code for language. Available are "en" (default), -"fr" and "de".} +\item{lang}{2-letter language code, default is "\code{en}" (English), other +options are "\code{fr}" (French) and "\code{de}" (German). Used for labeling datasets.} -\item{countrycode}{A \code{NULL} or a name of the coding scheme for -the \code{\link[countrycode]{countrycode}} +\item{countrycode}{A \code{NULL} or a name of the coding scheme for +the \code{\link[countrycode:countrycode]{countrycode::countrycode()}} to label "geo" variable with countrycode-package. It can be used to convert to short and long country names in many different languages. If \code{NULL} (default) eurostat dictionary is used instead.} -\item{countrycode_nomatch}{What to do when using the countrycode to label a "geo" and -countrycode fails to find a match, for example other than country codes like EU28. -the original code is used with +\item{countrycode_nomatch}{What to do when using the countrycode to label +a "geo" and countrycode fails to find a match, for example other than +country codes like EU28. The original code is used with a \code{NULL} (default), eurostat dictionary label is used with "eurostat", and \code{NA} is used with NA.} -\item{custom_dic}{a named vector or named list of named vectors to give an own dictionary -for (part of) codes. Names of the vector should be codes and values labels. List -can be used to spesify dictonaries and then list names should be dictionary codes.} +\item{custom_dic}{a named vector or named list of named vectors to give an +own dictionary for (part of) codes. Names of the vector should be codes +and values labels. List can be used to specify dictionaries and then +list names should be dictionary codes.} \item{fix_duplicated}{A logical. If TRUE, the code is added to the -duplicated label values. If FALSE (default) error is given if -labelling produce duplicates.} +duplicated label values. If FALSE (default) error is given if +labeling produce duplicates.} + +\item{id}{A unique identifier / code for the dataset of interest. If code is not +known \code{\link[=search_eurostat]{search_eurostat()}} function can be used to search Eurostat table +of contents.} } \value{ a vector or a data_frame. @@ -57,44 +70,71 @@ a vector or a data_frame. Get definitions for Eurostat codes from Eurostat dictionaries. } \details{ -A character or a factor vector of codes returns a corresponding - vector of definitions. \code{label_eurostat} labels also data_frames from - \code{\link{get_eurostat}}. For vectors a dictionary name have to be - supplied. For data_frames dictonary names are taken from column names. - "time" and "values" columns are returned as they were, so you can supply - data_frame from \code{\link{get_eurostat}} and get data_frame with - definitions instead of codes. - - Some Eurostat dictionaries includes dublicated labels. By default - dublicated labels cause an error, but they can be fixed automatically - with \code{fix_duplicated = TRUE}. +A character or a factor vector of codes returns a corresponding +vector of definitions. \code{\link[=label_eurostat]{label_eurostat()}} labels also data_frames from +\code{\link[=get_eurostat]{get_eurostat()}}. For vectors a dictionary name have to be +supplied. For data_frames dictionary names are taken from column names. +"time" and "values" columns are returned as they were, so you can supply +data_frame from \code{\link[=get_eurostat]{get_eurostat()}} and get data_frame with +definitions instead of codes. + +Some Eurostat dictionaries includes duplicated labels. By default +duplicated labels cause an error, but they can be fixed automatically +with \code{fix_duplicated = TRUE}. } \section{Functions}{ \itemize{ -\item \code{label_eurostat_vars}: Get definitions for variable (column) names. For -objects other than characters or factors definitions are get for names. +\item \code{label_eurostat_vars()}: Get definitions for variable (column) names. -\item \code{label_eurostat_tables}: Get definitions for table names -}} +\item \code{label_eurostat_tables()}: Get definitions for table names +}} \examples{ - \dontrun{ - lp <- get_eurostat("nama_10_lp_ulc") - lpl <- label_eurostat(lp) - str(lpl) - lpl_order <- label_eurostat(lp, eu_order = TRUE) - lpl_code <- label_eurostat(lp, code = "unit") - label_eurostat_vars(names(lp)) - label_eurostat_tables("nama_10_lp_ulc") - label_eurostat(c("FI", "DE", "EU28"), dic = "geo") - label_eurostat(c("FI", "DE", "EU28"), dic = "geo", custom_dic = c(DE = "Germany")) - label_eurostat(c("FI", "DE", "EU28"), dic = "geo", countrycode = "country.name", - custom_dic = c(EU28 = "EU")) - label_eurostat(c("FI", "DE", "EU28"), dic = "geo", countrycode = "country.name") - # In Finnish - label_eurostat(c("FI", "DE", "EU28"), dic = "geo", countrycode = "cldr.short.fi") - } +\dontrun{ +lp <- get_eurostat("nama_10_lp_ulc") +lpl <- label_eurostat(lp) +str(lpl) +lpl_order <- label_eurostat(lp, eu_order = TRUE) +lpl_code <- label_eurostat(lp, code = "unit") +# Note that the dataset id must be provided in label_eurostat_vars +label_eurostat_vars(id = "nama_10_lp_ulc", x = "geo", lang = "en") +label_eurostat_tables("nama_10_lp_ulc") +label_eurostat(c("FI", "DE", "EU28"), dic = "geo") +label_eurostat( + c("FI", "DE", "EU28"), + dic = "geo", + custom_dic = c(DE = "Germany") +) +label_eurostat( + c("FI", "DE", "EU28"), + dic = "geo", countrycode = "country.name", + custom_dic = c(EU28 = "EU") +) +label_eurostat( + c("FI", "DE", "EU28"), + dic = "geo", + countrycode = "country.name" +) +# In Finnish +label_eurostat( + c("FI", "DE", "EU28"), + dic = "geo", + countrycode = "cldr.short.fi" +) +} + +} +\seealso{ +\code{\link[countrycode:countrycode]{countrycode::countrycode()}} + +Other helpers: +\code{\link{cut_to_classes}()}, +\code{\link{dic_order}()}, +\code{\link{eurotime2date}()}, +\code{\link{eurotime2num}()}, +\code{\link{harmonize_country_code}()} } \author{ -Janne Huovari \email{janne.huovari@ptt.fi} +Janne Huovari \href{mailto:janne.huovari@ptt.fi}{janne.huovari@ptt.fi} } +\concept{helpers} diff --git a/man/list_eurostat_cache_items.Rd b/man/list_eurostat_cache_items.Rd new file mode 100644 index 00000000..7bf3317f --- /dev/null +++ b/man/list_eurostat_cache_items.Rd @@ -0,0 +1,22 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/set_eurostat_cache.R +\name{list_eurostat_cache_items} +\alias{list_eurostat_cache_items} +\title{Output cache information as data.frame} +\usage{ +list_eurostat_cache_items(cache_dir = NULL) +} +\arguments{ +\item{cache_dir}{a path to a cache directory. \code{NULL} (default) uses and creates +'eurostat' directory in the temporary directory defined by base R +\code{\link[=tempdir]{tempdir()}} function. The user can set the cache directory to an existing +directory by using this argument. The cache directory can also be set with +\code{\link[=set_eurostat_cache_dir]{set_eurostat_cache_dir()}} function.} +} +\value{ +A data.frame object with 3 columns: dataset code, download date and +query md5 hash +} +\description{ +Parses cache_list.json file and returns a data.frame +} diff --git a/man/recode_to_nuts_2013.Rd b/man/recode_to_nuts_2013.Rd new file mode 100755 index 00000000..92045a5b --- /dev/null +++ b/man/recode_to_nuts_2013.Rd @@ -0,0 +1,61 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/deprecated_regions_functions.R +\name{recode_to_nuts_2013} +\alias{recode_to_nuts_2013} +\title{Recode geo labels and rename regions from NUTS2016 to NUTS2013} +\usage{ +recode_to_nuts_2013(dat) +} +\arguments{ +\item{dat}{A Eurostat data frame downloaded with +\code{\link[=get_eurostat]{get_eurostat()}}.} +} +\value{ +An augmented and potentially relabelled data frame which +contains all formerly \code{'NUTS2013'} definition geo labels in the +\code{'NUTS2016'} vocabulary when only the code changed, but the +boundary did not. It also contains some information on other geo labels +that cannot be brought to the current \code{'NUTS2013'} definition. +Furthermore, when the official name of the region changed, it will use +the new name (if the otherwise the region boundary did not change.) +If not called before, the function will use the helper function +\code{\link[=harmonize_geo_code]{harmonize_geo_code()}} +} +\description{ +Eurostat mixes NUTS2013 and NUTS2016 geographic label codes +in the \code{'geo'} column, which creates time-wise comparativity issues. + +This function is deprecated, and a more general function was moved to +\verb{[regions::recode_nuts()]}. +} +\examples{ +test_regional_codes <- data.frame( + geo = c("FRB", "FRE", "UKN02", "IE022", "FR243", "FRB03"), + time = c(rep(as.Date("2014-01-01"), 5), as.Date("2015-01-01")), + values = c(1:6), + control = c( + "Changed from NUTS2 to NUTS1", + "New region NUTS2016 only", + "Discontinued region NUTS2013", + "Boundary shift NUTS2013", + "Recoded in NUTS2013", + "Recoded in NUTS2016" + ) +) + +recode_to_nuts_2013(test_regional_codes) +} +\seealso{ +\code{\link[regions:recode_nuts]{regions::recode_nuts()}} + +Other regions functions: +\code{\link{add_nuts_level}()}, +\code{\link{harmonize_geo_code}()}, +\code{\link{recode_to_nuts_2016}()}, +\code{\link{reexports}} +} +\author{ +Daniel Antal +} +\concept{regions functions} +\keyword{internal} diff --git a/man/recode_to_nuts_2016.Rd b/man/recode_to_nuts_2016.Rd new file mode 100755 index 00000000..65317ef5 --- /dev/null +++ b/man/recode_to_nuts_2016.Rd @@ -0,0 +1,61 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/deprecated_regions_functions.R +\name{recode_to_nuts_2016} +\alias{recode_to_nuts_2016} +\title{Recode geo labels and rename regions from NUTS2013 to NUTS2016} +\usage{ +recode_to_nuts_2016(dat) +} +\arguments{ +\item{dat}{A Eurostat data frame downloaded with +\code{\link[=get_eurostat]{get_eurostat()}}.} +} +\value{ +An augmented and potentially relabelled data frame which +contains all formerly \code{'NUTS2013'} definition geo labels in the +\code{'NUTS2016'} vocabulary when only the code changed, but the +boundary did not. It also contains some information on other geo labels +that cannot be brought to the current \code{'NUTS2016'} definition. +Furthermore, when the official name of the region changed, it will use +the new name (if the otherwise the region boundary did not change.) +If not called before, the function will use the helper function +\code{\link[=harmonize_geo_code]{harmonize_geo_code()}} +} +\description{ +Eurostat mixes NUTS2013 and NUTS2016 geographic label codes +in the \code{'geo'} column, which creates time-wise comparativity issues. + +This function is deprecated, and a more general function was moved to +\verb{[regions::recode_nuts()]}. +} +\examples{ +test_regional_codes <- data.frame( + geo = c("FRB", "FRE", "UKN02", "IE022", "FR243", "FRB03"), + time = c(rep(as.Date("2014-01-01"), 5), as.Date("2015-01-01")), + values = c(1:6), + control = c( + "Changed from NUTS2 to NUTS1", + "New region NUTS2016 only", + "Discontinued region NUTS2013", + "Boundary shift NUTS2013", + "Recoded in NUTS2013", + "Recoded in NUTS2016" + ) +) + +recode_to_nuts_2016(test_regional_codes) +} +\seealso{ +\code{\link[regions:recode_nuts]{regions::recode_nuts()}} + +Other regions functions: +\code{\link{add_nuts_level}()}, +\code{\link{harmonize_geo_code}()}, +\code{\link{recode_to_nuts_2013}()}, +\code{\link{reexports}} +} +\author{ +Daniel Antal +} +\concept{regions functions} +\keyword{internal} diff --git a/man/reexports.Rd b/man/reexports.Rd new file mode 100644 index 00000000..d2b0e04f --- /dev/null +++ b/man/reexports.Rd @@ -0,0 +1,124 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/regional_coding_functions.R +\docType{import} +\name{reexports} +\alias{reexports} +\alias{recode_nuts} +\alias{validate_nuts_regions} +\alias{validate_geo_code} +\title{Recode Region Codes From Source To Target NUTS Typology} +\arguments{ +\item{dat}{A data frame with a 3-5 character \code{geo_var} +variable to be validated.} + +\item{geo_var}{Defaults to \code{"geo"}. The variable that contains +the 3-5 character geo codes to be validated.} + +\item{geo}{A vector of geographical code to validate.} + +\item{nuts_year}{A valid NUTS edition year.} +} +\value{ +The original data frame with a \code{'geo_var'} column is extended +with a \code{'typology'} column that states in which typology is the \code{'geo_var'} +a valid code. For invalid codes, looks up potential reasons of invalidity +and adds them to the \code{'typology_change'} column, and at last it +adds a column of character vector containing the desired codes in the +target typology, for example, in the NUTS2013 typology. + +Returns the original \code{dat} data frame with a column +that specifies the comformity with the NUTS definition of the year +\code{nuts_year}. + +A character list with the valid typology, or 'invalid' in the cases +when the geo coding is not valid. +} +\details{ +While country codes are technically not part of the NUTS typologies, +Eurostat de facto uses a \code{NUTS0} typology to identify countries. +This de facto typology has three exception which are handled by the +\link[regions:validate_nuts_countries]{validate_nuts_countries} function. + +NUTS typologies have different versions, therefore the conformity +is validated with one specific versions, which can be any of these: +\code{1999}, \code{2003}, \code{2006}, \code{2010}, +\code{2013}, the currently used \code{2016} and the already +announced and defined \code{2021}. + +The NUTS typology was codified with the \code{NUTS2003}, and the +pre-1999 NUTS typologies may confuse programmatic data processing, +given that some NUTS1 regions were identified with country codes +in smaller countries that had no \code{NUTS1} divisions. + +Currently the \code{2016} is used by Eurostat, but many datasets +still contain \code{2013} and sometimes earlier metadata. +} +\examples{ +{ +foo <- data.frame ( + geo = c("FR", "DEE32", "UKI3" , + "HU12", "DED", + "FRK"), + values = runif(6, 0, 100 ), + stringsAsFactors = FALSE ) + +recode_nuts(foo, nuts_year = 2013) +} +\donttest{ +my_reg_data <- data.frame( + geo = c( + "BE1", "HU102", "FR1", + "DED", "FR7", "TR", "DED2", + "EL", "XK", "GB" + ), + values = runif(10) +) + +validate_nuts_regions(my_reg_data) + +validate_nuts_regions(my_reg_data, nuts_year = 2013) + +validate_nuts_regions(my_reg_data, nuts_year = 2003) +} +\donttest{ +my_reg_data <- data.frame( + geo = c( + "BE1", "HU102", "FR1", + "DED", "FR7", "TR", "DED2", + "EL", "XK", "GB" + ), + values = runif(10) +) + +validate_geo_code(my_reg_data$geo) +} +} +\seealso{ +Other regions functions: +\code{\link{add_nuts_level}()}, +\code{\link{harmonize_geo_code}()}, +\code{\link{recode_to_nuts_2013}()}, +\code{\link{recode_to_nuts_2016}()} + +Other regions functions: +\code{\link{add_nuts_level}()}, +\code{\link{harmonize_geo_code}()}, +\code{\link{recode_to_nuts_2013}()}, +\code{\link{recode_to_nuts_2016}()} + +Other regions functions: +\code{\link{add_nuts_level}()}, +\code{\link{harmonize_geo_code}()}, +\code{\link{recode_to_nuts_2013}()}, +\code{\link{recode_to_nuts_2016}()} +} +\concept{regions functions} +\keyword{internal} +\description{ +These objects are imported from other packages. Follow the links +below to see their documentation. + +\describe{ + \item{regions}{\code{\link[regions]{recode_nuts}}, \code{\link[regions]{validate_geo_code}}, \code{\link[regions]{validate_nuts_regions}}} +}} + diff --git a/man/search_eurostat.Rd b/man/search_eurostat.Rd index b0bae44e..2f96125b 100755 --- a/man/search_eurostat.Rd +++ b/man/search_eurostat.Rd @@ -2,64 +2,140 @@ % Please edit documentation in R/search_eurostat.R \name{search_eurostat} \alias{search_eurostat} -\alias{grepEurostatTOC} \title{Grep Datasets Titles from Eurostat} \usage{ -search_eurostat(pattern, type = "dataset", fixed = TRUE) - -grepEurostatTOC(pattern, type = "dataset") +search_eurostat( + pattern, + type = "dataset", + column = "title", + fixed = TRUE, + lang = "en" +) } \arguments{ -\item{pattern}{Character, datasets, folder or tables with this pattern in -the description will be returned (depending on the 'type' argument)} +\item{pattern}{Text string that is used to search from dataset, folder or table titles, +depending on the type argument.} + +\item{type}{Selection for types of datasets to be searched. Default is \code{dataset}, other +possible options are \code{table}, \code{folder} and \code{all} for all types.} -\item{type}{Grep the Eurostat table of contents either for -'dataset' (default), 'folder', 'table' or "all" (for all types).} +\item{column}{Selection for the column of TOC where search is done. Default is \code{title}, +other possible option is \code{code}.} -\item{fixed}{logical. If TRUE, pattern is a string to be matched as is. -Change to FALSE if more complex regex matching is needed.} +\item{fixed}{logical. If TRUE (default), pattern is a string to be matched as is. +See \code{grep()} documentation for more information.} + +\item{lang}{2-letter language code, default is "\code{en}" (English), other +options are "\code{fr}" (French) and "\code{de}" (German). Used for labeling datasets.} } \value{ -A tibble with eight columns - \itemize{ - \item{title}{The name of dataset of theme} -\item{code}{The codename of dataset of theme, will be used by the get_eurostat and get_eurostat_raw functions.} -\item{type}{Is it a dataset, folder or table.} -\item{last.update.of.data, last.table.structure.change, data.start, data.end}{Dates.} - } +A tibble with nine columns: +\describe{ +\item{title}{Dataset title in English (default)} +\item{code}{ Each item (dataset, table and folder) of the TOC has a +unique code which allows it to be identified in the API. Used in the +\code{\link[=get_eurostat]{get_eurostat()}} and \code{\link[=get_eurostat_raw]{get_eurostat_raw()}} functions to retrieve datasets.} +\item{type}{dataset, folder or table} +\item{last.update.of.data}{Date, indicates the last time the +dataset/table was updated (format \code{DD.MM.YYYY} or \verb{\%d.\%m.\%Y})} +\item{last.table.structure.change}{Date, indicates the last time the +dataset/table structure was modified (format \code{DD.MM.YYYY} or \verb{\%d.\%m.\%Y})} +\item{data.start}{Date of the oldest value included in the dataset +(if available) (format usually \code{YYYY} or \verb{\%Y} but can also be \code{YYYY-MM}, +\code{YYYY-MM-DD}, \code{YYYY-SN}, \code{YYYY-QN} etc.)} +\item{data.end}{Date of the most recent value included in the dataset +(if available) (format usually \code{YYYY} or \verb{\%Y} but can also be \code{YYYY-MM}, +\code{YYYY-MM-DD}, \code{YYYY-SN}, \code{YYYY-QN} etc.)} +\item{values}{Number of actual values included in the dataset} +\item{hierarchy}{Hierarchy of the data navigation tree, represented +in the original txt file by a 4-spaces indentation prefix in the title} +} } \description{ -Lists names of dataset from eurostat with the particular -pattern in the description. +Lists datasets from eurostat table of contents with the +particular pattern in item titles. } \details{ Downloads list of all datasets available on eurostat and return list of names of datasets that contains particular pattern in the dataset description. E.g. all datasets related to education of teaching. + +If you wish to perform searches on other fields than item title, +you can download the Eurostat Table of Contents manually using +\code{get_eurostat_toc()} function and use \code{grep()} function normally. The data +browser on Eurostat website may also return useful results. +} +\section{Data source: Eurostat Table of Contents}{ +The Eurostat Table of Contents (TOC) is downloaded from +\url{https://ec.europa.eu/eurostat/api/dissemination/catalogue/toc/txt?lang=en} +(default) or from French or German language variants: +\url{https://ec.europa.eu/eurostat/api/dissemination/catalogue/toc/txt?lang=fr} +\url{https://ec.europa.eu/eurostat/api/dissemination/catalogue/toc/txt?lang=de} + +See Eurostat documentation on TOC items: +\url{https://wikis.ec.europa.eu/display/EUROSTATHELP/API+-+Detailed+guidelines+-+Catalogue+API+-+TOC} } -\section{Functions}{ -\itemize{ -\item \code{grepEurostatTOC}: Old deprecated version -}} \examples{ -\dontrun{ - tmp <- search_eurostat("education") - head(tmp) - # Use "fixed = TRUE" when pattern has characters that would need escaping. - # Here, parentheses would normally need to be escaped in regex - tmp <- search_eurostat("Live births (total) by NUTS 3 region", fixed = TRUE) +\dontshow{if (check_access_to_data()) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf} +\donttest{ +tmp <- search_eurostat("education") +head(tmp) +# Use "fixed = TRUE" when pattern has characters that would need escaping. +# Here, parentheses would normally need to be escaped in regex +tmp <- search_eurostat("Live births (total) by NUTS 3 region", fixed = TRUE) } +\dontshow{\}) # examplesIf} } \references{ -See citation("eurostat") +See \code{citation("eurostat")}: + +\if{html}{\out{
    }}\preformatted{Kindly cite the eurostat R package as follows: + + Lahti L., Huovari J., Kainu M., and Biecek P. (2017). Retrieval and + analysis of Eurostat open data with the eurostat package. The R + Journal 9(1), pp. 385-392. doi: 10.32614/RJ-2017-019 + +A BibTeX entry for LaTeX users is + + @Article\{10.32614/RJ-2017-019, + title = \{Retrieval and Analysis of Eurostat Open Data with the eurostat Package\}, + author = \{Leo Lahti and Janne Huovari and Markus Kainu and Przemyslaw Biecek\}, + journal = \{The R Journal\}, + volume = \{9\}, + number = \{1\}, + pages = \{385--392\}, + year = \{2017\}, + doi = \{10.32614/RJ-2017-019\}, + url = \{https://doi.org/10.32614/RJ-2017-019\}, + \} + + Lahti, L., Huovari J., Kainu M., Biecek P., Hernangomez D., Antal D., + and Kantanen P. (2023). eurostat: Tools for Eurostat Open Data + [Computer software]. R package version 4.0.0. + https://github.com/rOpenGov/eurostat + +A BibTeX entry for LaTeX users is + + @Misc\{eurostat, + title = \{eurostat: Tools for Eurostat Open Data\}, + author = \{Leo Lahti and Janne Huovari and Markus Kainu and Przemyslaw Biecek and Diego Hernangomez and Daniel Antal and Pyry Kantanen\}, + url = \{https://github.com/rOpenGov/eurostat\}, + type = \{Computer software\}, + year = \{2023\}, + note = \{R package version 4.0.0\}, + \} +}\if{html}{\out{
    }} + +When citing data downloaded from Eurostat, see section "Citing Eurostat data" +in \code{\link[=get_eurostat]{get_eurostat()}} documentation. } \seealso{ -\code{\link{get_eurostat}}, \code{\link{get_eurostat_toc}} +\code{\link[=get_eurostat]{get_eurostat()}}, \code{\link[=search_eurostat]{search_eurostat()}} } \author{ -Przemyslaw Biecek and Leo Lahti \email{ropengov-forum@googlegroups.com} +Przemyslaw Biecek and Leo Lahti \href{mailto:ropengov-forum@googlegroups.com}{ropengov-forum@googlegroups.com} } \keyword{database} \keyword{utilities} diff --git a/man/set_eurostat_cache_dir.Rd b/man/set_eurostat_cache_dir.Rd new file mode 100644 index 00000000..df9e50e9 --- /dev/null +++ b/man/set_eurostat_cache_dir.Rd @@ -0,0 +1,71 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/set_eurostat_cache.R +\name{set_eurostat_cache_dir} +\alias{set_eurostat_cache_dir} +\title{Set Eurostat Cache} +\usage{ +set_eurostat_cache_dir( + cache_dir, + overwrite = FALSE, + install = FALSE, + verbose = TRUE +) +} +\arguments{ +\item{cache_dir}{A path to a cache directory. On missing value the function +would store the cached files on a temporary dir (See +\code{\link[base:tempfile]{base::tempdir()}}).} + +\item{overwrite}{If this is set to \code{TRUE}, it will overwrite an existing +\code{EUROSTAT_CACHE_DIR} that you already have in local machine.} + +\item{install}{if \code{TRUE}, will install the key in your local machine for +use in future sessions. Defaults to \code{FALSE}. If \code{cache_dir} is +\code{FALSE} this parameter is set to \code{FALSE} automatically.} + +\item{verbose}{Logical, displays information. Useful for debugging, +default is \code{FALSE}.} +} +\value{ +An (invisible) character with the path to your \code{cache_dir}. +} +\description{ +This function will store your \code{cache_dir} path on your local machine +and would load it for future sessions. Type +\code{Sys.getenv("EUROSTAT_CACHE_DIR")} to +find your cached path. + +Alternatively, you can store the \code{cache_dir} manually with the following +options: +\itemize{ +\item Run \code{Sys.setenv(EUROSTAT_CACHE_DIR = "cache_dir")}. You +would need to run this command on each session +(Similar to \code{install = FALSE}). +\item Set \code{options(eurostat_cache_dir = "cache_dir")}. Similar to +the previous option. This is provided for backwards compatibility +purposes. +\item Write this line on your .Renviron file: +\code{EUROSTAT_CACHE_DIR = "value_for_cache_dir"} (same behavior than +\code{install = TRUE}). This would store your \code{cache_dir} +permanently. +} +} +\examples{ + +# Don't run this! It would modify your current state +\dontrun{ +set_eurostat_cache_dir(verbose = TRUE) +} + +Sys.getenv("EUROSTAT_CACHE_DIR") +} +\seealso{ +\code{\link[rappdirs:user_data_dir]{rappdirs::user_config_dir()}} + +Other cache utilities: +\code{\link{clean_eurostat_cache}()} +} +\author{ +Diego Hernangómez +} +\concept{cache utilities} diff --git a/man/set_eurostat_toc.Rd b/man/set_eurostat_toc.Rd index 4d2a64da..1dd96891 100755 --- a/man/set_eurostat_toc.Rd +++ b/man/set_eurostat_toc.Rd @@ -4,10 +4,11 @@ \alias{set_eurostat_toc} \title{Set Eurostat TOC} \usage{ -set_eurostat_toc(...) +set_eurostat_toc(lang = "en") } \arguments{ -\item{...}{Arguments to be passed} +\item{lang}{2-letter language code, default is "\code{en}" (English), other +options are "\code{fr}" (French) and "\code{de}" (German). Used for labeling datasets.} } \value{ Empty element @@ -18,7 +19,11 @@ Internal function. \references{ see citation("eurostat") } +\seealso{ +\code{\link[=get_eurostat_toc]{get_eurostat_toc()}} \code{\link[=toc_count_children]{toc_count_children()}} \code{\link[=toc_determine_hierarchy]{toc_determine_hierarchy()}} +\code{\link[=toc_list_children]{toc_list_children()}} \code{\link[=toc_count_whitespace]{toc_count_whitespace()}} +} \author{ -Przemyslaw Biecek and Leo Lahti \email{ropengov-forum@googlegroups.com} +Przemyslaw Biecek and Leo Lahti \href{mailto:ropengov-forum@googlegroups.com}{ropengov-forum@googlegroups.com} } \keyword{internal} diff --git a/man/tgs00026.Rd b/man/tgs00026.Rd index 74299d89..548e1dfc 100755 --- a/man/tgs00026.Rd +++ b/man/tgs00026.Rd @@ -4,7 +4,9 @@ \name{tgs00026} \alias{tgs00026} \title{Auxiliary Data} -\format{data_frame} +\format{ +data_frame +} \usage{ tgs00026 } @@ -12,6 +14,14 @@ tgs00026 Auxiliary Data Sets } \details{ +Disposable income of private households by NUTS 2 regions Retrieved with: \code{tgs00026 <- get_eurostat("tgs00026", time_format = "raw") } +Data retrieval date: 2022-06-27 +} +\seealso{ +Other datasets: +\code{\link{eu_countries}}, +\code{\link{eurostat_geodata_60_2016}} } +\concept{datasets} \keyword{datasets} diff --git a/man/tidy_eurostat.Rd b/man/tidy_eurostat.Rd index d542c23e..55156ae6 100755 --- a/man/tidy_eurostat.Rd +++ b/man/tidy_eurostat.Rd @@ -4,47 +4,118 @@ \alias{tidy_eurostat} \title{Transform Data into Row-Column-Value Format} \usage{ -tidy_eurostat(dat, time_format = "date", select_time = NULL, - stringsAsFactors = default.stringsAsFactors(), keepFlags = FALSE) +tidy_eurostat( + dat, + time_format = "date", + select_time = NULL, + stringsAsFactors = FALSE, + keepFlags = FALSE, + use.data.table = FALSE +) } \arguments{ -\item{dat}{a data_frame from \code{\link{get_eurostat_raw}}.} +\item{dat}{a data_frame from \code{\link[=get_eurostat_raw]{get_eurostat_raw()}}.} -\item{time_format}{a string giving a type of the conversion of the - time column from the eurostat format. - A "date" (default) convers to a \code{\link{Date}} - with a first date of the period. A "date_last" - convers to a \code{\link{Date}} with -a last date of the period. A "num" convers to a numeric and "raw" -does not do conversion. See \code{\link{eurotime2date}} and -\code{\link{eurotime2num}}.} +\item{time_format}{a string giving a type of the conversion of the time column from the +eurostat format. The default argument "\code{date}" converts to a \code{\link[=Date]{Date()}} class +with the date being the first day of the period. A "\code{date_last}" argument +converts the dataset date to a \code{\link[=Date]{Date()}} class object with the difference +that the exact date is the last date of the period. Period can be year, +semester (half year), quarter, month, or week (See \code{\link[=eurotime2date]{eurotime2date()}} for +more information). +Argument "\code{num}" converts the date into a numeric (integer) meaning that +the first day of the year 2000 is close to 2000.01 and the last day of the +year is close to 2000.99 (see \code{\link[=eurotime2num]{eurotime2num()}} for more information). +Using the argument "\code{raw}" preserves the dates as they were in the original +Eurostat data.} -\item{select_time}{a character symbol for a time frequence or NULL -(default).} +\item{select_time}{a character symbol for a time frequency or \code{NULL}, +which is used by default as most datasets have just one time +frequency. For datasets with multiple time +frequencies, select one or more of the desired frequencies with: +"Y" (or "A") = annual, "S" = semi-annual / semester, "Q" = quarterly, +"M" = monthly, "W" = weekly. For all frequencies in same data +frame \code{time_format = "raw"} should be used.} -\item{stringsAsFactors}{if \code{TRUE} (the default) variables are -converted to factors in original Eurostat order. If \code{FALSE} -they are returned as strings.} +\item{stringsAsFactors}{if \code{TRUE} (the default) variables are converted to factors in the original +Eurostat order. If \code{FALSE} they are returned as strings.} \item{keepFlags}{a logical whether the flags (e.g. "confidential", "provisional") should be kept in a separate column or if they -can be removed. Default is \code{FALSE}} +can be removed. Default is \code{FALSE}. For flag values see: +\url{https://ec.europa.eu/eurostat/data/database/information}. +Also possible non-real zero "0n" is indicated in flags column. +Flags are not available for eurostat API, so \code{keepFlags} +can not be used with a \code{filters}.} + +\item{use.data.table}{Use faster data.table functions? Default is FALSE. +On Windows requires that RTools is installed.} } \value{ -tibble in the molten format with the last column 'values'. +tibble in the melted format with the last column 'values'. } \description{ -Transform raw Eurostat data table into the row-column-value -format (RCV). +Transform raw Eurostat data table downloaded from the +API into a tidy row-column-value format (RCV). +} +\examples{ +\dontrun{ +# Example of a dataset with multiple time series +get_eurostat("AVIA_GOR_ME", + time_format = "date_last", + cache = F + ) +} + } \references{ -See citation("eurostat"). +See \code{citation("eurostat")}: + +\if{html}{\out{
    }}\preformatted{Kindly cite the eurostat R package as follows: + + Lahti L., Huovari J., Kainu M., and Biecek P. (2017). Retrieval and + analysis of Eurostat open data with the eurostat package. The R + Journal 9(1), pp. 385-392. doi: 10.32614/RJ-2017-019 + +A BibTeX entry for LaTeX users is + + @Article\{10.32614/RJ-2017-019, + title = \{Retrieval and Analysis of Eurostat Open Data with the eurostat Package\}, + author = \{Leo Lahti and Janne Huovari and Markus Kainu and Przemyslaw Biecek\}, + journal = \{The R Journal\}, + volume = \{9\}, + number = \{1\}, + pages = \{385--392\}, + year = \{2017\}, + doi = \{10.32614/RJ-2017-019\}, + url = \{https://doi.org/10.32614/RJ-2017-019\}, + \} + + Lahti, L., Huovari J., Kainu M., Biecek P., Hernangomez D., Antal D., + and Kantanen P. (2023). eurostat: Tools for Eurostat Open Data + [Computer software]. R package version 4.0.0. + https://github.com/rOpenGov/eurostat + +A BibTeX entry for LaTeX users is + + @Misc\{eurostat, + title = \{eurostat: Tools for Eurostat Open Data\}, + author = \{Leo Lahti and Janne Huovari and Markus Kainu and Przemyslaw Biecek and Diego Hernangomez and Daniel Antal and Pyry Kantanen\}, + url = \{https://github.com/rOpenGov/eurostat\}, + type = \{Computer software\}, + year = \{2023\}, + note = \{R package version 4.0.0\}, + \} +}\if{html}{\out{
    }} + +When citing data downloaded from Eurostat, see section "Citing Eurostat data" +in \code{\link[=get_eurostat]{get_eurostat()}} documentation. } \seealso{ -\code{\link{get_eurostat}} +\code{\link[=get_eurostat]{get_eurostat()}}, \code{\link[=convert_time_col]{convert_time_col()}}, \code{\link[=eurotime2date]{eurotime2date()}} } \author{ -Przemyslaw Biecek, Leo Lahti and Janne Huovari \email{ropengov-forum@googlegroups.com} \url{http://github.com/ropengov/eurostat} +Przemyslaw Biecek, Leo Lahti, Janne Huovari and Pyry Kantanen } \keyword{database} \keyword{internal} diff --git a/man/toc_count_children.Rd b/man/toc_count_children.Rd new file mode 100644 index 00000000..2822d9a1 --- /dev/null +++ b/man/toc_count_children.Rd @@ -0,0 +1,22 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/set_eurostat_toc.R +\name{toc_count_children} +\alias{toc_count_children} +\title{Count number of children} +\usage{ +toc_count_children(code) +} +\arguments{ +\item{code}{Eurostat TOC item code (folder, dataset, table)} +} +\description{ +Determine how many children a certain TOC item (usually a folder) has. +} +\seealso{ +\code{\link[=get_eurostat_toc]{get_eurostat_toc()}} \code{\link[=toc_count_children]{toc_count_children()}} \code{\link[=toc_determine_hierarchy]{toc_determine_hierarchy()}} +\code{\link[=toc_list_children]{toc_list_children()}} \code{\link[=toc_count_whitespace]{toc_count_whitespace()}} +} +\author{ +Pyry Kantanen +} +\keyword{internal} diff --git a/man/toc_count_whitespace.Rd b/man/toc_count_whitespace.Rd new file mode 100644 index 00000000..ca7f08e1 --- /dev/null +++ b/man/toc_count_whitespace.Rd @@ -0,0 +1,47 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/set_eurostat_toc.R +\name{toc_count_whitespace} +\alias{toc_count_whitespace} +\title{Count white space at the start of the title} +\usage{ +toc_count_whitespace(input_string) +} +\arguments{ +\item{input_string}{A string containing Eurostat TOC titles} +} +\value{ +Numeric (number of white space characters) +} +\description{ +Counts the number of white space characters at the start +of the string. +} +\details{ +Used in toc_determine_hierarchy function to determine hierarchy. +Hierarchy is defined in Eurostat .txt format TOC files by the number of +white space characters at intervals of four. For example, +" Foo" (4 white space characters) is one level higher than +" Bar" (8 white space characters). +"Database by themes" (0 white space characters before the first +alphanumeric character) is highest in the hierarchy. + +The function will return a warning if the input has white space in anything +else than as increments of 4. 0, 4, 8... are acceptable but 3, 6, 10... +are not. +} +\examples{ +strings <- c(" abc", " cdf", "no_spaces") +for (string in strings) { + whitespace_count <- eurostat:::toc_count_whitespace(string) + cat("String:", string, "\tWhitespace Count:", whitespace_count, "\n") +} + +} +\seealso{ +\code{\link[=get_eurostat_toc]{get_eurostat_toc()}} \code{\link[=toc_count_children]{toc_count_children()}} \code{\link[=toc_determine_hierarchy]{toc_determine_hierarchy()}} +\code{\link[=toc_list_children]{toc_list_children()}} \code{\link[=toc_count_whitespace]{toc_count_whitespace()}} +} +\author{ +Pyry Kantanen +} +\keyword{internal} diff --git a/man/toc_determine_hierarchy.Rd b/man/toc_determine_hierarchy.Rd new file mode 100644 index 00000000..584ca2f8 --- /dev/null +++ b/man/toc_determine_hierarchy.Rd @@ -0,0 +1,44 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/set_eurostat_toc.R +\name{toc_determine_hierarchy} +\alias{toc_determine_hierarchy} +\title{Determine level in hierarchy} +\usage{ +toc_determine_hierarchy(input_string) +} +\arguments{ +\item{input_string}{A string containing Eurostat TOC titles} +} +\value{ +Numeric +} +\description{ +Divides the number of spaces before alphanumeric characters +with 4 and uses the result to determine hierarchy. Top level is 0. +} +\details{ +Used in toc_determine_hierarchy function to determine hierarchy. +Hierarchy is defined in Eurostat .txt format TOC files by the number of +white space characters at intervals of four. For example, +" Foo" (4 white space characters) is one level higher than +" Bar" (8 white space characters). +"Database by themes" (0 white space characters before the first +alphanumeric character) is highest in the hierarchy. + +The function will return a warning if the input has white space in anything +else than as increments of 4. 0, 4, 8... are acceptable but 3, 6, 10... +are not. +} +\examples{ +strings <- c(" abc", " cdf", "no_spaces") +eurostat:::toc_determine_hierarchy(strings) + +} +\seealso{ +\code{\link[=get_eurostat_toc]{get_eurostat_toc()}} \code{\link[=toc_count_children]{toc_count_children()}} \code{\link[=toc_determine_hierarchy]{toc_determine_hierarchy()}} +\code{\link[=toc_list_children]{toc_list_children()}} \code{\link[=toc_count_whitespace]{toc_count_whitespace()}} +} +\author{ +Pyry Kantanen +} +\keyword{internal} diff --git a/man/toc_list_children.Rd b/man/toc_list_children.Rd new file mode 100644 index 00000000..69d8c769 --- /dev/null +++ b/man/toc_list_children.Rd @@ -0,0 +1,22 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/set_eurostat_toc.R +\name{toc_list_children} +\alias{toc_list_children} +\title{List children} +\usage{ +toc_list_children(code) +} +\arguments{ +\item{code}{Eurostat TOC item code (folder, dataset, table)} +} +\description{ +List children of a specific folder. +} +\seealso{ +\code{\link[=get_eurostat_toc]{get_eurostat_toc()}} \code{\link[=toc_count_children]{toc_count_children()}} \code{\link[=toc_determine_hierarchy]{toc_determine_hierarchy()}} +\code{\link[=toc_list_children]{toc_list_children()}} \code{\link[=toc_count_whitespace]{toc_count_whitespace()}} +} +\author{ +Pyry Kantanen +} +\keyword{internal} diff --git a/pkgdown/_pkgdown.yml b/pkgdown/_pkgdown.yml new file mode 100644 index 00000000..fd46adc1 --- /dev/null +++ b/pkgdown/_pkgdown.yml @@ -0,0 +1,22 @@ +url: https://ropengov.github.io/eurostat/ +template: + package: rogtemplate +reference: +- title: Get data from Eurostat + contents: + - starts_with("get_") + - starts_with("search_") +- title: Access and Cache management + contents: + - has_concept("cache utilities") + - check_access_to_data + - list_eurostat_cache_items +- title: Additional functions + contents: has_concept("helpers") +- title: Datasets + contents: has_concept("datasets") +- title: About the package + contents: eurostat +- title: Deprecated or defunct + contents: + - eurostat-defunct diff --git a/pkgdown/favicon/apple-touch-icon-120x120.png b/pkgdown/favicon/apple-touch-icon-120x120.png new file mode 100644 index 00000000..28060347 Binary files /dev/null and b/pkgdown/favicon/apple-touch-icon-120x120.png differ diff --git a/pkgdown/favicon/apple-touch-icon-152x152.png b/pkgdown/favicon/apple-touch-icon-152x152.png new file mode 100644 index 00000000..cb3ea573 Binary files /dev/null and b/pkgdown/favicon/apple-touch-icon-152x152.png differ diff --git a/pkgdown/favicon/apple-touch-icon-180x180.png b/pkgdown/favicon/apple-touch-icon-180x180.png new file mode 100644 index 00000000..b6072805 Binary files /dev/null and b/pkgdown/favicon/apple-touch-icon-180x180.png differ diff --git a/pkgdown/favicon/apple-touch-icon-60x60.png b/pkgdown/favicon/apple-touch-icon-60x60.png new file mode 100644 index 00000000..fdb28572 Binary files /dev/null and b/pkgdown/favicon/apple-touch-icon-60x60.png differ diff --git a/pkgdown/favicon/apple-touch-icon-76x76.png b/pkgdown/favicon/apple-touch-icon-76x76.png new file mode 100644 index 00000000..3ce3a25f Binary files /dev/null and b/pkgdown/favicon/apple-touch-icon-76x76.png differ diff --git a/pkgdown/favicon/apple-touch-icon.png b/pkgdown/favicon/apple-touch-icon.png new file mode 100644 index 00000000..b02012c0 Binary files /dev/null and b/pkgdown/favicon/apple-touch-icon.png differ diff --git a/pkgdown/favicon/favicon-16x16.png b/pkgdown/favicon/favicon-16x16.png new file mode 100644 index 00000000..97bce6f0 Binary files /dev/null and b/pkgdown/favicon/favicon-16x16.png differ diff --git a/pkgdown/favicon/favicon-32x32.png b/pkgdown/favicon/favicon-32x32.png new file mode 100644 index 00000000..ef5d20de Binary files /dev/null and b/pkgdown/favicon/favicon-32x32.png differ diff --git a/pkgdown/favicon/favicon.ico b/pkgdown/favicon/favicon.ico new file mode 100644 index 00000000..0a4d4605 Binary files /dev/null and b/pkgdown/favicon/favicon.ico differ diff --git a/revdep/.gitignore b/revdep/.gitignore new file mode 100644 index 00000000..31f6c40d --- /dev/null +++ b/revdep/.gitignore @@ -0,0 +1,6 @@ +checks +library +checks.noindex +library.noindex +data.sqlite +*.html diff --git a/revdep/README.md b/revdep/README.md new file mode 100644 index 00000000..5aceec41 --- /dev/null +++ b/revdep/README.md @@ -0,0 +1,85 @@ +# Platform + +|field |value | +|:--------|:------------------------------------------| +|version |R version 4.3.1 (2023-06-16 ucrt) | +|os |Windows 11 x64 (build 22621) | +|system |x86_64, mingw32 | +|ui |RStudio | +|language |(EN) | +|collate |Spanish_Spain.utf8 | +|ctype |Spanish_Spain.utf8 | +|tz |Europe/Madrid | +|date |2023-07-01 | +|rstudio |2023.06.0+421 Mountain Hydrangea (desktop) | +|pandoc |2.19.2 @ C:\PROGRA~1\Pandoc\pandoc.exe | + +# Dependencies + +|package |old |new |Δ | +|:-----------|:------|:----------|:--| +|eurostat |3.8.2 |4.0.0.9002 |* | +|askpass |1.1 |1.1 | | +|assertthat |0.2.1 |0.2.1 | | +|backports |1.4.1 |1.4.1 | | +|bibtex |0.5.1 |0.5.1 | | +|bit |4.0.5 |4.0.5 | | +|bit64 |4.0.5 |4.0.5 | | +|broom |1.0.5 |NA |* | +|cellranger |1.1.0 |1.1.0 | | +|classInt |0.4-9 |0.4-9 | | +|cli |3.6.1 |3.6.1 | | +|clipr |0.8.0 |0.8.0 | | +|countrycode |1.5.0 |1.5.0 | | +|cpp11 |0.4.4 |0.4.4 | | +|crayon |1.5.2 |1.5.2 | | +|curl |5.0.1 |5.0.1 | | +|dplyr |1.1.2 |1.1.2 | | +|e1071 |1.7-13 |1.7-13 | | +|ellipsis |0.3.2 |NA |* | +|fansi |1.0.4 |1.0.4 | | +|generics |0.1.3 |0.1.3 | | +|glue |1.6.2 |1.6.2 | | +|here |1.0.1 |1.0.1 | | +|hms |1.1.3 |1.1.3 | | +|httr |1.4.6 |1.4.6 | | +|ISOweek |0.6-2 |0.6-2 | | +|jsonlite |1.8.7 |1.8.7 | | +|lifecycle |1.0.3 |1.0.3 | | +|lubridate |1.9.2 |1.9.2 | | +|magrittr |2.0.3 |2.0.3 | | +|mime |0.12 |0.12 | | +|openssl |2.0.6 |2.0.6 | | +|pillar |1.9.0 |1.9.0 | | +|pkgconfig |2.0.3 |2.0.3 | | +|plyr |1.8.8 |1.8.8 | | +|prettyunits |1.1.1 |1.1.1 | | +|progress |1.2.2 |1.2.2 | | +|proxy |0.4-27 |0.4-27 | | +|purrr |1.0.1 |1.0.1 | | +|R6 |2.5.1 |2.5.1 | | +|rappdirs |0.3.3 |0.3.3 | | +|Rcpp |1.0.10 |1.0.10 | | +|readr |2.1.4 |2.1.4 | | +|readxl |1.4.2 |1.4.2 | | +|RefManageR |1.4.0 |1.4.0 | | +|regions |0.1.8 |0.1.8 | | +|rematch |1.0.1 |1.0.1 | | +|rlang |1.1.1 |1.1.1 | | +|rprojroot |2.0.3 |2.0.3 | | +|stringi |1.7.12 |1.7.12 | | +|stringr |1.5.0 |1.5.0 | | +|sys |3.4.2 |3.4.2 | | +|tibble |3.2.1 |3.2.1 | | +|tidyr |1.3.0 |1.3.0 | | +|tidyselect |1.2.0 |1.2.0 | | +|timechange |0.2.0 |0.2.0 | | +|tzdb |0.4.0 |0.4.0 | | +|utf8 |1.2.3 |1.2.3 | | +|vctrs |0.6.3 |0.6.3 | | +|vroom |1.6.3 |1.6.3 | | +|withr |2.5.0 |2.5.0 | | +|xml2 |1.3.4 |1.3.4 | | + +# Revdeps + diff --git a/revdep/check.R b/revdep/check.R deleted file mode 100755 index e262948c..00000000 --- a/revdep/check.R +++ /dev/null @@ -1,5 +0,0 @@ -library("devtools") - -revdep_check() -revdep_check_save_summary() -revdep_check_print_problems() diff --git a/revdep/cran.md b/revdep/cran.md new file mode 100644 index 00000000..7ac41de3 --- /dev/null +++ b/revdep/cran.md @@ -0,0 +1,7 @@ +## revdepcheck results + +We checked 9 reverse dependencies, comparing R CMD check results across CRAN and dev versions of this package. + + * We saw 0 new problems + * We failed to check 0 packages + diff --git a/revdep/data.sqlite b/revdep/data.sqlite new file mode 100644 index 00000000..fd5dd57d Binary files /dev/null and b/revdep/data.sqlite differ diff --git a/revdep/failures.md b/revdep/failures.md new file mode 100644 index 00000000..9a207363 --- /dev/null +++ b/revdep/failures.md @@ -0,0 +1 @@ +*Wow, no problems at all. :)* \ No newline at end of file diff --git a/revdep/problems.md b/revdep/problems.md new file mode 100644 index 00000000..9a207363 --- /dev/null +++ b/revdep/problems.md @@ -0,0 +1 @@ +*Wow, no problems at all. :)* \ No newline at end of file diff --git a/tests/testthat/_snaps/03_get_eurostat_geospatial.md b/tests/testthat/_snaps/03_get_eurostat_geospatial.md new file mode 100644 index 00000000..93616591 --- /dev/null +++ b/tests/testthat/_snaps/03_get_eurostat_geospatial.md @@ -0,0 +1,22 @@ +# get_eurostat_geospatial cache_dir + + Code + a <- get_eurostat_geospatial(nuts_id = "LU", nuts_level = 0) + Message + Extracting data using giscoR package, please report issues on https://github.com/rOpenGov/giscoR/issues + +--- + + Code + a <- get_eurostat_geospatial(nuts_id = "LU", nuts_level = 0, cache_dir = another_temp) + Message + Extracting data using giscoR package, please report issues on https://github.com/rOpenGov/giscoR/issues + +--- + + Code + a <- get_eurostat_geospatial(nuts_id = "LU", nuts_level = 0) + Message + Extracting data using giscoR package, please report issues on https://github.com/rOpenGov/giscoR/issues + Cache management as per giscoR. see 'giscoR::gisco_get_nuts()' + diff --git a/tests/testthat/test-all.R b/tests/testthat/test-all.R deleted file mode 100755 index 390c25e2..00000000 --- a/tests/testthat/test-all.R +++ /dev/null @@ -1,185 +0,0 @@ -context("Get") - -test_that("get_eurostat includes time and value",{ - skip_on_cran() - expect_true(all(c("time", "values") %in% - names(get_eurostat("road_eqr_trams")))) -}) - -test_that("get_eurostat works with multi-frequency",{ - skip_on_cran() - expect_error(get_eurostat("avia_gonc", cache = FALSE)) - expect_match(as.character(unique(get_eurostat("avia_gonc", select_time = "Y" , - cache = FALSE)$time)), "-01-01") -}) - -test_that("get_eurostat return right classes",{ - skip_on_cran() - expect_true(all(c("factor", "numeric") %in% - sapply(get_eurostat("road_eqr_trams"), class))) - expect_true(all(c("character", "numeric") %in% - sapply(get_eurostat("road_eqr_trams", stringsAsFactors = FALSE), - class))) -}) - -test_that("get_eurostat handles daily data", { - skip_on_cran() - dat1 <- get_eurostat("ert_bil_eur_d", - filters = list(currency = "ARS", statinfo ="AVG", - time = c("2017M03D09", "2017M03D10")), - time_format = "date", cache = FALSE) - expect_equal(as.numeric(difftime(dat1$time[2], dat1$time[1], units = "days")), 1) -}) - - -test_that("get_eurostat get non-normal variable order",{ - skip_on_cran() - expect_gt(nrow(get_eurostat("cens_01rdhh")), 0) -}) - -context("cache") - -test_that("Cache give error if cache dir does not exist", { - skip_on_cran() - expect_error( - get_eurostat("nama_10_lp_ulc", cache_dir = file.path(tempdir(), "r_cache"))) -}) - -test_that("Cache works", { - skip_on_cran() - expect_is({ - t_dir <- file.path(tempdir(), "reurostat") - dir.create(t_dir) - k <- get_eurostat("nama_10_lp_ulc", cache_dir = t_dir) - }, - "data.frame") -}) - - -context("Search") - -test_that("search_eurostat finds",{ - skip_on_cran() - expect_equal(search_eurostat( - "Dwellings by type of housing, building and NUTS 3", type = "dataset")$code[1], - "cens_01rdhh" - ) -}) - - -context("Label") - -test_that("Variable names are labeled",{ - skip_on_cran() - expect_equal(label_eurostat_vars("geo"), "Geopolitical entity (reporting)") - expect_equal(label_eurostat_vars("housing", lang = "fr"), "Habitation") - - expect_true(any(grepl("_code", - names(label_eurostat( - get_eurostat("road_eqr_trams"), code = "geo"))))) -}) - -test_that("Label ordering is ordered", { - skip_on_cran() - expect_equal(c("European Union (current composition)", - "Finland", "United States"), - levels(label_eurostat(factor(c("FI", "US", "EU28")), - dic = "geo", eu_order = TRUE))) -}) - - -test_that("Countrycodes are labelled for factors", { - expect_equal(levels(label_eurostat(factor(c("FI", "DE", "EU28"), c("FI", "DE", "EU28")), dic = "geo", - countrycode = "country.name")), - c("Finland", "Germany", "EU28")) -}) - -test_that("Countrycodes return NA for countrycode_nomatch = NA", { - expect_equal(suppressWarnings(label_eurostat(c("FI", "DE", "EU28"), dic = "geo", - countrycode = "country.name", countrycode_nomatch = NA)), - c("Finland", "Germany", NA)) -}) - -test_that("Countrycodes use eurostat for missing", { - expect_equal(suppressWarnings(label_eurostat(c("FI", "DE", "EU28"), dic = "geo", - countrycode = "country.name", countrycode_nomatch = "eurostat")), - c("Finland", "Germany", "European Union (current composition)")) -}) - -test_that("custom_dic works", { - expect_equal(label_eurostat(c("FI", "DE"), dic = "geo", custom_dic = c(DE = "Germany")), - c("Finland", "Germany")) -}) - -context("Misc") - -test_that("Dic downloading works", { - skip_on_cran() - expect_warning(get_eurostat_dic("na_item"), NA) -}) - -test_that("Factors are retained in data.frame", { - skip_on_cran() - y <- label_eurostat(data.frame(unit = factor("EUR"))) - expect_is(y$unit, "factor") -}) - -test_that("Duplicated gives an error", { - skip_on_cran() - expect_error(label_eurostat(x = factor(c("P5G", "P5")), dic = "na_item")) -}) - -test_that("Duplicated with fix_duplicated does not give an error", { - skip_on_cran() - expect_match(as.character( - label_eurostat(x = factor(c("P5G", "P5")), dic = "na_item", - fix_duplicated = TRUE)), "P5", all = TRUE) -}) - -context("Flags") - -#flag_dat <- get_eurostat("t2020_rk310", type = "label", keepFlags=T, cache = FALSE) -#flag_dat <- get_eurostat("tsdtr210", type = "label", keepFlags=T, cache = FALSE) -flag_dat <- get_eurostat("road_pa_buscoa", type = "label", keepFlags=T, cache = FALSE) - - -test_that("get_eurostat includes flags",{ - skip_on_cran() - expect_true(all(c("flags") %in% - names(get_eurostat("road_eqr_trams", keepFlags = TRUE)))) -}) - -test_that("keepFlags + label as in #61",{ - skip_on_cran() - expect_true(all(c("flags") %in% - names(flag_dat))) -}) - -test_that("flag content",{ - skip_on_cran() - expect_true(all(c("b", "e") %in% - unique(flag_dat$flags))) -}) - -context("json") - -test_that("Get json data",{ - skip_on_cran() - expect_named(get_eurostat_json("nama_10_gdp", filters = list(geo = "FI", - na_item = "B1GQ", - unit = "CLV_I10")), - c("geo", "unit", "na_item", "time", "values"), - ignore.order = TRUE) -}) - -test_that("Handle numbers in filter name",{ - skip_on_cran() - expect_named(get_eurostat(id = "sts_inpr_a", filters = list(geo = "AT", - nace_r2 = "B", - s_adj = "CA", - indic_bt = "PROD", - unit = "I10")), - c("geo", "nace_r2", "s_adj", "indic_bt", "unit", "time", "values"), - ignore.order = TRUE) -}) - diff --git a/tests/testthat/test_00_cache.R b/tests/testthat/test_00_cache.R new file mode 100755 index 00000000..c5bbc23c --- /dev/null +++ b/tests/testthat/test_00_cache.R @@ -0,0 +1,54 @@ +test_that("Save user cache for test", { + skip_on_cran() + skip_if_offline() + + # Get current cache dir + Sys.setenv("TEST_EUROSTAT_CURRENT_CACHE" = eur_helper_detect_cache_dir()) + + cat("User cache dir is ", Sys.getenv("TEST_EUROSTAT_CURRENT_CACHE"), "\n") + + testdir <- file.path(tempdir(), "eurostat", "testthat") + # Set a temp cache dir + expect_message(set_eurostat_cache_dir(testdir)) + + cat("Testing cache dir is ", Sys.getenv("EUROSTAT_CACHE_DIR"), "\n") +}) + +test_that("Cache is ok if cache dir does not exist", { + skip_on_cran() + skip_if_offline() + k <- get_eurostat("nama_10_lp_ulc") + + expect_true(inherits(k, "data.frame")) +}) + +test_that("Cache works", { + skip_on_cran() + skip_if_offline() + + t_dir <- file.path(tempdir(), "reurostat") + k <- get_eurostat("nama_10_lp_ulc", cache_dir = t_dir) + expect_true(inherits(k, "data.frame")) +}) + +test_that("Dataset is filtered from cached bulk file", { + skip_on_cran() + skip_if_offline() + + t_dir <- file.path(tempdir(), "reurostat") + k2 <- get_eurostat("nama_10_lp_ulc", + cache_dir = t_dir, + filters = list()) + expect_message(get_eurostat("nama_10_lp_ulc", + cache_dir = t_dir, + filters = list(geo = "AT")), "and filtering it") + +}) + +test_that("Set cache", { + old <- eur_helper_detect_cache_dir() + new <- file.path(tempdir(), "eurostat", "testthat", "new") + expect_message(set_eurostat_cache_dir(new)) + + set_eurostat_cache_dir(old) +}) diff --git a/tests/testthat/test_01_bibliography.R b/tests/testthat/test_01_bibliography.R new file mode 100755 index 00000000..32374ba3 --- /dev/null +++ b/tests/testthat/test_01_bibliography.R @@ -0,0 +1,65 @@ +test_that("Bibentry gives correct results", { + skip_on_cran() + skip_if_offline() + expect_equal( + class(get_bibentry( + code = c("sts_inpr_a", "nama_10_gdp"), + keywords = list( + c("production", "industry"), + c("GDP") + ), + format = "Biblatex" + )), + "Bibtex" + ) + + expect_equal( + class( + suppressWarnings( + get_bibentry( + code = c("sts_inpr_a"), + lang = "fr", + format = "Bibtex" + ))), + "Bibtex" + ) + + expect_error( + get_bibentry(code = 123456) + ) + + expect_error( + get_bibentry( + code = c("sts_inpr_a"), + lang = "fr", + keywords = "production" + ) + ) + + # None of the codes not found + expect_warning( + get_bibentry( + code = "sts_inpr_b" + ) + ) + + # Some of the codes not found + expect_warning( + get_bibentry( + code = c("sts_inpr_b", "sts_inpr_a") + ) + ) + + expect_warning( + get_bibentry( + code = c("sts_inpr_a", "nama_10_gdp"), + keywords = list( + c("production", "industry"), + c("GDP") + ), + format = "character" + ) + ) + + +}) diff --git a/tests/testthat/test_02_flags.R b/tests/testthat/test_02_flags.R new file mode 100755 index 00000000..4331f7c6 --- /dev/null +++ b/tests/testthat/test_02_flags.R @@ -0,0 +1,44 @@ + +# flag_dat <- get_eurostat("t2020_rk310", type = "label", keepFlags=T, cache = FALSE) +# flag_dat <- get_eurostat("tsdtr210", type = "label", keepFlags=T, cache = FALSE) + +test_that("get_eurostat includes flags", { + skip_on_cran() + skip_if_offline() + expect_true(all(c("flags") %in% + names(get_eurostat("road_eqr_trams", keepFlags = TRUE)))) +}) + +test_that("keepFlags + label as in #61", { + skip_on_cran() + skip_if_offline() + flag_dat <- get_eurostat("road_pa_buscoa", type = "label", keepFlags = TRUE, cache = FALSE) + + expect_true(all(c("flags") %in% + names(flag_dat))) +}) + +test_that("flag content", { + skip_on_cran() + skip_if_offline() + flag_dat <- get_eurostat("road_pa_buscoa", type = "label", keepFlags = TRUE, cache = FALSE) + + expect_true(all(c("b", "e") %in% + unique(flag_dat$flags))) +}) + +test_that("flag content2", { + skip_on_cran() + skip_if_offline() + flag_dat <- get_eurostat("road_pa_buscoa", + type = "label", + keepFlags = TRUE, + cache = FALSE, + legacy_bulk_download = FALSE) + + expect_true(all(c("b", "e") %in% + unique(flag_dat$flags))) + + # sleep for a while to let the API rest + Sys.sleep(5) +}) diff --git a/tests/testthat/test_03_get_eurostat_geospatial.R b/tests/testthat/test_03_get_eurostat_geospatial.R new file mode 100755 index 00000000..7ea873d3 --- /dev/null +++ b/tests/testthat/test_03_get_eurostat_geospatial.R @@ -0,0 +1,640 @@ +test_that("get_eurostat_geospatial errors", { + skip_if_not_installed(pkg = "giscoR") + skip_if_not_installed(pkg = "sf") + skip_on_cran() + skip_if_offline() + skip_if(!giscoR::gisco_check_access(), "No access to GISCO") + + # Testing argument 'output_class' + expect_error(get_eurostat_geospatial(output_class = 0)) + expect_error(get_eurostat_geospatial(output_class = "foo")) + expect_error(get_eurostat_geospatial(output_class = "sf", "df")) + + # Testing argument 'resolution' + expect_error(get_eurostat_geospatial(resolution = 12345)) + expect_error(get_eurostat_geospatial(resolution = 1:2)) + + # Testing argument nuts_level + expect_error(get_eurostat_geospatial(nuts_level = 12345)) + expect_error(get_eurostat_geospatial(nuts_level = 1:2)) + + # Testing argument year + expect_error(get_eurostat_geospatial(year = 1900)) + expect_error(get_eurostat_geospatial(year = c(2003, 2006))) + + # Testing argment cache + expect_error(get_eurostat_geospatial(cache = as.logical(NA), year = 2021)) + expect_error(get_eurostat_geospatial(cache = c(TRUE, FALSE), year = 2021)) + + # Testing argument CRS + expect_error(get_eurostat_geospatial(crs = "north polar stereographic")) + expect_error(get_eurostat_geospatial(crs = c(4326, 3035))) + + # Invalid combinations + expect_error(get_eurostat_geospatial(resolution = 60, year = 2003)) +}) + +test_that("get_eurostat_geospatial messages", { + skip_if_not_installed(pkg = "giscoR") + skip_if_not_installed(pkg = "sf") + skip_on_cran() + skip_if_offline() + skip_if(!giscoR::gisco_check_access(), "No access to GISCO") + + + # Deprecations + expect_message( + get_eurostat_geospatial(make_valid = TRUE), + "'make_valid' argument has been deprecated" + ) + + expect_message( + spdf <- get_eurostat_geospatial(output_class = "spdf"), + "'spdf' output deprecated. Switching to sf output" + ) + expect_s3_class(spdf, "sf") + + # Info about source of data + expect_message(get_eurostat_geospatial(), "from eurostat") + expect_message(get_eurostat_geospatial(nuts_id = "BE"), "giscoR package") +}) + + +test_that("get_eurostat_geospatial nuts levels", { + skip_if_not_installed(pkg = "sf") + # From internal data with default args + expect_message(all <- get_eurostat_geospatial(nuts_level = "all"), "eurostat") + expect_message(n0 <- get_eurostat_geospatial(nuts_level = "0"), "eurostat") + expect_message(n1 <- get_eurostat_geospatial(nuts_level = "1"), "eurostat") + expect_message(n2 <- get_eurostat_geospatial(nuts_level = "2"), "eurostat") + expect_message(n3 <- get_eurostat_geospatial(nuts_level = "3"), "eurostat") + + expect_gt(nrow(all), nrow(n3)) + expect_gt(nrow(n3), nrow(n2)) + expect_gt(nrow(n2), nrow(n1)) + expect_gt(nrow(n1), nrow(n0)) + + expect_s3_class(all, "sf") + expect_s3_class(n3, "sf") + expect_s3_class(n2, "sf") + expect_s3_class(n1, "sf") + + skip_if_not_installed(pkg = "giscoR") + skip_on_cran() + skip_if_offline() + skip_if(!giscoR::gisco_check_access(), "No access to GISCO") + + + # From internal data with default args + expect_message(gall <- get_eurostat_geospatial( + nuts_level = "all", + crs = 3035 + ), "giscoR") + expect_message(gn0 <- get_eurostat_geospatial( + nuts_level = "0", + crs = 3035 + ), "giscoR") + expect_message(gn1 <- get_eurostat_geospatial( + nuts_level = "1", + crs = 3035 + ), "giscoR") + expect_message(gn2 <- get_eurostat_geospatial( + nuts_level = "2", + crs = 3035 + ), "giscoR") + expect_message(gn3 <- get_eurostat_geospatial( + nuts_level = "3", + crs = 3035 + ), "giscoR") + + expect_gt(nrow(gall), nrow(gn3)) + expect_gt(nrow(gn3), nrow(gn2)) + expect_gt(nrow(gn2), nrow(gn1)) + expect_gt(nrow(gn1), nrow(gn0)) + expect_true("geo" %in% names(gall)) + + expect_s3_class(gall, "sf") + expect_s3_class(gn3, "sf") + expect_s3_class(gn2, "sf") + expect_s3_class(gn1, "sf") +}) + +test_that("get_eurostat_geospatial df", { + skip_if_not_installed(pkg = "sf") + # From internal data with default args + expect_message( + all <- get_eurostat_geospatial( + nuts_level = "all", + output_class = "df" + ), + "eurostat" + ) + expect_message(n0 <- get_eurostat_geospatial( + nuts_level = "0", + output_class = "df" + ), "eurostat") + expect_message(n1 <- get_eurostat_geospatial( + nuts_level = "1", + output_class = "df" + ), "eurostat") + expect_message(n2 <- get_eurostat_geospatial( + nuts_level = "2", + output_class = "df" + ), "eurostat") + expect_message(n3 <- get_eurostat_geospatial( + nuts_level = "3", + output_class = "df" + ), "eurostat") + + expect_gt(nrow(all), nrow(n3)) + expect_gt(nrow(n3), nrow(n2)) + expect_gt(nrow(n2), nrow(n1)) + expect_gt(nrow(n1), nrow(n0)) + + expect_s3_class(all, "data.frame") + expect_s3_class(n3, "data.frame") + expect_s3_class(n2, "data.frame") + expect_s3_class(n1, "data.frame") + + skip_if_not_installed(pkg = "giscoR") + skip_on_cran() + skip_if_offline() + skip_if(!giscoR::gisco_check_access(), "No access to GISCO") + + + # From giscoR data + expect_message(gall <- get_eurostat_geospatial( + nuts_level = "all", + output_class = "df", + verbose = TRUE + ), "giscoR") + expect_message(gn0 <- get_eurostat_geospatial( + nuts_level = "0", + crs = 3035, + verbose = TRUE + ), "giscoR") + expect_message(gn1 <- get_eurostat_geospatial( + nuts_level = "1", + crs = 3035, + verbose = TRUE + ), "giscoR") + expect_message(gn2 <- get_eurostat_geospatial( + nuts_level = "2", + crs = 3035, + verbose = TRUE + ), "giscoR") + expect_message(gn3 <- get_eurostat_geospatial( + nuts_level = "3", + crs = 3035, + verbose = TRUE + ), "giscoR") + + expect_gt(nrow(gall), nrow(gn3)) + expect_gt(nrow(gn3), nrow(gn2)) + expect_gt(nrow(gn2), nrow(gn1)) + expect_gt(nrow(gn1), nrow(gn0)) + expect_true("geo" %in% names(gall)) + + expect_s3_class(gall, "data.frame") + expect_s3_class(gn3, "data.frame") + expect_s3_class(gn2, "data.frame") + expect_s3_class(gn1, "data.frame") +}) + + +test_that("get_eurostat_geospatial cache_dir", { + skip_if_not_installed(pkg = "sf") + skip_if_not_installed(pkg = "giscoR") + skip_on_cran() + skip_if_offline() + skip_if(!giscoR::gisco_check_access(), "No access to GISCO") + + # Get initial cache dir + init_cache <- eur_helper_detect_cache_dir() + + # Now mocking as if the user set a specific cache dir + test_cache_dir <- file.path(tempdir(), "eurostat_set_by_user") + suppressMessages(set_eurostat_cache_dir(test_cache_dir)) + + # Check change + new_cache <- eur_helper_detect_cache_dir() + expect_false(identical(init_cache, new_cache)) + + # Check now the messages with snapshot testing + # This would show nothing regarding cache + expect_snapshot(a <- get_eurostat_geospatial( + nuts_id = "LU", + nuts_level = 0 + )) + + # If set by the user no messages on caching + another_temp <- tempdir() + expect_snapshot(a <- get_eurostat_geospatial( + nuts_id = "LU", + nuts_level = 0, + cache_dir = another_temp + )) + + # But if using the default unset cache dir from eurostat, expect a message + # stating that giscoR is managing it + + # Now mocking as if the user set a specific cache dir + default_temp <- file.path(tempdir(), "eurostat") + suppressMessages(set_eurostat_cache_dir(default_temp)) + + # Check change + new_cache <- eur_helper_detect_cache_dir() + expect_false(identical(init_cache, new_cache)) + expect_true(identical(default_temp, new_cache)) + + expect_snapshot(a <- get_eurostat_geospatial( + nuts_id = "LU", + nuts_level = 0 + )) + + + # Finally, restore cache dir set by the user (if any) + suppressMessages(set_eurostat_cache_dir(init_cache)) + expect_identical(init_cache, eur_helper_detect_cache_dir()) +}) + + +test_that("giscoR returns NULL", { + skip_if_not_installed(pkg = "sf") + skip_if_not_installed(pkg = "giscoR") + skip_on_cran() + skip_if_offline() + skip_if(!giscoR::gisco_check_access(), "No access to GISCO") + skip_if(packageVersion("giscoR") < "0.3.5", "Use latest giscoR release") + + options(giscoR_test_offline = TRUE) + expect_message( + n <- get_eurostat_geospatial( + country = "AT", nuts_level = "0", + update_cache = TRUE + ), + "not reachable" + ) + expect_null(n) + options(giscoR_test_offline = FALSE) +}) + + +test_that("Check column names", { + skip_if_not_installed(pkg = "sf") + + # See https://github.com/rOpenGov/eurostat/issues/240 + col_order <- c( + "id", "LEVL_CODE", "NUTS_ID", "CNTR_CODE", "NAME_LATN", + "NUTS_NAME", "MOUNT_TYPE", "URBN_TYPE", "COAST_TYPE", + "FID", "geo", "geometry" + ) + + + cached <- get_eurostat_geospatial() + expect_s3_class(cached, "sf") + expect_identical(names(cached), col_order) + + # df + cached_df <- get_eurostat_geospatial(output_class = "df") + expect_s3_class(cached_df, "data.frame") + expect_identical(names(cached_df), col_order[-length(col_order)]) +}) + + +test_that("Check column names POLYGONS from GISCO", { + skip_if_not_installed(pkg = "sf") + skip_if_not_installed(pkg = "giscoR") + skip_on_cran() + skip_if_offline() + skip_if(!giscoR::gisco_check_access(), "No access to GISCO") + skip_if(packageVersion("giscoR") < "0.3.5", "Use latest giscoR release") + + col_order <- c( + "id", "LEVL_CODE", "NUTS_ID", "CNTR_CODE", "NAME_LATN", + "NUTS_NAME", "MOUNT_TYPE", "URBN_TYPE", "COAST_TYPE", + "FID", "geo", "geometry" + ) + + # Polygons 2003 + poly <- get_eurostat_geospatial(nuts_level = 0, resolution = 20, year = 2003) + expect_s3_class(poly, "sf") + expect_identical(names(poly), col_order) + + # df + poly_df <- get_eurostat_geospatial( + output_class = "df", nuts_level = 0, + resolution = 20, year = 2003 + ) + + expect_s3_class(poly_df, "data.frame") + expect_identical(names(poly_df), col_order[-length(col_order)]) + + # Polygons 2006 + poly <- get_eurostat_geospatial(nuts_level = 0, resolution = 60, year = 2006) + expect_s3_class(poly, "sf") + expect_identical(names(poly), col_order) + + # df + poly_df <- get_eurostat_geospatial( + output_class = "df", nuts_level = 0, + resolution = 60, year = 2006 + ) + + expect_s3_class(poly_df, "data.frame") + expect_identical(names(poly_df), col_order[-length(col_order)]) + + + # Polygons 2010 + poly <- get_eurostat_geospatial(nuts_level = 0, resolution = 60, year = 2010) + expect_s3_class(poly, "sf") + expect_identical(names(poly), col_order) + + # df + poly_df <- get_eurostat_geospatial( + output_class = "df", nuts_level = 0, + resolution = 60, year = 2010 + ) + + expect_s3_class(poly_df, "data.frame") + expect_identical(names(poly_df), col_order[-length(col_order)]) + + # Polygons 2013 + poly <- get_eurostat_geospatial(nuts_level = 0, resolution = 60, year = 2013) + expect_s3_class(poly, "sf") + expect_identical(names(poly), col_order) + + # df + poly_df <- get_eurostat_geospatial( + output_class = "df", nuts_level = 0, + resolution = 60, year = 2013 + ) + + expect_s3_class(poly_df, "data.frame") + expect_identical(names(poly_df), col_order[-length(col_order)]) + + # Polygons 2016 + poly <- get_eurostat_geospatial( + nuts_level = 0, resolution = 60, year = 2016, + update_cache = TRUE + ) + expect_s3_class(poly, "sf") + expect_identical(names(poly), col_order) + + # df + poly_df <- get_eurostat_geospatial( + output_class = "df", nuts_level = 0, + resolution = 60, year = 2016, + update_cache = TRUE + ) + + expect_s3_class(poly_df, "data.frame") + expect_identical(names(poly_df), col_order[-length(col_order)]) + + # Polygons 2021 + poly <- get_eurostat_geospatial(nuts_level = 0, resolution = 60, year = 2021) + expect_s3_class(poly, "sf") + expect_identical(names(poly), col_order) + + # df + poly_df <- get_eurostat_geospatial( + output_class = "df", nuts_level = 0, + resolution = 60, year = 2021 + ) + + expect_s3_class(poly_df, "data.frame") + expect_identical(names(poly_df), col_order[-length(col_order)]) +}) + +test_that("Check column names LABELS from GISCO", { + skip_if_not_installed(pkg = "sf") + skip_if_not_installed(pkg = "giscoR") + skip_on_cran() + skip_if_offline() + skip_if(!giscoR::gisco_check_access(), "No access to GISCO") + skip_if(packageVersion("giscoR") < "0.3.5", "Use latest giscoR release") + + col_order <- c( + "id", "LEVL_CODE", "NUTS_ID", "CNTR_CODE", "NAME_LATN", + "NUTS_NAME", "MOUNT_TYPE", "URBN_TYPE", "COAST_TYPE", + "FID", "geo", "geometry" + ) + + # Labels 2003 + poly <- get_eurostat_geospatial( + nuts_level = 0, resolution = 20, year = 2003, + spatialtype = "LB" + ) + expect_s3_class(poly, "sf") + expect_identical(names(poly), col_order) + + # df + poly_df <- get_eurostat_geospatial( + output_class = "df", nuts_level = 0, + resolution = 20, year = 2003, + spatialtype = "LB" + ) + + expect_s3_class(poly_df, "data.frame") + expect_identical(names(poly_df), col_order[-length(col_order)]) + + # Labels 2006 + poly <- get_eurostat_geospatial( + nuts_level = 0, resolution = 60, year = 2006, + spatialtype = "LB" + ) + expect_s3_class(poly, "sf") + expect_identical(names(poly), col_order) + + # df + poly_df <- get_eurostat_geospatial( + output_class = "df", nuts_level = 0, + resolution = 60, year = 2006, + spatialtype = "LB" + ) + + expect_s3_class(poly_df, "data.frame") + expect_identical(names(poly_df), col_order[-length(col_order)]) + + + # Labels 2010 + poly <- get_eurostat_geospatial( + nuts_level = 0, resolution = 60, year = 2010, + spatialtype = "LB" + ) + expect_s3_class(poly, "sf") + expect_identical(names(poly), col_order) + + # df + poly_df <- get_eurostat_geospatial( + output_class = "df", nuts_level = 0, + resolution = 60, year = 2010, + spatialtype = "LB" + ) + + expect_s3_class(poly_df, "data.frame") + expect_identical(names(poly_df), col_order[-length(col_order)]) + + # Labels 2013 + poly <- get_eurostat_geospatial( + nuts_level = 0, resolution = 60, year = 2013, + spatialtype = "LB" + ) + expect_s3_class(poly, "sf") + expect_identical(names(poly), col_order) + + # df + poly_df <- get_eurostat_geospatial( + output_class = "df", nuts_level = 0, + resolution = 60, year = 2013, + spatialtype = "LB" + ) + + expect_s3_class(poly_df, "data.frame") + expect_identical(names(poly_df), col_order[-length(col_order)]) + + # Labels 2016 + poly <- get_eurostat_geospatial( + nuts_level = 0, resolution = 60, year = 2016, + update_cache = TRUE, spatialtype = "LB" + ) + expect_s3_class(poly, "sf") + expect_identical(names(poly), col_order) + + # df + poly_df <- get_eurostat_geospatial( + output_class = "df", nuts_level = 0, + resolution = 60, year = 2016, + update_cache = TRUE, + spatialtype = "LB" + ) + + expect_s3_class(poly_df, "data.frame") + expect_identical(names(poly_df), col_order[-length(col_order)]) + + # Labels 2021 + poly <- get_eurostat_geospatial( + nuts_level = 0, resolution = 60, year = 2021, + spatialtype = "LB" + ) + expect_s3_class(poly, "sf") + expect_identical(names(poly), col_order) + + # df + poly_df <- get_eurostat_geospatial( + output_class = "df", nuts_level = 0, + resolution = 60, year = 2021, + spatialtype = "LB" + ) + + expect_s3_class(poly_df, "data.frame") + expect_identical(names(poly_df), col_order[-length(col_order)]) +}) + + +test_that("Check column names BORDERS from GISCO", { + skip_if_not_installed(pkg = "sf") + skip_if_not_installed(pkg = "giscoR") + skip_on_cran() + skip_if_offline() + skip_if(!giscoR::gisco_check_access(), "No access to GISCO") + skip_if(packageVersion("giscoR") < "0.3.5", "Use latest giscoR release") + + # BORDERS 2003 + poly <- get_eurostat_geospatial( + nuts_level = 0, resolution = 20, year = 2003, + spatialtype = "BN" + ) + expect_s3_class(poly, "sf") + + # df + poly_df <- get_eurostat_geospatial( + output_class = "df", nuts_level = 0, + resolution = 20, year = 2003, + spatialtype = "BN" + ) + + expect_s3_class(poly_df, "data.frame") + + # BORDERS 2006 + poly <- get_eurostat_geospatial( + nuts_level = 0, resolution = 60, year = 2006, + spatialtype = "BN" + ) + expect_s3_class(poly, "sf") + + # df + poly_df <- get_eurostat_geospatial( + output_class = "df", nuts_level = 0, + resolution = 60, year = 2006, + spatialtype = "BN" + ) + + expect_s3_class(poly_df, "data.frame") + + + # BORDERS 2010 + poly <- get_eurostat_geospatial( + nuts_level = 0, resolution = 60, year = 2010, + spatialtype = "BN" + ) + expect_s3_class(poly, "sf") + + # df + poly_df <- get_eurostat_geospatial( + output_class = "df", nuts_level = 0, + resolution = 60, year = 2010, + spatialtype = "BN" + ) + + expect_s3_class(poly_df, "data.frame") + + # BORDERS 2013 + poly <- get_eurostat_geospatial( + nuts_level = 0, resolution = 60, year = 2013, + spatialtype = "BN" + ) + expect_s3_class(poly, "sf") + + # df + poly_df <- get_eurostat_geospatial( + output_class = "df", nuts_level = 0, + resolution = 60, year = 2013, + spatialtype = "BN" + ) + + expect_s3_class(poly_df, "data.frame") + + # BORDERS 2016 + poly <- get_eurostat_geospatial( + nuts_level = 0, resolution = 60, year = 2016, + update_cache = TRUE, spatialtype = "BN" + ) + expect_s3_class(poly, "sf") + + # df + poly_df <- get_eurostat_geospatial( + output_class = "df", nuts_level = 0, + resolution = 60, year = 2016, + update_cache = TRUE, + spatialtype = "BN" + ) + + expect_s3_class(poly_df, "data.frame") + + # BORDERS 2021 + poly <- get_eurostat_geospatial( + nuts_level = 0, resolution = 60, year = 2021, + spatialtype = "BN" + ) + expect_s3_class(poly, "sf") + + # df + poly_df <- get_eurostat_geospatial( + output_class = "df", nuts_level = 0, + resolution = 60, year = 2021, + spatialtype = "BN" + ) + + expect_s3_class(poly_df, "data.frame") +}) diff --git a/tests/testthat/test_04_get.R b/tests/testthat/test_04_get.R new file mode 100755 index 00000000..dc525b7d --- /dev/null +++ b/tests/testthat/test_04_get.R @@ -0,0 +1,129 @@ +test_that("get_eurostat (dissemination API) includes TIME_PERIOD and value", { + skip_on_cran() + skip_if_offline() + expect_true(all(c("TIME_PERIOD", "values") %in% + names(get_eurostat(id = "road_eqr_trams", + stringsAsFactors = TRUE, + select_time = "A")))) +}) + +test_that("get_eurostat (dissemination API) includes TIME_PERIOD and value", { + skip_on_cran() + skip_if_offline() + expect_true(all(c("TIME_PERIOD", "values") %in% + names(get_eurostat(id = "road_eqr_trams", + stringsAsFactors = TRUE, + select_time = "Y")))) + # sleep for a while to let the API rest + Sys.sleep(5) +}) + +test_that("get_eurostat (dissemination API) produces a message with multiple select_time", { + skip_on_cran() + skip_if_offline() + expect_message(get_eurostat(id = "avia_gonc", + select_time = c("A", "M", "Q"))) +}) + +test_that("get_eurostat (dissemination API) produces an error with imaginary select_time parameters", { + skip_on_cran() + skip_if_offline() + expect_error(get_eurostat(id = "avia_gonc", + select_time = c("X", "Y", "Z"))) + # sleep for a while to let the API rest + Sys.sleep(5) +}) + +test_that("get_eurostat (dissemination API) works correctly with multi-frequency", { + skip_on_cran() + skip_if_offline() + expect_message(get_eurostat("avia_gonc", + cache = FALSE, + time_format = "date_last") + ) + expect_match(as.character(unique(get_eurostat("avia_gonc", + select_time = NULL, + cache = FALSE)$TIME_PERIOD)), + "-01-01") +}) + +test_that("get_eurostat return right classes", { + skip_on_cran() + skip_if_offline() + expect_true(all(c("character", "numeric", "Date") %in% + sapply(get_eurostat("road_eqr_trams"), class))) + expect_true(all(c("character", "numeric", "Date") %in% + sapply( + get_eurostat("road_eqr_trams", keepFlags = TRUE), + class + ))) +}) + +test_that("bi-annual data contains freq S", { + skip_on_cran() + skip_if_offline() + expect_true("S" %in% get_eurostat("earn_mw_cur")$freq) + # sleep for a while to let the API rest + Sys.sleep(5) +}) + + +test_that("eurostat2num2 (dissemination API) works correctly", { + skip_on_cran() + skip_if_offline() + expect_true( + is.numeric( + get_eurostat(id = "earn_mw_cur", + time_format = "num", + use.data.table = TRUE)$TIME_PERIOD + ) + ) +}) + +test_that("weekly dataset download (dissemination API) works correctly", { + skip_on_cran() + skip_if_offline() + expect_match( + get_eurostat(id = "lfsi_abs_w", + select_time = c("W"), + time_format = "date")$freq[1], "W") +}) + +test_that("get_eurostat get non-normal variable order", { + skip_on_cran() + skip_if_offline() + expect_gt(nrow(get_eurostat("cens_01rdhh")), 0) +}) + +test_that("get_eurostat and eurotime2date work with daily data", { + skip_on_cran() + skip_if_offline() + expect_match(get_eurostat("irt_h_eurcoe_d", + filters = list(lastTimePeriod = 5))$freq[1], "D") +}) + +test_that("get_eurostat and eurotime2num work with daily data", { + skip_on_cran() + skip_if_offline() + # Downloading daily data with time_format = "num" produces a warning + # suppressWarnings is here to suppress that + expect_match(suppressWarnings(get_eurostat("irt_h_eurcoe_d", + filters = list(lastTimePeriod = 5), + time_format = "num"))$freq[1], "D") +}) + +test_that("get_eurostat and eurotime2num work with daily data", { + skip_on_cran() + skip_if_offline() + expect_match(get_eurostat("ei_bsci_m_r2", + filters = list(lastTimePeriod = 5), + time_format = "num")$freq[1], "M") +}) + +test_that("get_eurostat and eurotime2num work with daily data", { + skip_on_cran() + skip_if_offline() + expect_match(get_eurostat("med_ag32", + filters = list(lastTimePeriod = 5), + time_format = "num")$freq[1], "A") +}) diff --git a/tests/testthat/test_05_json.R b/tests/testthat/test_05_json.R new file mode 100755 index 00000000..3e3d75d8 --- /dev/null +++ b/tests/testthat/test_05_json.R @@ -0,0 +1,43 @@ +test_that("Get json data", { + skip_on_cran() + skip_if_offline() + expect_named( + get_eurostat_json("nama_10_gdp", + filters = list( + geo = "FI", + na_item = "B1GQ", + unit = "CLV_I10")), + c("geo", "unit", "na_item", "time", "values", "freq"), + ignore.order = TRUE + ) + + # Unsupported language code used. Using the default language: "en" + expect_message( + get_eurostat_json("nama_10_gdp", + filters = list( + geo = "FI", + na_item = "B1GQ", + unit = "CLV_I10"), + lang = "FI", + type = "label") + ) + + # Using the default language: "en" + expect_message( + get_eurostat_json("nama_10_gdp", + filters = list( + geo = "FI", + na_item = "B1GQ", + unit = "CLV_I10"), + lang = NULL, + type = "both") + ) + + # Error message + expect_error( + get_eurostat_json("invalid_id") + ) + + # sleep for a while to let the API rest + Sys.sleep(5) +}) diff --git a/tests/testthat/test_06_label.R b/tests/testthat/test_06_label.R new file mode 100755 index 00000000..dead5bcd --- /dev/null +++ b/tests/testthat/test_06_label.R @@ -0,0 +1,87 @@ +test_that("Variable names are labeled", { + skip_on_cran() + skip_if_offline() + expect_equal(label_eurostat_vars(id = "nama_10_lp_ulc", x = "geo", lang = "en"), "Geopolitical entity (reporting)") + expect_equal(label_eurostat_tables("nama_10_lp_ulc"), "Labour productivity and unit labour costs") + + expect_true(any(grepl( + "_code", + names(label_eurostat( + get_eurostat("road_eqr_trams"), + code = "geo" + )) + ))) +}) + +test_that("Label ordering is ordered", { + skip_on_cran() + skip_if_offline() + expect_equal( + c( + "European Union - 28 countries (2013-2020)", + "Finland", "United States" + ), + levels(label_eurostat(factor(c("FI", "US", "EU28")), + dic = "geo", eu_order = TRUE + )) + ) +}) + + +test_that("Countrycodes are labelled for factors", { + skip_on_cran() + skip_if_offline() + expect_equal( + levels(label_eurostat(factor(c("FI", "DE", "EU28"), c("FI", "DE", "EU28")), + dic = "geo", + countrycode = "country.name" + )), + c("Finland", "Germany", "EU28") + ) + + # sleep for a while to let the API rest + Sys.sleep(5) +}) + +test_that("Countrycodes return NA for countrycode_nomatch = NA", { + skip_on_cran() + skip_if_offline() + expect_equal( + suppressWarnings(label_eurostat(c("FI", "DE", "EU28"), + dic = "geo", + countrycode = "country.name", countrycode_nomatch = NA + )), + c("Finland", "Germany", NA) + ) +}) + +test_that("Countrycodes use eurostat for missing", { + skip_on_cran() + skip_if_offline() + expect_equal( + suppressWarnings(label_eurostat(c("FI", "DE", "EU28"), + dic = "geo", + countrycode = "country.name", countrycode_nomatch = "eurostat" + )), + c("Finland", "Germany", "European Union - 28 countries (2013-2020)") + ) +}) + +test_that("custom_dic works", { + skip_on_cran() + skip_if_offline() + expect_equal( + label_eurostat(c("FI", "DE"), dic = "geo", custom_dic = c(DE = "Germany")), + c("Finland", "Germany") + ) +}) + +test_that("wrong code (for this dataset) produces an error", { + skip_on_cran() + skip_if_offline() + expect_error( + label_eurostat( + get_eurostat("road_eqr_trams"), code = "coef" + ) + ) +}) \ No newline at end of file diff --git a/tests/testthat/test_07_misc.R b/tests/testthat/test_07_misc.R new file mode 100755 index 00000000..9e638371 --- /dev/null +++ b/tests/testthat/test_07_misc.R @@ -0,0 +1,61 @@ +test_that("Dic downloading works", { + skip_on_cran() + skip_if_offline() + expect_warning(get_eurostat_dic("na_item"), NA) +}) + +test_that("Factors are retained in data.frame", { + skip_on_cran() + skip_if_offline() + y <- label_eurostat(data.frame(unit = factor("EUR"))) + expect_s3_class(y$unit, "factor") +}) + +test_that("Duplicated gives an error", { + skip_on_cran() + skip_if_offline() + expect_error(label_eurostat(x = factor(c("P5G", "P5")), dic = "na_item")) +}) + +test_that("Duplicated with fix_duplicated does not give an error", { + skip_on_cran() + skip_if_offline() + expect_match(as.character( + label_eurostat( + x = factor(c("P5G", "P5")), dic = "na_item", + fix_duplicated = TRUE + ) + ), "P5", all = TRUE) +}) + +# W99 values are now reported in separate Excel files that are published +# in demo_r_mweek3 Reference metadata page so this test no longer +# applies, as of 2025-02-17 +# test_that("Get eurotime2date error message related to W99 values", { +# skip_on_cran() +# skip_if_offline() +# expect_warning( +# get_eurostat( +# "demo_r_mweek3", +# filters = list( +# sex = "F", +# age = "TOTAL", +# geo = "BG" +# ) +# ) +# ) +# }) + +test_that("cut_to_classes works", { + skip_on_cran() + skip_if_offline() + dataset <- get_eurostat( + "nama_10_lp_ulc", + filters = list( + geo = c("AT", "DK", "BG"), + unit = "EUR", + na_item = "D1_SAL_HW")) + dataset <- na.omit(dataset) + + expect_visible(cut_to_classes(dataset$values)) +}) \ No newline at end of file diff --git a/tests/testthat/test_08_regional.R b/tests/testthat/test_08_regional.R new file mode 100755 index 00000000..abb6e510 --- /dev/null +++ b/tests/testthat/test_08_regional.R @@ -0,0 +1,78 @@ +test_regional_codes <- data.frame( + geo = c("FRB", "FRE", "UKN02", "IE022", "FR243", "FRB03"), + time = c(rep(as.Date("2014-01-01"), 5), as.Date("2015-01-01")), + values = c(1:6), + control = c( + "Changed from NUTS2 to NUTS1", + "New region NUTS2016 only", + "Discontinued region NUTS2013", + "Boundary shift NUTS2013", + "Recoded in NUTS2013", + "Recoded in NUTS2016" + ) +) + + + +dat <- data.frame( + geo = c("FR", "IE04", "DEB1C"), + values = c(1000, 23, 12) +) + +test_that("deprecation warning works", { + expect_warning(recode_to_nuts_2013(test_regional_codes)) + expect_warning(recode_to_nuts_2016(test_regional_codes)) + expect_message(add_nuts_level(dat)) +}) + +suppressMessages( + test_that("add_nuts_level works", { + expect_equal(add_nuts_level(dat)$nuts_level, c(0, 2, 3)) + }) +) + +# Deprecated test, needs reworking: +# test_that("Recoding gives correct results",{ +# +# skip_on_cran() +# skip_on_ci() +# +# expect_warning (harmonize_geo_code(test_regional_codes)) +# +# suppressWarnings(test_harmonized <- harmonize_geo_code(test_regional_codes)) +# +# suppressWarnings(try_recode_2013 <- recode_to_nuts_2013(test_harmonized)) +# +# lookup_code16 <- test_harmonized %>% +# filter ( geo == "FR243") %>% +# select ( code16 ) %>% unlist() %>% as.character() +# +# lookup_code13 <- test_harmonized %>% +# filter ( geo == "FRB03") %>% +# select ( code13 ) %>% unlist() %>% as.character() +# +# recode_frb <- try_recode_2013 %>% +# filter ( code16 == "FRB") %>% +# select ( geo ) %>% unlist() %>% as.character() +# +# recode_ukn02 <- try_recode_2016 %>% +# filter ( code13 == "UKN02") %>% +# select ( geo ) %>% unlist() %>% as.character() +# +# expect_equal( lookup_code16, +# "FRB03" +# ) +# expect_equal( lookup_code13, +# "FR243" +# ) +# expect_equal( lookup_code13, +# "FR243" +# ) +# expect_equal( recode_frb, +# NA_character_ +# ) +# expect_equal( recode_ukn02, +# NA_character_ +# ) +# +# }) diff --git a/tests/testthat/test_09_search.R b/tests/testthat/test_09_search.R new file mode 100755 index 00000000..bc0dec65 --- /dev/null +++ b/tests/testthat/test_09_search.R @@ -0,0 +1,32 @@ +test_that("search_eurostat finds", { + skip_on_cran() + skip_if_offline() + expect_equal( + search_eurostat( + "Dwellings by type of housing, building and NUTS 3", + type = "dataset" + )$code[1], + "cens_01rdhh" + ) + + expect_equal( + suppressWarnings( + search_eurostat( + "Volkswirtschaftliche Gesamtrechnungen", + type = "folder", + lang = "de" + ))$code[1], + "ei_qna" + ) + + expect_equal( + suppressWarnings( + search_eurostat( + "sts_os", + type = "folder", + column = "code", + lang = "fr" + ))$title[1], + "Services" + ) +}) diff --git a/tests/testthat/test_99_restore_cache.R b/tests/testthat/test_99_restore_cache.R new file mode 100644 index 00000000..4f09c7a8 --- /dev/null +++ b/tests/testthat/test_99_restore_cache.R @@ -0,0 +1,24 @@ +test_that("Restore user cache dir after testing", { + skip_on_cran() + skip_if_offline() + + # Clear test cache + cat("Test cache was ", eur_helper_detect_cache_dir(), "\n") + expect_message(clean_eurostat_cache(config = FALSE)) + + user_dir <- Sys.getenv("TEST_EUROSTAT_CURRENT_CACHE") + current_env <- Sys.getenv("EUROSTAT_CACHE_DIR") + + expect_false(current_env == user_dir) + + expect_message(expect_message( + set_eurostat_cache_dir(user_dir) + )) + newcache <- suppressMessages(set_eurostat_cache_dir(user_dir)) + expect_equal(newcache, user_dir) + expect_equal(user_dir, Sys.getenv("EUROSTAT_CACHE_DIR")) + + cat("Cache restored to ", Sys.getenv("EUROSTAT_CACHE_DIR"), "\n") + + eurostat:::clean_eurostat_toc() +}) diff --git a/vignettes/.gitignore b/vignettes/.gitignore new file mode 100644 index 00000000..097b2416 --- /dev/null +++ b/vignettes/.gitignore @@ -0,0 +1,2 @@ +*.html +*.R diff --git a/vignettes/articles/.gitignore b/vignettes/articles/.gitignore new file mode 100644 index 00000000..097b2416 --- /dev/null +++ b/vignettes/articles/.gitignore @@ -0,0 +1,2 @@ +*.html +*.R diff --git a/vignettes/articles/Accessing-culture-datasets-with-the-eurostat-package.Rmd b/vignettes/articles/Accessing-culture-datasets-with-the-eurostat-package.Rmd new file mode 100644 index 00000000..8f313937 --- /dev/null +++ b/vignettes/articles/Accessing-culture-datasets-with-the-eurostat-package.Rmd @@ -0,0 +1,270 @@ +--- +title: "Accessing culture datasets with the eurostat package" +date: "`r Sys.Date()`" +--- + +```{r, include = FALSE} +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>" +) +``` + +# Introduction + +The eurostat package can be used to access datasets related to various facets of life. Datasets belonging to the culture sector are scattered across different database tables. Eurostat has collected datasets related to the cultural sector, for example datasets that are related to culture, music, and literature, in a special section in their website: [https://ec.europa.eu/eurostat/web/culture/database/data-domain](https://ec.europa.eu/eurostat/web/culture/database/data-domain). + +Downloading these datasets manually is demonstrated in this article. + +# Loading the eurostat R package + +```{r setup} +library(eurostat) +``` + +# Dataset examples + +## EU Labour Force Survey (EU-LFS) + +Download like this: + +```{r eu-lfs} +# J59: Motion picture, video and television programme production, +# sound recording and music publishing activities +# R90: Creative, arts and entertainment activities +# R91: Libraries, archives, museums and other cultural activities + +stats <- get_eurostat( + "lfsq_egan22d", + filters = + list( + nace_r2 = c("R90", "R91", "J59") + ) + ) +stats_label <- label_eurostat(stats, code = "nace_r2") +``` + +Quick glance at dataset: + +```{r} +head(stats) +``` + +Quick glance at labeled dataset: + +```{r} +head(stats_label) +``` + +Variable names: + +```{r} +label_eurostat_vars(names(stats), id = "lfsq_egan22d") +``` + +## Structured business statistics (SBS) + +First we must ask the question: What are music-related goods and services in the vast sea of structured business statistics? From the [Eurostat website](https://ec.europa.eu/eurostat/web/culture/database/data-domain#Business%20statistics) documentation: + +>"No data collection specifically on music exists. The various EU harmonised surveys and data collections include only a few items of information on the topic. +> +>A difficulty with those is that statistical classifications and variables often do not differentiate music from other cultural activities in broader categories, such as live performances, or artistic creation." + +Two concrete examples are given: Sound recording and music publishing activities (NACE code 59.2) and Manufacture of musical instruments (NACE code 32.2). + +### Sound recording and music publishing activities (NACE code 59.2) + +```{r} +# J592: Sound recording and music publishing activities +music_business1 <- get_eurostat( + id = "sbs_na_1a_se_r2", + filters = + list( + indic_sb = c("V11110", "V12110", "V12120", + "V12150", "12170"), + nace_r2 = c("J592") + ) + ) +head(music_business1) +``` + +### Manufacture of musical instruments (NACE code 32.2) + +```{r} +music_business2 <- get_eurostat( + id = "sbs_na_ind_r2", + filters = + list( + indic_sb = c("V11110", "V12110", "V12120", + "V12130", "12150"), + nace_r2 = c("C322") + ) + ) +head(music_business2) +# Or +# music_business2 <- get_eurostat( +# id = "sbs_na_ind_r2", +# filters = list( +# indic_sb = c("V11110", "V12110", "V12120", +# "V12130", "12150"), +# nace_r2 = c("C3220") +# ) +# ) +``` + +### Music-related goods production + +Also, database on the production of various goods contains information about production of music-related goods, such as instruments and recorded media. + +The code to download the dataset: + +```{r sbs} +stats <- get_eurostat("lfsq_egan22d", + filters = + list(nace_r2 = c("R90", "R91", "J59"))) +stats_label <- label_eurostat(stats, code = "nace_r2") +``` + +## International trade in goods statistics (ITGS) (OM_dataset_sec_eurostat_003) + +What, then, are these specified music-related goods? From [Eurostat website](https://ec.europa.eu/eurostat/web/culture/database/data-domain#International%20trade): + +>"The domain of international trade in goods includes annual data on trade of musical instruments and parts of thereof. +> +>Since 2017, data on recorded media containing only music have not been collected as a separate category. In statistics on international trade in services, music items are included in the existing categories: +> +>- audio-visual services +>- artistic services +>- licences" + +(Source: [https://ec.europa.eu/eurostat/web/culture/database/data-domain#International%20trade](https://ec.europa.eu/eurostat/web/culture/database/data-domain#International%20trade)) + +Download: + +```{r} +stats <- get_eurostat("ext_lt_intertrd") +stats_label <- label_eurostat(stats, code = "sitc06") +``` + +```{r} +# C322: Manufacture of musical instruments +stats <- get_eurostat("ext_tec09", filters = list(nace_r2 = "C322")) +``` + +## Data by domain: Culture + +### Music + +Original information can be found here: [https://ec.europa.eu/eurostat/web/culture/database/data-domain](https://ec.europa.eu/eurostat/web/culture/database/data-domain) + +### Employment + +There is an Excel file that contains the number of persons employed as musicians, singers and composers (ISCO code 2652, main job) in years 2019-2021. + +2 NACE codes could be used to collect data from EU labour force survey (EU-LFS) statistics: + +- sound recording and music publishing activities (59.2) +- manufacture of musical instruments (32.2) + + +## Business statistics + +### Sound recording and music publishing activities (NACE code 59.2) + +```{r} +music_business1 <- get_eurostat( + id = "sbs_na_1a_se_r2", + filters = + list( + indic_sb = c("V11110", "V12110", "V12120", + "V12150", "12170"), + nace_r2 = c("J592") + ) + ) +head(music_business1) +``` + +### Manufacture of musical instruments + +```{r} +music_business2 <- get_eurostat( + id = "sbs_na_ind_r2", + filters = + list( + indic_sb = c("V11110", "V12110", "V12120", + "V12130", "12150"), + nace_r2 = c("C322") + ) + ) +head(music_business2) +# Or +# music_business2 <- get_eurostat( +# id = "sbs_na_ind_r2", +# filters = list( +# indic_sb = c("V11110", "V12110", "V12120", +# "V12130", "12150"), +# nace_r2 = c("C3220") +# ) +# ) +``` + +### Music-related goods production + +Downloading PRODCOM data is is done via different route than the usual datasets and the functionality is currently experimental. The logic of the functions, however, is identical to the currently existing functions. Here is a non-functional example of how the workflow should look: + +```{r remotes-example, eval=FALSE} +remotes::install_github("ropengov/eurostat", ref = "v4.1") +``` + +```{r prodcom-example, eval=FALSE} +prodcom <- get_eurostat_sdmx( + id = "DS-059359", + compressed = FALSE, + agency = "eurostat_comext", + filters = + list( + FREQ = c("A"), + product = c("18121920", "18201010", "18201030", + "18201050", "18201070", "18202050", + "18202070", "32201110", "32201130", + "32201150", "32201200", "32201310", + "32201340", "32201370", "32201400", + "32201510", "32201530", "32201600", + "32202000"), + DECL = c("001", "003", "004", "005", "006", + "007", "008", "009", "010", "011", + "017", "018", "024", "028", "030", + "032", "038", "046", "052", "053", + "054", "055", "060", "061", "063", + "064", "066", "068", "091", "092", + "093", "096", "097", "098", "2027", + "600"), + INDICATORS = c("PRODVAL"), + PRCCODE = c("18121920", "18201010", "18201030", + "18201050", "18201070", "18202050", + "18202070", "32201110", "32201130", + "32201150", "32201200", "32201310", + "32201340", "32201370", "32201400", + "32201510", "32201530", "32201600", + "32202000"))) + +prodcom_labeled <- label_eurostat_sdmx( + x, + agency = "eurostat_comext", + id = "DS-056120" + ) +``` + +The URL to this custom dataset: https://ec.europa.eu/eurostat/databrowser/view/DS-056120__custom_4088056/bookmark/table?lang=en&bookmarkId=a25712df-96d0-445a-95d6-4b807e83be43 + +# Session info + +```{r} +sessionInfo() +``` + + + + + + diff --git a/vignettes/articles/blogposts.Rmd b/vignettes/articles/blogposts.Rmd new file mode 100644 index 00000000..d0e41884 --- /dev/null +++ b/vignettes/articles/blogposts.Rmd @@ -0,0 +1,16 @@ +--- +title: "Blog posts" +date: "2022-02-07" +--- + +```{r, include = FALSE} +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>" +) +``` + +Here are some blog posts where eurostat package has been featured. If you have used eurostat package in your workflow and you would like to be included on this list, please let us know! + + * [Package release](https://rpubs.com/muuankarski/27119) + * [Interactive widgets](https://www.mytinyshinys.com/2017/07/11/eurostat/) by Andrew Clark diff --git a/vignettes/articles/cheatsheet.Rmd b/vignettes/articles/cheatsheet.Rmd new file mode 100644 index 00000000..bec5871d --- /dev/null +++ b/vignettes/articles/cheatsheet.Rmd @@ -0,0 +1,15 @@ +--- +title: "Cheat sheet: eurostat R package" +date: "2022-02-07" +--- + +```{r, include = FALSE} +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>" +) +``` + + * [eurostat R package: cheat sheet (RStudio release version)](https://github.com/rstudio/cheatsheets/blob/main/eurostat.pdf) + + * [eurostat R package: cheat sheet (rOpenGov development version)](https://github.com/rOpenGov/eurostat/blob/master/inst/extras/cheatsheet/eurostat_cheatsheet.pdf) diff --git a/vignettes/articles/dimlst_vs_allconceptschemes.Rmd b/vignettes/articles/dimlst_vs_allconceptschemes.Rmd new file mode 100644 index 00000000..ecfa452e --- /dev/null +++ b/vignettes/articles/dimlst_vs_allconceptschemes.Rmd @@ -0,0 +1,353 @@ +--- +title: "Differences between dimlst.dic and ALL_CONCEPTSCHEMES.xml" +date: "`r Sys.Date()`" +editor_options: + chunk_output_type: inline +output: + html_document: + toc: yes +--- + +# Introduction + +As Eurostat is in the process of getting rid of Bulk Download facilities, there are inevitably some changes that affect the `eurostat` package as well. One of those is the removal of old `.dic` objects that have been used in translating Eurostat variable codes into cleartext labels in English, French or German. + +All things must pass. We have removed the old `label_eurostat_vars()` function that simply downloaded `dimlst.dic`, sort of 'master file' of all available codes and their cleartext labels, and used that to label all Eurostat datasets. Now labeling is done by downloading a Concept Scheme file for each individual dataset and using that information to give labels to the dataset in the desired language. + +# Comparison of old and new + +An example of the old English version dimlst.dic file (downloaded 2023-12-18 from [here](https://ec.europa.eu/eurostat/estat-navtree-portlet-prod/BulkDownloadListing?sort=1&dir=dic%2Fen)), 10 first rows: + +```{text} +ACCIDENT Accident +ACCOMMOD Mode of accommodation +ACCOMSIZE Size of accommodation by number of bedplaces +ACCOMUNIT Accommodation unit +ACL00 Classification of activities for time use +ACTIVITY Type of activity +ADMINISTR Administration indicator +AFFORD Affordability +AGE Age class +AGECHILD Age of the child +AGEDEF Age definition +``` + +An example of the new Concept Scheme file for dataset `NAMA_10_GDP` (see instructions for downloading [here](https://wikis.ec.europa.eu/display/EUROSTATHELP/API+SDMX+2.1+-+metadata+query#APISDMX2.1metadataquery-SDMX2.1endpoint-REST-SDMX-ML2.1ConceptScheme)): + +```{xml} + + + Time frequency + + + Zeitliche Frequenz + + + Fréquence (relative au temps) + + + + + + + + + + Unit of measure + + + Maßeinheit + + + Unité de mesure + + + + + + + +``` + +The apparent benefit of XML presentation is that all language versions can be found in the same file. This makes the files a bit larger than old .tsv files but for individual datasets the size is still manageable. + +Concept id's or Ref id's ("unit", "UNIT") can be used to look up further classifications in Codelists. In the old .dic metaphor all definition files were "dictionaries" where `dimlst.dic` was a special case, a dictionary of dictionaries, whereas in the new metaphor there is more of a hierarchy of definitions. For example in the case of units all available English labels can be downloaded in JSON-stat and TSV formats: + +https://ec.europa.eu/eurostat/api/dissemination/sdmx/2.1/codelist/ESTAT/UNIT?format=TSV&lang=en +https://ec.europa.eu/eurostat/api/dissemination/sdmx/2.1/codelist/ESTAT/UNIT?format=JSON&lang=en + +However, the new TSV files and the old .dic files are virtually identical: + +```{text} +# unit.dic +TOTAL Total +NR Number +NR_HAB Number per inhabitant +THS Thousand +MIO Million +BN Billion +CT Euro cent +EUR Euro +THS_EUR Thousand euro +MIO_EUR Million euro +BN_EUR Billion euro +[...] +[711 lines] + +# ESTAT_UNIT_22.0_EN.tsv +TOTAL Total +NR Number +NR_HAB Number per inhabitant +THS Thousand +MIO Million +BN Billion +CT Euro cent +EUR Euro +THS_EUR Thousand euro +MIO_EUR Million euro +BN_EUR Billion euro +[...] +[711 lines] +``` + +# Replicating old style dimlst.dic with new xml files + +In some cases it may have been useful to access all labels for all datasets from a single file. In theory this is possible with Concept Schemes as well, by downlaoding all concept schemes at once in the form of "ALL_CONCEPTSCHEMES.xml" file, at 29.7 Mb large. We can parse the xml file to create a list that is similar to the old `dimlst.dic` object to see if there are any functional differences. + +```{r eval=FALSE} +library(xml2) +# file downloaded from https://ec.europa.eu/eurostat/api/dissemination/sdmx/2.1/conceptscheme/ESTAT/?compressed=true and unpacked +xml_object <- xml2::read_xml("ALL_CONCEPTSCHEMES.xml") +number <- length(xml2::xml_find_all(xml_object, ".//s:Concept")) +dic_df <- data.frame( + code_name = rep(NA, times = number), + full_name = rep(NA, times = number) +) +attributes <- xml2::xml_attrs(xml2::xml_find_all(xml_object, ".//s:Concept")) +contents <- xml2::xml_text(xml2::xml_find_all(xml_object, ".//s:Concept/c:Name[@xml:lang='en']")) +for (i in seq_len(number)) { + dic_df$code_name[i] <- unname(attributes[[i]]["id"]) +} +# This is ok because the length of and is the same +dic_df$full_name <- contents +``` + +We can see that there are more unique codes than labels and that some labels are being used in several different codes: + +```{r eval=FALSE} +length(unique(dic_df$full_name)) +# [1] 586 +length(unique(dic_df$code_name)) +# [1] 592 +``` + +To make the data.frame similar to the one that we would get from reading a tab-separated .dic object: + +```{r eval=FALSE} +# Select unique rows +library(dplyr) + +new_df <- dic_df %>% + distinct() + +# codes toupper +new_df$code_name <- toupper(new_df$code_name) + +new_df_sort <- new_df[order(new_df$code_name),] + +# Remove row numbers +rownames(new_df_sort) <- NULL + +head(new_df_sort) +# code_name full_name +# 1 ACCIDENT Accident +# 2 ACCOMMOD Mode of accommodation +# 3 ACCOMSIZE Size of accommodation by number of bedplaces +# 4 ACCOMUNIT Accommodation unit +# 5 ACL00 Classification of activities for time use +# 6 ACTIVITY Type of activity +``` + +As comparison to the `dimlst.dic` object: + +```{r eval=FALSE} +# downloaded from https://ec.europa.eu/eurostat/estat-navtree-portlet-prod/BulkDownloadListing?sort=1&dir=dic%2Fen +dimlst_dic <- readr::read_tsv("dimlst.dic", + col_names = c("code_name", "full_name"), + col_types = readr::cols(.default = readr::col_character())) + +head(dimlst_dic) +## A tibble: 6 × 2 +# code_name full_name +# +# 1 ACCIDENT Accident +# 2 ACCOMMOD Mode of accommodation +# 3 ACCOMSIZE Size of accommodation by number of bedplaces +# 4 ACCOMUNIT Accommodation unit +# 5 ACL00 Classification of activities for time use +# 6 ACTIVITY Type of activity +``` + +Clearly, the two objects have different types (the former is a data.frame, the latter is a tibble), but that doesn't stop us from noticing that at least the 6 first rows are similar with each other. However, `dimlst.dic` has 623 rows while `new_df` object has 593 rows (obs.). Let's find out what the differences are: + +```{r eval=FALSE} +setdiff(dimlst_dic$code_name, new_df_sort$code_name) +# [1] "AGR_INP" "CALCMETH" "DIMLST" "ECOSYST" "ECOSYST_C" "FARMSIZE" "HLTH_HLE" +# [8] "HOSPCARE" "HOUS_ANI" "INDIC_AGR" "IND_ACCT" "IND_IMPV" "ISSUER" "LEARNING" +# [15] "LEV_INTRF" "MANSTO" "NRG_FLOW" "NRG_TECH" "OBS_STATUS" "OGA_FAM" "OGA_NRH" +# [22] "OGA_RH" "OGA_TYPE" "PEDS" "PERS_INV" "PRD_ACCT" "PRD_AMO" "RAWMATPR" +# [29] "RAWMATSEC" "REVDATE" "SIZE_TUR" "TABLE_DIC" "TIME" "VOT_CAT" "WEEK" +# [36] "YN_CARE" "YN_DIF" "YN_DIS" +# length: 38 items +length(setdiff(dimlst_dic$code_name, new_df_sort$code_name)) +# [1] 38 +setdiff(new_df_sort$code_name, dimlst_dic$code_name) +# [1] "FIELDID" "INDIC_EU" "OBS_FLAG" "OBS_VALUE" "SIZEN_R2" "TARGET" "TARGET_FLAG" +# [8] "TIME_PERIOD" +length(setdiff(new_df_sort$code_name, dimlst_dic$code_name)) +# [1] 8 +``` + +To summarize, the old `dimlst.dic` file has 38 codes that are not found in the `ALL_CONCEPTSCHEMES.xml` file. The new `ALL_CONCEPTSCHEMES.xml` has 8 codes that are not found in the old `dimlst.dic`. + +For more information about the different fields, let's print the codes and their descriptions. Unique to `dimlst_dic` object: + +```{r eval=FALSE} +print(dimlst_dic[which(dimlst_dic$code_name %in% setdiff(dimlst_dic$code_name, new_df_sort$code_name)),], n = 40) +# A tibble: 38 × 2 +# code_name full_name +# +# 1 AGR_INP Agricultural inputs +# 2 CALCMETH Calculation method +# 3 DIMLST null +# 4 ECOSYST Ecosystem typology +# 5 ECOSYST_C Ecosystem typology - converted +# 6 FARMSIZE Size of farm +# 7 HLTH_HLE Health and life expectancy +# 8 HOSPCARE Hospital care +# 9 HOUS_ANI Animal housing +# 10 INDIC_AGR Agricultural indicators +# 11 IND_ACCT Industries and accounting items +# 12 IND_IMPV Industries, imports and valuations +# 13 ISSUER Type of issuer +# 14 LEARNING Learning form +# 15 LEV_INTRF Level of interference +# 16 MANSTO Manure storage +# 17 NRG_FLOW Energy flows +# 18 NRG_TECH Energy technologies +# 19 OBS_STATUS Observation status (Flag) +# 20 OGA_FAM Other gainful activity of the family members +# 21 OGA_NRH Other gainful activity of the holder (not related to the agricultural holding) +# 22 OGA_RH Other gainful activity of the holder (related to the agricultural holding) +# 23 OGA_TYPE Types of other gainful activity (OGA) related to the agricultural holding +# 24 PEDS Potential Environmentally Damaging Subsidies (ESA transfers) +# 25 PERS_INV Persons involved in the accident +# 26 PRD_ACCT Products and accounting items +# 27 PRD_AMO Products, adjustments and market output +# 28 RAWMATPR Primary raw materials +# 29 RAWMATSEC Secondary raw materials +# 30 REVDATE Revision date +# 31 SIZE_TUR Size classes of turnover +# 32 TABLE_DIC null +# 33 TIME Period of time +# 34 VOT_CAT Category of voters +# 35 WEEK Calendar week +# 36 YN_CARE Use of profesional care - Yes/No +# 37 YN_DIF Difficulties - Yes/No +# 38 YN_DIS Disability - Yes/No +``` + +Unique to new_df or new_df_sort: + +```{r eval=FALSE} +new_df_sort[which(new_df_sort$code_name %in% setdiff(new_df_sort$code_name, dimlst_dic$code_name)),] +# code_name full_name +# 152 FIELDID Agricultural product +# 221 INDIC_EU Indicators for EU2020 project +# 364 OBS_FLAG Observation status (Flag) +# 365 OBS_VALUE Observation value +# 464 SIZEN_R2 Enterprise size and Nace Rev. 2 +# 502 TARGET TARGET Observation value +# 503 TARGET_FLAG TARGET Observation status (Flag) +# 510 TIME_PERIOD Time +``` + +Of these, "FIELDID / Agricultural product" seems almost like an input error as there are also "prod_apr / Agricultural product (old codes)" and "agriprod / Agricultural products" on the list. If that were the case, the correct course of action is to of course give feedback to Eurostat. + +# Types of duplicates + +There are also some duplicates in the list created from the XML file. Duplicates exist both in the `code_name` column or in the `full_name` column. + +```{r eval=FALSE} +new_df_sort[duplicated(new_df_sort$code_name),] +# code_name full_name +# 471 SO_EUR Standardoutput in Euros + +new_df_sort[duplicated(new_df_sort$full_name),] +# code_name full_name +# 35 ASYL_APP Applicant type +# 179 HHTYPE Type of household +# 227 INDIC_INN Innovation indicator +# 233 INDIC_NRG Energy indicator +# 237 INDIC_SBS Economical indicator for structural business statistics +# 452 SECTPART Sector (ESA 2010) +# 528 TY Type of expenditure +``` + +The differences can be due to typos (probably ?): + +```{r eval=FALSE} + +new_df_sort[which(new_df_sort$code_name == "SO_EUR"),] +# code_name full_name +# 470 SO_EUR Standard output in Euros +# 471 SO_EUR Standardoutput in Euros + +new_df_sort[which(new_df_sort$full_name == "Type of household"),] +# code_name full_name +# 178 HHTYP Type of household +# 179 HHTYPE Type of household + +new_df_sort[which(new_df_sort$full_name == "Innovation indicator"),] +# code_name full_name +# 226 INDIC_IN Innovation indicator +# 227 INDIC_INN Innovation indicator + +new_df_sort[which(new_df_sort$full_name == "Economical indicator for structural business statistics"),] +# code_name full_name +# 236 INDIC_SB Economical indicator for structural business statistics +# 237 INDIC_SBS Economical indicator for structural business statistics +``` + +...or due to actual differences (?) in the fields, although there could also be some kind of a misunderstanding: + +```{r eval=FALSE} +# Different types of applicants +new_df_sort[which(new_df_sort$full_name == "Applicant type"),] +# code_name full_name +# 24 APPLICANT Applicant type +# 35 ASYL_APP Applicant type + +new_df_sort[which(new_df_sort$full_name == "Energy indicator"),] +# code_name full_name +# 218 INDIC_EN Energy indicator +# 233 INDIC_NRG Energy indicator + +new_df_sort[which(new_df_sort$full_name == "Sector (ESA 2010)"),] +# code_name full_name +# 450 SECTOR10 Sector (ESA 2010) +# 452 SECTPART Sector (ESA 2010) + +new_df_sort[which(new_df_sort$full_name == "Type of expenditure"),] +# code_name full_name +# 144 EXPEN Type of expenditure +# 528 TY Type of expenditure +``` + +# Conclusion + +Changes in methods of delivering metadata affect, naturally, all end users of Eurostat data. With the eurostat package version 4.0.0 we have aimed at retaining the user-facing functionalities and the expected outputs. The interesting world of XML parsing is kept under the hood and should not be of concern for users. + +This document is written mainly as a future reference for ourselves if we might at some point be wondering why something that was possible before is not possible anymore, or for users who have had scripts relying on functions like `label_eurostat_vars()`. + +Feel free to open an issue or a pull request in Github if there are any suggestions or corrections you would like to make. \ No newline at end of file diff --git a/vignettes/articles/eurostat_tutorial.Rmd b/vignettes/articles/eurostat_tutorial.Rmd new file mode 100644 index 00000000..79218a7d --- /dev/null +++ b/vignettes/articles/eurostat_tutorial.Rmd @@ -0,0 +1,399 @@ +--- +title: "Tutorial for the eurostat R package" +date: "`r Sys.Date()`" +editor_options: + chunk_output_type: inline +output: + html_document: + toc: yes +--- + +# R Tools for Eurostat Open Data + +This [rOpenGov](http://ropengov.github.io) R package provides tools to access [Eurostat database](http://ec.europa.eu/eurostat/data/database), which you can also browse on-line for the data sets and documentation. For contact information and source code, see the [package website](http://ropengov.github.io/eurostat/). + +```{r setup, include=FALSE} +# Global options +library(knitr) +opts_chunk$set(fig.path = "fig/") +options(citation.bibtex.max=999) +``` + +# Installation + +Release version [(CRAN)](https://CRAN.R-project.org/package=eurostat): + +```{r install, eval=FALSE} +install.packages("eurostat") +``` + +Development version [(Github)](https://github.com/rOpenGov/eurostat): + +```{r install_devel, eval=FALSE} +library(remotes) +remotes::install_github("ropengov/eurostat") +``` + +Alternatively, development versions (more specifically: development versions in the master branch of eurostat GitHub repository) can be installed with the help of R-universe: + +```{r install_runiverse, eval=FALSE} +# Enable this universe +options(repos = c( + ropengov = "https://ropengov.r-universe.dev", + CRAN = "https://cloud.r-project.org" +)) + +install.packages("eurostat") +``` + +The package is loaded with the library function. + +```{r, echo=FALSE} +library(eurostat) +``` + +Overall, the eurostat package includes the following user-facing functions: + +```{r, echo=FALSE,comment=NA} +cat(paste0(library(help = "eurostat")$info[[2]], collapse = "\n")) +``` + +```{r check_internet} +evaluate <- curl::has_internet() +``` + + +# Finding data + +First stop for most researchers would be to browse the [Eurostat Data Browser website](https://ec.europa.eu/eurostat/databrowser/explore/all/all_themes) or other thematically arranged sections in the Eurostat website. However, the eurostat R package offers some ways to search for datasets without leaving the R interface. + +Function `get_eurostat_toc()` downloads a table of contents (TOC) of eurostat datasets. + +```{r get_eurostat_toc, warning=FALSE, message=FALSE, eval = evaluate} +# Load the package +library(eurostat) + +# Get Eurostat data listing +toc <- get_eurostat_toc() + +# Check the first items +library(knitr) +kable(tail(toc)) +``` + +The values in column 'code' are unique identifiers for each dataset that have to be used when downloading specific datasets. In the `get_eurostat()` function the dataset code is put into the first argument of the function, `id`. + +From eurostat version 4.0.0 onwards the returned TOC object has had an additional column, `hierarchy`. It is used to determine which dataset belongs to which folder. This is helpful for example when downloading datasets in a single folder all at once. + +From eurostat version 4.0.0 onwards it is possible to download TOC objects in French and German as well, in addition to English, which remains the default option. This enables new functionalities in other eurostat functions that have used the TOC object internally but retains backwards-compatibility with old code as the `lang` argument is not mandatory and queries without it continue to deliver the English version of the TOC object. + +```{r get_eurostat_toc2, warning=FALSE, message=FALSE, eval = evaluate} +kable(head(get_eurostat_toc(lang = "fr"))) +``` + +With `search_eurostat()` you can search the table of contents for particular patterns, e.g. all datasets related to *passenger transport*. With the `type` argument the user can choose which types of datasets the search should return: datasets, tables, folders or all types (the default). + +According to [Eurostat database basic terminology](https://ec.europa.eu/eurostat/statistics-explained/index.php?title=Glossary:Eurostat_database_-_basic_terminology) "tables (predefined tables) are used to provide easy access to the main statistical indicators. They are based in general on datasets and are derived from them. They are predefined, non-modifiable and presented as two or three dimensional tables." The more general purpose datasets are, on the other hand, described to be "multi-dimensional tables" that have "up to 8 dimensions" and are used "store the base data, more appropriate for use by statistical and other experts via special applications". + +```{r search_eurostat, warning=FALSE, message=FALSE, eval = evaluate} +# info about passengers +kable(head(search_eurostat("passenger transport"))) +``` + +From eurostat version 4.0.0 onwards it possible to perform searches also from dataset codes. This is done by specifying the search column by setting the `column` attribute to `"code"`. Searching for codes can be useful in finding datasets that belong to the same folder or are part of a larger theme that shares similar dataset code patterns, such as "migr" for migration related statistics and "tran" in the case of (multimodal) transport statistics. + +```{r search_eurostat2, warning=FALSE, message=FALSE, eval = evaluate} +kable(head(search_eurostat("migr", column = "code"))) +``` + +Another new addition in version 4.0.0 is the option to perform searches from French and German language TOC versions as well by setting the `lang` argument to `"fr"` or `"de"`. Naturally, dataset codes are shared between language versions so French and German language searches should be conducted only on the title column. + +```{r search_eurostat3, warning=FALSE, message=FALSE, eval = evaluate} +kable(head(search_eurostat("flughafen", column = "title", lang = "de"))) +``` + +As mentioned in the beginning, codes for different dataset can be found also from the [Eurostat database](http://ec.europa.eu/eurostat/data/database). The Eurostat database gives codes in the Data Navigation Tree in parenthesis after the full name of the dataset, folder, or table. + +# Downloading data + +The package supports two of the Eurostats download methods: the SDMX 2.1 REST API and the API Statistics ("JSON API"). The bulk download facility is the fastest method to download whole datasets. To download only a small section of the dataset the JSON API is faster, as it allows to make a data selection before downloading. + +The end user does not usually have to bother where original data is downloaded, as both data sources are accessed via the main download function `get_eurostat()`. If only the table id is given, the whole table is downloaded from the SDMX 2.1 REST API. If any filters are given the JSON API is used instead. However, the `get_eurostat_json()` function used internally is also a user-facing function so that can be used as well. + +We will use the dataset 'Modal split of air, sea and inland passenger transport' as an example dataset in this vignette. This is the percentage share of each mode of transport in total inland transport, expressed in passenger-kilometres (pkm) based on transport by passenger cars, buses and coaches, trains, aircraft, and seagoing vessels. All data should be based on movements on national territory, regardless of the nationality of the vehicle. However, the data collection is not harmonized at the EU level. For more detailed information about the dataset, see [Reference Metadata](https://ec.europa.eu/eurostat/cache/metadata/en/tran_hv_ms_esms.htm). + +Pick and print the id of the data set to download: +```{r get_id, warning=FALSE, message=FALSE, results='asis', eval = evaluate} +# Perform search, the output is a table of search results +search_results <- search_eurostat("Modal split of air, sea and inland passenger transport", + type = "dataset" +) + +# Since our search term was so detailed, we should have only 1 result / 1 row +kable(head(search_results)) + +# Get the id from the table +id <- search_results$code[1] + +# Check the id +print(id) +``` + + +```{r reevaluate, include = FALSE, eval = evaluate} +if (!is.na(id)) evaluate <- TRUE else evaluate <- FALSE +``` + +Get the whole corresponding table. As the table is annual data, it is more +convenient to use a numeric time variable than use the default date format, where yearly data would be coerced to be on the first day of the year (e.g. 2000-01-01). + +```{r get_eurostat, warning=FALSE, message=FALSE, results='asis', eval = evaluate} +dat <- get_eurostat(id, time_format = "num", stringsAsFactors = TRUE) +``` + +The structure of the downloaded data set can be investigated by using the base R `str()` function: + +```{r str_dat, warning=FALSE, message=FALSE, eval = evaluate} +str(dat) +``` + +```{r head_dat, warning=FALSE, message=FALSE, results='asis', eval = evaluate} +kable(head(dat)) +``` + +You can get only a part of the dataset by defining `filters` argument. It +should be named list, where names corresponds to variable names (lower case) and +values are vectors of codes corresponding desired series (upper case). For +time variable, in addition to a `time` or `TIME_PERIOD` , also `sinceTimePeriod`, `untilTimePeriod` and a `lastTimePeriod` can be used. + +More information about filtering can be found in `get_eurostat()` and `get_eurostat_json()` function documentation. + +```{r get_eurostat_json, warning=FALSE, message=FALSE, results='asis', eval=evaluate} +dat2 <- get_eurostat(id, filters = list(geo = c("EU27_2020", "FI"), lastTimePeriod = 1), time_format = "num") +kable(dat2) +``` + +## Replacing codes with labels + +By default variables are returned as Eurostat codes, but to get human-readable +labels instead, use a `type = "label"` argument in `get_eurostat()`. + +```{r json_labels, warning=FALSE, message=FALSE, results='asis', eval = evaluate} +dat_labeled2 <- get_eurostat(id, + filters = list( + geo = c("EU27_2020", "FI"), + lastTimePeriod = 1 + ), + type = "label", time_format = "num" +) +kable(head(dat_labeled2)) +``` + +Eurostat codes in the downloaded data set can be replaced with +human-readable labels from the Eurostat dictionaries with the +`label_eurostat()` function. + +```{r labels, warning=FALSE, message=FALSE, results='asis', eval = evaluate} +dat_labeled <- label_eurostat(dat) +kable(head(dat_labeled)) +``` + +The `label_eurostat_vars()` allows conversion of variable names as well. + +```{r name_labels, eval = evaluate} +print(label_eurostat_vars(id = "tran_hv_ms_psmod", names(dat_labeled))) +``` + + +Vehicle information has 5 levels. You can check them now with: + +```{r vehicle_levels, eval = evaluate} +levels(dat_labeled$vehicle) +``` + +## Downloading data interactively + +New function in the eurostat package version 4.0.0 is the `get_eurostat_interactive()` function that allows users to search and download datasets with the help of interactive menus. If the user already knows which dataset they want to download, the `get_eurostat_interactive()` function can also take a dataset code as a parameter, skipping the search part of the interactive menu. Below we will demonstrate the whole process from search to download to printing a citation for the dataset, utilizing several different eurostat package functions at once. + +```{text} +> get_eurostat_interactive() +Select language + +1: English +2: French +3: German + +Selection: 1 +Enter search term for data: aviation +Which dataset would you like to download? + +1: [tran_sf_aviagah] Air accident victims in general aviation, by country of occurrence and country of registration of aircraft - maximum take-off mass above 2250 kg (source: EASA) +2: [tran_sf_aviagal] Air accident victims in general aviation by country of occurrence and country of registration of aircraft - maximum take-off mass under 2250 kg (source: EASA) +3: [avia_ec_enterp] Number of aviation and airport enterprises +4: [avia_ec_emp_ent] Employment in aviation and airport enterprises by sex + + +Selection: 4 +Download the dataset? + +1: Yes +2: No + +Selection: 1 +Would you like to use default download arguments or set them manually? + +1: Default +2: Manually selected + +Selection: 1 +trying URL 'https://ec.europa.eu/eurostat/api/dissemination/sdmx/2.1/data/avia_ec_emp_ent?format=TSV&compressed=true' +Content type 'text/tab-separated-values; charset=UTF-8' length 1354 bytes +================================================== +downloaded 1354 bytes + +Table avia_ec_emp_ent cached at /var/folders/f4/h_r3y60n0nn0qm6qx5hnx1s00000gn/T//RtmpDJ1gUA/eurostat/60ee371bcdcc9b130a20514d1e0d574d.rds +Print dataset citation? + +1: Yes +2: No + +Selection: 1 +Print code for downloading dataset? + +1: Yes +2: No + +Selection: 1 +Print dataset fixity checksum? + +1: Yes +2: No + +Selection: 1 +##### DATASET CITATION: + +@Misc{avia-ec-emp-ent-2016-4-20, + title = {Employment in aviation and airport enterprises by sex (avia\_ec\_emp\_ent)}, + url = {https://ec.europa.eu/eurostat/web/products-datasets/product?code=avia_ec_emp_ent}, + language = {english}, + year = {2016}, + author = {{Eurostat}}, + urldate = {2023-12-19}, + type = {Dataset}, + note = {Accessed 2023-12-19, dataset last updated 2016-04-20}, +} + +##### DOWNLOAD PARAMETERS: + +get_eurostat(id = 'avia_ec_emp_ent') + +##### FIXITY CHECKSUM: + +Fixity checksum (md5) for dataset avia_ec_emp_ent: 36975282eaaea50a6e5f0e6cd64ef4d2 + +# A tibble: 450 × 6 + freq enterpr sex geo TIME_PERIOD values + + 1 A AIRP F CY 2006-01-01 192 + 2 A AIRP F CY 2007-01-01 240 + 3 A AIRP F CY 2008-01-01 514 + 4 A AIRP F CY 2009-01-01 3278 + 5 A AIRP F CY 2010-01-01 2587 + 6 A AIRP F CY 2011-01-01 2255 + 7 A AIRP F CY 2012-01-01 2954 + 8 A AIRP F CZ 2001-01-01 0 + 9 A AIRP F CZ 2002-01-01 0 +10 A AIRP F CZ 2003-01-01 0 +# ℹ 440 more rows +# ℹ Use `print(n = ...)` to see more rows +``` + +# Selecting and modifying data + +## EFTA, Eurozone, EU and EU candidate countries + +To facilitate smooth visualization of standard European geographic areas, the package provides ready-made lists of the country codes used in the eurostat database for EFTA (efta\_countries), Euro area (ea\_countries), EU (eu\_countries) and EU candidate countries (eu\_candidate\_countries). These can be used to select specific groups of countries for closer investigation. For conversions with other standard country coding systems, see the [countrycode](https://CRAN.R-project.org/package=countrycode) R package. To retrieve the country code list for EFTA, for instance, use: + +```{r, echo=TRUE, eval = evaluate} +data(efta_countries) +kable(efta_countries) +``` + + +## EU data from 2012 in all vehicles: + +```{r eu_12, eval = evaluate} +dat_eu12 <- subset(dat_labeled, geo == "European Union - 27 countries (from 2020)" & TIME_PERIOD == 2012) +kable(dat_eu12, row.names = FALSE) +``` + +## EU data from 2008 - 2020 with vehicle types as variables: + +Reshaping the data is best done with `spread()` in `tidyr`. +```{r eu_vehicles_table, eval = evaluate} +library("tidyr") +dat_eu_0012 <- subset(dat, geo == "EU27_2020" & TIME_PERIOD %in% c(2008:2020)) +dat_eu_0012_wide <- spread(dat_eu_0012, vehicle, values) +kable(subset(dat_eu_0012_wide, select = -geo), row.names = FALSE) +``` + +## Train passengers for selected EU countries in 2008 - 2020 + +```{r trains_table, eval = evaluate} +dat_trains <- subset(dat_labeled, geo %in% c("Austria", "Belgium", "Finland", "Sweden") & + TIME_PERIOD %in% c(2008:2020) & + vehicle == "Trains") +dat_trains_wide <- spread(dat_trains, geo, values) +kable(subset(dat_trains_wide, select = -vehicle), row.names = FALSE) +``` + + +## Other packages + +### Strongly recommended + +The `giscoR` ([package homepage](https://ropengov.github.io/giscoR/)) package used to be only suggested but starting from `eurostat` version 4.0.0 it has become a dependency of eurostat and required for using geospatial data functions. In addition to using `get_eurostat_geospatial()` from the `eurostat` package, it is highly recommended to study `giscoR` package functions and vignettes for creating more sophisticated visualisations to support geospatial analyses. + +### Packages with similar functionalities + +The [restatapi](https://CRAN.R-project.org/package=restatapi) R package has similar functionalities and some familiar function names for seasoned eurostat R package users. The `restatapi` package focuses more on statistical data and retrieving and returning data in a non-tidy data format. + +The [rsdmx](https://CRAN.R-project.org/package=rsdmx) and [rjsdmx](https://CRAN.R-project.org/package=RJSDMX) R packages provide a more generic method to download data from a wide variety of statistical data providers that utilize the Statistical Data and Metadata eXchange ([SDMX](https://sdmx.org)) standards. + +# Further examples + +For further examples, see articles in the [package homepage](http://ropengov.github.io/eurostat/). + +# Citations and related work + +### Citing the data sources + +Eurostat data: cite [Eurostat](http://ec.europa.eu/eurostat/). + +Administrative boundaries: cite EuroGeographics + + +### Citing the eurostat R package + +For main developers and contributors, see the [package homepage](http://ropengov.github.io/eurostat). + +This work can be freely used, modified and distributed under the +BSD-2-clause (modified FreeBSD) license: + +```{r citation, message=FALSE, eval=TRUE, echo=TRUE} +citation("eurostat") +``` + + +### Contact + +For contact information, see the [package homepage](http://ropengov.github.io/eurostat). + + +# Version info + +This tutorial was created with + +```{r sessioninfo, message=FALSE, warning=FALSE} +sessioninfo::session_info() +``` diff --git a/vignettes/articles/mapping.Rmd b/vignettes/articles/mapping.Rmd new file mode 100755 index 00000000..48912477 --- /dev/null +++ b/vignettes/articles/mapping.Rmd @@ -0,0 +1,399 @@ +--- +title: "Mapping Regional Data, Mapping Metadata Problems" +author: Daniel Antal (CFA) +date: "`r Sys.Date()`" +output: + html_document: + toc: yes +editor_options: + markdown: + wrap: 80 + canonical: true +--- + +```{r, include = FALSE} +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>", + tidy = "styler", + dev = "ragg_png", + warning = FALSE, + dpi = 300, + out.width = "100%" +) +``` + +The [regions](https://regions.dataobservatory.eu/) package offers tools two work +with regional statistics. It is an offspring of the +[eurostat](https://ropengov.github.io/eurostat/) package of +[rOpenGov](https://ropengov.org/), which offers data search, download, +manipulation and visualization for Eurostat's [European +statistics](https://ec.europa.eu/eurostat). While you can use +[regions](https://regions.dataobservatory.eu/) for any European regional +statistics, and with a limited functionality, any regional statistics from other +parts of the world, this article provides a combined use case for the two +packages. + +```{r setup} +library(regions) +library(eurostat) +library(dplyr) +``` + +Eurostat's main function for data access is `get_eurostat()`, but in this case +we will use the more specific `get_eurostat_json()` to avoid downloading +unnecessary aspects of this data product. Let us get a long-established regional +dataset, the full-time equivalent (FTE) R&D workforce, in both sexes, in all +sectors and all professional positions, and limit our data to two years only: + +```{r rd-workforce-get, eval=FALSE} +regional_rd_personnel <- get_eurostat_json( + id = "rd_p_persreg", + filters = list( + sex = "T", + prof_pos = "TOTAL", + sectperf = "TOTAL", + unit = "FTE" + ) +) + +regional_rd_personnel <- regional_rd_personnel %>% + filter(time %in% c("2009", "2018")) +``` + +We have saved this filtered datasets as `regions::regional_rd_personnel` in the +[regions](https://regions.dataobservatory.eu/) package. + +```{r rd-presaved} +data("regional_rd_personnel") +``` + +We have quiet a few missing cases: + +```{r missing-cases} +summary(is.na(regional_rd_personnel$values)) +``` + +But this is not the only problem with the dataset. + +## Choropleth Map + +Let us try to place the data on a `ggplot2` map. + +```{r} +library(ggplot2) +``` + +Let us download a map with `get_eurostat_geospatial()`. We will use the +`NUTS2016`, i.e., `year = 2016`, which is the regional boundary definition set +in 2016 and used in the period 2018-2020. This is the most used definition in +2021. + +```{r get-map} +# Need to load sf for using dplyr methods with sf objects +library(sf) + +map_nuts_2 <- get_eurostat_geospatial( + resolution = "60", nuts_level = "2", + year = 2016 +) +``` + +You should always join your data with the geometric information of the regions +starting from left with the map: + +```{r} +indicator_with_map <- map_nuts_2 %>% + left_join(regional_rd_personnel, by = "geo") +``` + +Huge parts of Europe are not covered, but the missing values are not randomly +missing. France went under a regional reform; Turkey and Albania did not provide +this data earlier. Ireland has no regional statistics available. + +```{r choro1} +indicator_with_map %>% + ggplot() + + geom_sf(aes(fill = values), + color = "dim grey", linewidth = .1 + ) + + scale_fill_gradient(low = "#FAE000", high = "#00843A") + + facet_wrap(facets = "time") + + labs( + title = "R&D Personnel & Researchers", + subtitle = "In all sectors, both sexes by NUTS 2 regions", + caption = "\ua9 EuroGeographics for the administrative boundaries + \ua9 Tutorial and ready-to-use data on economy.dataobservatory.eu", + fill = NULL + ) + + theme_light() + + theme(legend.position = "none") + + coord_sf( + xlim = c(2377294, 7453440), + ylim = c(1313597, 5628510), + crs = 3035 + ) +``` + +## Missing Values and Seemingly Missing Values + +Some of these problems are real missing data problems, but some of them are +coding problem. In other words, the data is there, but it is not conforming the +boundaries that you have on the `NUTS2016` map. First we need to validate the +geographical coding of the dataset. This is the task of +`regions::validate_nuts_regions()`. + +```{r} +validated_indicator <- regions::validate_nuts_regions(regional_rd_personnel) +``` + +If we validate the dataset, we will see many interesting metadata observations. + +```{r validation-summary, message=FALSE} +library(dplyr) +validation_summary_2016 <- validated_indicator %>% + group_by(time, typology) %>% + summarize( + observations = n(), + values_missing = sum(is.na(values)), + values_present = sum(!is.na(values)), + valid_present = values_present / observations + ) +``` + +Even though the dataset is called [R&D personnel and researchers by sector of +performance, sex and NUTS 2 regions +(rd_p_persreg)](https://appsso.eurostat.ec.europa.eu/nui/show.do?dataset=rd_p_persreg&lang=en), +in fact, it contains data on country and `NUTS1` levels. And it has data on +non-EU countries that in 2009 were not part of the NUTS system. + +```{r} +validation_summary_2016 %>% + ungroup() %>% + filter(time == "2009") +``` + +The situation is not better in 2018: + +```{r} +validation_summary_2016 %>% + ungroup() %>% + filter(time == "2018") +``` + +The dataset is plagued with data that has no place in the `NUTS2016` boundary +definition, and therefore on a `NUTS2016` map! + +What are the non-conforming bits? + +```{r non-conforming-geo} +validated_indicator %>% + filter(!valid_2016) %>% + pull(geo) +``` + +- Plenty of French units. France went under a regional administrative reform, + and we have data about its past, but not in the current boundaries and + coding. +- To a lesser extent, we have the same problem with Poland and the UK. +- We have comparative data from Asia on country level, which ended up in a + regional dataset. +- We have Norway, which is a member of the EEA, and from 2021 it is officially + part of the NUTS2021 system. They were nice to provide their data + consistently for the past. +- We have aggregates like the entire EU or the eurozone. + +## Recoding and Renaming + +The question is, can we save some of the French data? If the boundaries of +regions changed, then we cannot: somebody must reaggregate the number of +researchers who used to work in the newly defined region back then, before the +reform. + +But in some cases, the regional boundaries did not change, only the name and the +code of the region, which is the task performed by `regions::recode_nuts()`: + +```{r recoding} +recoded_indicator <- regional_rd_personnel %>% + regions::recode_nuts( + geo_var = "geo", # your geograhical ID variable name + nuts_year = 2016 # change this for other definitions + ) +``` + +```{r recode-summary, message=FALSE} +recoding_summary <- recoded_indicator %>% + mutate(observations = nrow(.data)) %>% + mutate(typology_change = ifelse(grepl("Recoded", typology_change), + yes = "Recoded", + no = typology_change + )) %>% + group_by(typology_change, time) %>% + summarize( + values_missing = sum(is.na(values)), + values_present = sum(!is.na(values)), + pct = values_present / (values_present + values_missing) + ) +``` + +Let us take a look at the problems identified by `regions::recode_nuts()`: + +```{r} +recoding_summary +``` + +- We were able to recode quite a few data points to the `NUTS2016` definition + for the time of observation 2009 as well as 2018. Sometimes we are recoding + rows that have missing values, which does not help that much: we know where + the data should be, but it is missing anyway. But particularly for the year + 2009 we can save plenty of data by recorded the obsolete coding. + +- We identify further problems. We have coding the that was used in various + time periods, but there is no clear recoding possibility, because the + regions boundaries have changed. To have the history of the data, we would + need to recalculate them, say, by adding up the R&D personnel from each + settlement in the new regional boundary. + +The following non-empty cases were present in the dataset, just not with the +coding that we used in the 2018-2020 period (i.e., the `NUTS2016` coding.) We +are able to save 27 observations just by fixing the regional codes! + +```{r geocode-changes} +recoded_indicator %>% + filter(typology == "nuts_level_2") %>% + filter(!is.na(typology_change)) %>% + filter( + # Keep only pairs where we actually save + # non-missing observations + !is.na(values) + ) %>% + distinct(geo, code_2016) %>% + filter( + # We filter out cases of countries who + # joined the NUTS system later + geo != code_2016 + ) +``` + +So, let us do the trick: change the `geo` variable to `code_2016`, which is, +whenever there is an equivalent `geo` code in the `NUTS2016` definition, the +data that you should have. Your original `geo` variable contains codes that were +used, for example, in the `NUTS2010` or `NUTS2013` boundary definitions. + +```{r change-to-nuts2016, eval=TRUE} +recoded_with_map <- map_nuts_2 %>% + left_join( + recoded_indicator %>% + mutate(geo = code_2016), + by = "geo" + ) +``` + +Let us make our work visible by creating three observation `type` variables: + +- `missing` which is not present in the dataset; +- `before` which were correctly coded before our recoding; +- `after` which became visible after recoding. + +```{r} +regional_rd_personnel_recoded <- recoded_indicator %>% + mutate(geo = code_2016) %>% + rename(values_2016 = values) %>% + select(-typology, -typology_change, -code_2016) %>% + full_join( + regional_rd_personnel, + by = c("prof_pos", "sex", "sectperf", "unit", "geo", "time") + ) %>% + mutate(type = case_when( + is.na(values_2016) & is.na(values) ~ "missing", + is.na(values) ~ "after", + TRUE ~ "before" + )) +``` + +And let's place it now on the map: + +```{r, choro2} +map_nuts_2 %>% + left_join(regional_rd_personnel_recoded, by = "geo") %>% + # remove completely missing cases + filter(!is.na(time)) %>% + ggplot() + + geom_sf(aes(fill = type), + color = "dim grey", linewidth = .1 + ) + + scale_fill_manual(values = c("#FAE000", "#007CBB", "grey70")) + + guides(fill = guide_legend(reverse = T, title = NULL)) + + facet_wrap(facets = "time") + + labs( + title = "R&D Personnel & Researchers", + subtitle = "In all sectors, both sexes by NUTS 2 regions", + caption = "\ua9 EuroGeographics for the administrative boundaries + \ua9 Daniel Antal, rOpenGov", + fill = NULL + ) + + theme_light() + + theme(legend.position = c(.93, .7)) + + coord_sf( + xlim = c(2377294, 7453440), + ylim = c(1313597, 5628510), + crs = 3035 + ) +``` + +## Conclusion + +We did improve our dataset, and this improvement would not have worked with +traditional imputation techniques very well. For example, replacing the missing +French data with the median value of Europe would have created a huge bias in +our dataset. + +This example is a simplification. There are many territorial typologies in use +in Europe and globally, but the main takeaway is clear: sub-national boundaries +are changing very fast, and you must make sure that you join datasets, or data +with a map with the same boundary definitions. + +# Citations and related work + +### Citing the data sources + +Eurostat data: cite [Eurostat](https://ec.europa.eu/eurostat/). + +Administrative boundaries: cite +[EuroGeographics](https://ec.europa.eu/eurostat/web/gisco/geodata/reference-data/administrative-units-statistical-units). + +### Citing the eurostat R package + +For main developers and contributors, see the [package +homepage](https://ropengov.github.io/eurostat). + +This work can be freely used, modified and distributed under the BSD-2-clause +(modified FreeBSD) license: + +```{r citation-eurostat, message=FALSE} +citation("eurostat") +``` + +### Citing the regions R package + +For main developer and contributors, see the +[package](https://regions.dataobservatory.eu/). + +This work can be freely used, modified and distributed under the GPL-3 license: + +```{r citation-regions, message=FALSE} +citation("regions") +``` + +### Contact + +For contact information, see the [package +homepage](https://ropengov.github.io/eurostat). + +# Version info + +This tutorial was created with + +```{r sessioninfo, message=FALSE} +sessioninfo::session_info() +``` diff --git a/vignettes/articles/maps.Rmd b/vignettes/articles/maps.Rmd new file mode 100644 index 00000000..11d6d80f --- /dev/null +++ b/vignettes/articles/maps.Rmd @@ -0,0 +1,222 @@ +--- +title: "Map examples for the eurostat R package" +date: "`r Sys.Date()`" +output: + html_document: + toc: yes +editor_options: + markdown: + wrap: 80 + canonical: true +--- + +```{r, include = FALSE} +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>", + tidy = "styler", + dev = "ragg_png", + warning = FALSE, + dpi = 300, + out.width = "100%" +) +``` + +```{r setup} +library(eurostat) +``` + +# R Tools for Eurostat Open Data: maps + +This [rOpenGov](http://ropengov.github.io) R package provides tools to access +[Eurostat database](http://ec.europa.eu/eurostat/data/database), which you can +also browse on-line for the data sets and documentation. For contact information +and source code, see the [package website](http://ropengov.github.io/eurostat/). + +See the vignette of eurostat (`vignette(package = "eurostat")`) for installation +and basic use. + +## Maps + +> NOTE: we recommend to check also the `giscoR` package +> (). This is another API package that +> provides R tools for Eurostat geographic data to support geospatial analysis +> and visualization. + +### Disposable income of private households by NUTS 2 regions at 1:60mln resolution using tmap + +The mapping examples below use [`tmap`](https://github.com/mtennekes/tmap) +package. + +```{r maps1-1} +library(dplyr) +library(eurostat) +library(sf) +library(tmap) + +# Download attribute data from Eurostat +sp_data <- eurostat::get_eurostat("tgs00026", time_format = "raw") %>% + # subset to have only a single row per geo + filter(TIME_PERIOD == 2016, nchar(geo) == 4) %>% + # categorise + mutate(income = cut_to_classes(values, n = 5)) + +# Download geospatial data from GISCO +geodata <- get_eurostat_geospatial(nuts_level = 2, year = 2016) + +# merge with attribute data with geodata +map_data <- inner_join(geodata, sp_data, by = "geo") +``` + +Construct the map + +```{r map1ex} +# Create and plot the map +map1 <- tm_shape(geodata, + projection = "EPSG:3035", + xlim = c(2400000, 7800000), + ylim = c(1320000, 5650000) +) + + tm_fill("lightgrey") + + tm_shape(map_data) + + tm_polygons("income", + title = "Disposable household\nincomes in 2016", + palette = "Oranges" + ) + +print(map1) +``` + +Interactive maps can be generated as well + +```{r maps1-inter, out.height="420px"} +# Interactive +tmap_mode("view") +map1 +``` + +```{r maps1-2} +# Set the mode back to normal plotting +tmap_mode("plot") +print(map1) +``` + +### Disposable income of private households by NUTS 2 regions in Poland with labels at 1:1mln resolution using tmap + +```{r maps2} +library(eurostat) +library(dplyr) +library(sf) + +# Downloading and manipulating the tabular data +print("Let us focus on year 2016 and NUTS-3 level") +euro_sf2 <- get_eurostat("tgs00026", + time_format = "raw", + filter = list(time = "2016") +) %>% + # Subset to NUTS-3 level + dplyr::filter(grepl("PL", geo)) %>% + # label the single geo column + mutate( + label = paste0(label_eurostat(.)[["geo"]], "\n", values, "€"), + income = cut_to_classes(values) + ) + +print("Download geospatial data from GISCO") +geodata <- get_eurostat_geospatial( + resolution = "01", nuts_level = 2, + year = 2016, country = "PL" +) + +# Merge with attribute data with geodata +map_data <- inner_join(geodata, euro_sf2, by = "geo") + +# plot map +library(tmap) + +map2 <- tm_shape(geodata) + + tm_fill("lightgrey") + + tm_shape(map_data, is.master = TRUE) + + tm_polygons("income", + title = "Disposable household incomes in 2014", + palette = "Oranges", border.col = "white" + ) + + tm_text("NUTS_NAME", just = "center") + + tm_scale_bar() + + tm_layout(legend.outside = TRUE) +map2 +``` + +### Disposable income of private households by NUTS 2 regions at 1:10mln resolution using ggplot2 + +```{r maps4} +# Disposable income of private households by NUTS 2 regions at 1:1mln res +library(eurostat) +library(dplyr) +library(ggplot2) +data_eurostat <- get_eurostat("tgs00026", time_format = "raw") %>% + filter(TIME_PERIOD == 2018, nchar(geo) == 4) %>% + # classifying the values the variable + dplyr::mutate(cat = cut_to_classes(values)) + +# Download geospatial data from GISCO +data_geo <- get_eurostat_geospatial( + resolution = "01", nuts_level = "2", + year = 2016 +) + +# merge with attribute data with geodata +data <- left_join(data_geo, data_eurostat, by = "geo") + +ggplot(data) + + # Base layer + geom_sf(fill = "lightgrey", color = "lightgrey") + + # Choropleth layer + geom_sf(aes(fill = cat), color = "lightgrey", linewidth = 0.1, na.rm = TRUE) + + scale_fill_brewer(palette = "Oranges", na.translate = FALSE) + + guides(fill = guide_legend(reverse = TRUE, title = "euro")) + + labs( + title = "Disposable household income in 2018", + caption = "© EuroGeographics for the administrative boundaries + Map produced in R with data from Eurostat-package http://ropengov.github.io/eurostat" + ) + + theme_light() + + coord_sf( + xlim = c(2377294, 7453440), + ylim = c(1313597, 5628510), + crs = 3035 + ) +``` + +# Citations and related work + +### Citing the data sources + +Eurostat data: cite [Eurostat](http://ec.europa.eu/eurostat/). + +Administrative boundaries: cite EuroGeographics + +### Citing the eurostat R package + +For main developers and contributors, see the [package +homepage](http://ropengov.github.io/eurostat). + +This work can be freely used, modified and distributed under the BSD-2-clause +(modified FreeBSD) license: + +```{r citation, message=FALSE} +citation("eurostat") +``` + +### Contact + +For contact information, see the [package +homepage](http://ropengov.github.io/eurostat). + +# Version info + +This tutorial was created with + +```{r sessioninfo, message=FALSE} +sessioninfo::session_info() +``` diff --git a/vignettes/articles/publications.Rmd b/vignettes/articles/publications.Rmd new file mode 100644 index 00000000..09686a77 --- /dev/null +++ b/vignettes/articles/publications.Rmd @@ -0,0 +1,35 @@ +--- +title: "Publications using the eurostat R package" +date: "2022-02-07" +--- + +```{r, include = FALSE} +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>" +) +``` + +You can send us a note via the [issue tracker](https://github.com/rOpenGov/eurostat/issues) if you like to add a publication using the eurostat R package on this list: + +- Retrieval and analysis of Eurostat open data with the eurostat package. R Journal 2017. ([manuscript](https://journal.r-project.org/archive/2017/RJ-2017-019/index.html); [source code](https://github.com/rOpenGov/eurostat/tree/master/inst/extras/2017_RJournal_manuscript)). + +External publications using the eurostat package: + +- Jungnickel, T., von Ute, J., Engeli, S. & Albrecht, U-V. (2022). Exploring the weight bias of professionals working in the field of obesity with a mobile IAT: a pilot study. *Therapeutic Advances in Endocrinology and Metabolism*, 13. + +- Balogh, A., Harman, A. & Kreuter, F. (2022). Real-time analysis of predictors of COVID-19 infection spread in the countries of the European Union: User's Manual to the Covid-Predictor-Tracker. URL: + +- Fusco, E., Maggi, B. & Rizzuto, L. (2022). Alternative indicators for the evaluation of renewables in Europe: An efficiency approach. *Renewable Energy*, 190, 48-65. + +- Hashim, D., Carioli, G., Malvezzi, M., Bertuccio, P., Waxman, S., Negri, E., La Vecchia, C., & Boffetta, P. (2020). Cancer mortality in the oldest old: a global overview. *Aging*, 12(17), 16744--16758. + +- Patias, N. (2020). Exploring long-term youth unemployment in Europe using sequence analysis: A reproducible notebook approach. *REGION*, 6(3), 53-69. + +- Belmonte, M., McMahon, S., Scipioni, M. & Tintori, G. (2019). What relationship is there between irregular and regular migration? An exploratory study of EU residence permits, asylum applications, and orders to leave. JRC, Ispra, JRC116674. + +- Galjak, M. (2018). East-West Demographic Divide in the EU: A Regional Overview. Stanovništvo, 56(2), 1-21. + +- Sehor, T. (2018). Terorismus a migrace. Diplomová práce. Brno: Masarykova Univerzita, Ekonomicko-správní fakulta. + +- Kenett, R. S., & Shmueli, G. (2016). Information quality: The potential of data and analytics to generate knowledge. John Wiley & Sons. diff --git a/vignettes/blogposts.Rmd b/vignettes/blogposts.Rmd deleted file mode 100755 index 1cfcb028..00000000 --- a/vignettes/blogposts.Rmd +++ /dev/null @@ -1,19 +0,0 @@ ---- -title: "Blog posts" -date: "`r Sys.Date()`" -output: - rmarkdown::html_vignette: - toc: true -vignette: > - %\VignetteIndexEntry{eurostat blog posts} - %\VignetteEngine{knitr::rmarkdown} - %\VignetteDepends{Cairo} - %\VignetteEncoding{UTF-8} - \usepackage[utf8]{inputenc} ---- - - - * [Package release](https://rpubs.com/muuankarski/27120) - * [Interactive widgets](https://www.mytinyshinys.com/2017/07/11/eurostat/) by Andrew Clark - * [Case studies](http://ropengov.github.io/r/2015/05/01/eurostat-package-examples/) - \ No newline at end of file diff --git a/vignettes/cheatsheet.Rmd b/vignettes/cheatsheet.Rmd deleted file mode 100755 index 477b8b25..00000000 --- a/vignettes/cheatsheet.Rmd +++ /dev/null @@ -1,22 +0,0 @@ ---- -title: "Cheat sheet: eurostat R package" -date: "`r Sys.Date()`" -output: - rmarkdown::html_vignette: - toc: true -vignette: > - %\VignetteIndexEntry{eurostat R package: cheat sheet} - %\VignetteEngine{knitr::rmarkdown} - %\VignetteDepends{Cairo} - %\VignetteEncoding{UTF-8} - \usepackage[utf8]{inputenc} ---- - - * [eurostat R package: cheat sheet (RStudio release version)](https://github.com/rstudio/cheatsheets/raw/master/eurostat.pdf) - - * [eurostat R package: cheat sheet (rOpenGov development version)](https://github.com/rOpenGov/eurostat/blob/master/inst/extras/cheatsheet/eurostat_cheatsheet.pdf) - - - - - diff --git a/vignettes/eurostat_tutorial.Rmd b/vignettes/eurostat_tutorial.Rmd deleted file mode 100755 index 7e05f17c..00000000 --- a/vignettes/eurostat_tutorial.Rmd +++ /dev/null @@ -1,509 +0,0 @@ ---- -title: "Tutorial (vignette) for the eurostat R package" -date: "`r Sys.Date()`" -output: - rmarkdown::html_vignette: - toc: true -vignette: > - %\VignetteIndexEntry{eurostat tutorial} - %\VignetteEngine{knitr::rmarkdown} - %\VignetteDepends{Cairo} - %\VignetteEncoding{UTF-8} - \usepackage[utf8]{inputenc} ---- - -# R Tools for Eurostat Open Data - -This [rOpenGov](http://ropengov.github.io) R package provides tools to access [Eurostat database](http://ec.europa.eu/eurostat/data/database), which you can also browse on-line for the data sets and documentation. For contact information and source code, see the [package website](http://ropengov.github.io/eurostat/). - - -```{r setup, include=FALSE} -# Global options -library(knitr) -opts_chunk$set(fig.path="fig/") -``` - -# Installation - -Release version [(CRAN)](https://cran.r-project.org/web/packages/eurostat/index.html): - -```{r install, eval=FALSE} -install.packages("eurostat") -``` - -Development version [(Github)](https://github.com/rOpenGov/eurostat): - -```{r install2, eval=FALSE} -library(devtools) -install_github("ropengov/eurostat") -``` - -```{r, echo=FALSE} -library(eurostat) -``` - - -Overall, the eurostat package includes the following functions: - -```{r, echo=FALSE,comment=NA} -cat(paste0(library(help = "eurostat")$info[[2]], collapse = "\n")) -``` - - -# Finding data - -Function `get_eurostat_toc()` downloads a table of contents of eurostat datasets. The values in column 'code' should be used to download a selected dataset. - -```{r get_eurostat_toc, warning=FALSE, message=FALSE} -# Load the package -library(eurostat) -library(rvest) - -# Get Eurostat data listing -toc <- get_eurostat_toc() - -# Check the first items -library(knitr) -kable(head(toc)) -``` - -With `search_eurostat()` you can search the table of contents for particular patterns, e.g. all datasets related to *passenger transport*. The kable function to produces nice markdown output. Note that with the `type` argument of this function you could restrict the search to for instance datasets or tables. - -```{r search_eurostat, warning=FALSE, message=FALSE} -# info about passengers -kable(head(search_eurostat("passenger transport"))) -``` - -Codes for the dataset can be searched also from the [Eurostat -database](http://ec.europa.eu/eurostat/data/database). The Eurostat -database gives codes in the Data Navigation Tree after every dataset -in parenthesis. - -# Downloading data - -The package supports two of the Eurostats download methods: the bulk download -facility and the Web Services' JSON API. The bulk download facility is the -fastest method to download whole datasets. It is also often the only way as -the JSON API has limitation of maximum 50 sub-indicators at a time and -whole datasets usually exceeds that. To download only a small section of the -dataset the JSON API is faster, as it allows to make a data selection -before downloading. - -A user does not usually have to bother with methods, as both are used via main -function `get_eurostat()`. If only the table id is given, the whole table is -downloaded from the bulk download facility. If also filters are defined -the JSON API is used. - -Here an example of indicator 'Modal split of passenger transport'. This is the percentage share of each mode of transport in total inland transport, expressed in passenger-kilometres (pkm) based on transport by passenger cars, buses and coaches, and trains. All data should be based on movements on national territory, regardless of the nationality of the vehicle. However, the data collection is not harmonized at the EU level. - -Pick and print the id of the data set to download: -```{r get_id, warning=FALSE, message=FALSE, results='asis'} -# For the original data, see -# http://ec.europa.eu/eurostat/tgm/table.do?tab=table&init=1&plugin=1&language=en&pcode=tsdtr210 -id <- search_eurostat("Modal split of passenger transport", - type = "table")$code[1] -print(id) -``` - -Get the whole corresponding table. As the table is annual data, it is more -convient to use a numeric time variable than use the default date format: - -```{r get_eurostat, warning=FALSE, message=FALSE, results='asis'} -dat <- get_eurostat(id, time_format = "num") -``` - -Investigate the structure of the downloaded data set: -```{r str_dat, warning=FALSE, message=FALSE} -str(dat) -``` - -```{r head_dat, warning=FALSE, message=FALSE, results='asis'} -kable(head(dat)) -``` - -Or you can get only a part of the dataset by defining `filters` argument. It -should be named list, where names corresponds to variable names (lower case) and -values are vectors of codes corresponding desidered series (upper case). For -time variable, in addition to a `time`, also a `sinceTimePeriod` -and a `lastTimePeriod` can be used. - -```{r get_eurostat_json, warning=FALSE, message=FALSE, results='asis', eval=FALSE} -dat2 <- get_eurostat(id, filters = list(geo = c("EU28", "FI"), lastTimePeriod=1), time_format = "num") -kable(dat2) -``` - -## Replacing codes with labels - -By default variables are returned as Eurostat codes, but to get human-readable -labels instead, use a `type = "label"` argument. - -```{r json_labels, warning=FALSE, message=FALSE, results='asis', eval=FALSE} -datl2 <- get_eurostat(id, filters = list(geo = c("EU28", "FI"), - lastTimePeriod = 1), - type = "label", time_format = "num") -kable(head(datl2)) -``` - -Eurostat codes in the downloaded data set can be replaced with -human-readable labels from the Eurostat dictionaries with the -`label_eurostat()` function. - -```{r labels, warning=FALSE, message=FALSE, results='asis'} -datl <- label_eurostat(dat) -kable(head(datl)) -``` - -The `label_eurostat()` allows conversion of individual variable -vectors or variable names as well. - -```{r name_labels, eval = FALSE} -label_eurostat_vars(names(datl)) -``` - - -Vehicle information has 3 levels. You can check them now with: - -```{r vehicle_levels, eval = FALSE} -levels(datl$vehicle) -``` - - - -# Selecting and modifying data - -## EFTA, Eurozone, EU and EU candidate countries - -To facilitate smooth visualization of standard European geographic areas, the package provides ready-made lists of the country codes used in the eurostat database for EFTA (efta\_countries), Euro area (ea\_countries), EU (eu\_countries) and EU candidate countries (eu\_candidate\_countries). These can be used to select specific groups of countries for closer investigation. For conversions with other standard country coding systems, see the [countrycode](...) R package. To retrieve the country code list for EFTA, for instance, use: - -```{r, echo=TRUE, eval=TRUE} -data(efta_countries) -kable(efta_countries) -``` - - -## EU data from 2012 in all vehicles: - -```{r eu_12} -dat_eu12 <- subset(datl, geo == "European Union (current composition)" & time == 2012) -kable(dat_eu12, row.names = FALSE) -``` - -## EU data from 2000 - 2012 with vehicle types as variables: - -Reshaping the data is best done with `spread()` in `tidyr`. -```{r eu_vehicles_table} -library("tidyr") -dat_eu_0012 <- subset(dat, geo == "EU28" & time %in% 2000:2012) -dat_eu_0012_wide <- spread(dat_eu_0012, vehicle, values) -kable(subset(dat_eu_0012_wide, select = -geo), row.names = FALSE) -``` - -## Train passengers for selected EU countries in 2000 - 2012 - -```{r trains_table} -dat_trains <- subset(datl, geo %in% c("Austria", "Belgium", "Finland", "Sweden") - & time %in% 2000:2012 - & vehicle == "Trains") - -dat_trains_wide <- spread(dat_trains, geo, values) -kable(subset(dat_trains_wide, select = -vehicle), row.names = FALSE) -``` - - - -# Visualization - -Visualizing train passenger data with `ggplot2`: - -```{r trains_plot, fig.width=6, fig.height=3} -library(ggplot2) -p <- ggplot(dat_trains, aes(x = time, y = values, colour = geo)) -p <- p + geom_line() -print(p) -``` - -**Triangle plot** - -Triangle plot is handy for visualizing data sets with three variables. - -```{r plotGallery, warning=FALSE, message=FALSE, fig.width=6, fig.height=6} -library(tidyr) -library(plotrix) -library(eurostat) -library(dplyr) -library(tidyr) - -# All sources of renewable energy are to be grouped into three sets - dict <- c("Solid biofuels (excluding charcoal)" = "Biofuels", - "Biogasoline" = "Biofuels", - "Other liquid biofuels" = "Biofuels", - "Biodiesels" = "Biofuels", - "Biogas" = "Biofuels", - "Hydro power" = "Hydro power", - "Tide, Wave and Ocean" = "Hydro power", - "Solar thermal" = "Wind, solar, waste and Other", - "Geothermal Energy" = "Wind, solar, waste and Other", - "Solar photovoltaic" = "Wind, solar, waste and Other", - "Municipal waste (renewable)" = "Wind, solar, waste and Other", - "Wind power" = "Wind, solar, waste and Other", - "Bio jet kerosene" = "Wind, solar, waste and Other") -# Some cleaning of the data is required - energy3 <- get_eurostat("ten00081") %>% - label_eurostat(dat) %>% - filter(time == "2013-01-01", - product != "Renewable energies") %>% - mutate(nproduct = dict[as.character(product)], # just three categories - geo = gsub(geo, pattern=" \\(.*", replacement="")) %>% - select(nproduct, geo, values) %>% - group_by(nproduct, geo) %>% - summarise(svalue = sum(values)) %>% - group_by(geo) %>% - mutate(tvalue = sum(svalue), - svalue = svalue/sum(svalue)) %>% - filter(tvalue > 1000) %>% # only large countries - spread(nproduct, svalue) - -# Triangle plot - par(cex=0.75, mar=c(0,0,0,0)) - positions <- plotrix::triax.plot(as.matrix(energy3[, c(3,5,4)]), - show.grid = TRUE, - label.points= FALSE, point.labels = energy3$geo, - col.axis="gray50", col.grid="gray90", - pch = 19, cex.axis=0.8, cex.ticks=0.7, col="grey50") - - # Larger labels - ind <- which(energy3$geo %in% c("Norway", "Iceland","Denmark","Estonia", "Turkey", "Italy", "Finland")) - df <- data.frame(positions$xypos, geo = energy3$geo) - points(df$x[ind], df$y[ind], cex=2, col="red", pch=19) - text(df$x[ind], df$y[ind], df$geo[ind], adj = c(0.5,-1), cex=1.5) -``` - - - -## Maps - -### Disposable income of private households by NUTS 2 regions at 1:60mln resolution using tmap - -The mapping examples below use [`tmap`](https://github.com/mtennekes/tmap) package. - - -```{r maps1-1, eval=TRUE, fig.width=8, fig.height=8} -library(dplyr) -library(eurostat) -library(sf) -library(tmap) - -# Download attribute data from Eurostat -sp_data <- eurostat::get_eurostat("tgs00026", time_format = "raw", stringsAsFactors = FALSE) %>% - # subset to have only a single row per geo - dplyr::filter(time == 2010, nchar(geo) == 4) %>% - # categorise - dplyr::mutate(income = cut_to_classes(values, n = 5)) - -# Download geospatial data from GISCO -geodata <- get_eurostat_geospatial(output_class = "sf", resolution = "60", nuts_level = 2, year = 2013) - -# merge with attribute data with geodata -map_data <- inner_join(geodata, sp_data) -``` - - -Construct the map - -```{r map1ex, eval=TRUE, warning=FALSE} -map1 <- tmap::tm_shape(geodata) + - tmap::tm_fill("lightgrey") + - tmap::tm_shape(map_data) + - tmap::tm_grid() + - tmap::tm_polygons("income", title = "Disposable household\nincomes in 2010", - palette = "Oranges") -print(map1) -``` - -Interactive maps can be generated as well - -```{r maps1-2, eval=FALSE, fig.width=8, fig.height=8} -# Interactive -tmap_mode("view") -map1 - -# Set the mode back to normal plotting -tmap_mode("plot") -print(map1) -``` - -### Disposable income of private households by NUTS 2 regions in Poland with labels at 1:1mln resolution using tmap - -```{r maps2, fig.width=8, fig.height=8, warning=FALSE} -library(eurostat) -library(dplyr) -library(sf) -library(RColorBrewer) - -# Downloading and manipulating the tabular data -print("Let us focus on year 2014 and NUTS-3 level") -euro_sf2 <- get_eurostat("tgs00026", time_format = "raw", - stringsAsFactors = FALSE, - filter = list(time = "2014")) %>% - - # Subset to NUTS-3 level - dplyr::filter(grepl("PL",geo)) %>% - # label the single geo column - mutate(label = paste0(label_eurostat(.)[["geo"]], "\n", values, "€"), - income = cut_to_classes(values)) - -print("Download geospatial data from GISCO") -geodata <- get_eurostat_geospatial(output_class = "sf", resolution = "60", nuts_level = 2, year = 2013) - -# Merge with attribute data with geodata -map_data <- inner_join(geodata, euro_sf2) - -# plot map -map2 <- tm_shape(geodata) + - tm_fill("lightgrey") + - tm_shape(map_data, is.master = TRUE) + - tm_polygons("income", title = "Disposable household incomes in 2014", - palette = "Oranges", border.col = "white") + - tm_text("NUTS_NAME", just = "center") + - tm_scale_bar() -map2 -``` - -### Disposable income of private households by NUTS 2 regions at 1:10mln resolution using spplot - -```{r maps3, fig.width=8, fig.height=8, dev='CairoPNG'} -library(sp) -library(eurostat) -library(dplyr) -library(RColorBrewer) -dat <- get_eurostat("tgs00026", time_format = "raw", stringsAsFactors = FALSE) %>% - # subsetting to year 2014 and NUTS-2 level - dplyr::filter(time == 2014, nchar(geo) == 4) %>% - # classifying the values the variable - dplyr::mutate(cat = cut_to_classes(values)) - -# Download geospatial data from GISCO -geodata <- get_eurostat_geospatial(output_class = "spdf", resolution = "10", nuts_level = 2, year = 2013) - -# merge with attribute data with geodata -geodata@data <- left_join(geodata@data, dat) - -# plot map -sp::spplot(obj = geodata, "cat", main = "Disposable household income", - xlim = c(-22,34), ylim = c(35,70), - col.regions = c("dim grey", brewer.pal(n = 5, name = "Oranges")), - col = "white", usePolypath = FALSE) -``` - -### Disposable income of private households by NUTS 2 regions at 1:60mln resolution using ggplot2 - -Meanwhile the CRAN version of `ggplot2` is lacking support for simple features, you can plot maps with `ggplot2` by downloading geospatial data as `data.frame` with `output_class` argument set as `df`. - -```{r maps4, fig.width=8, fig.height=8, dev='CairoPNG'} -library(eurostat) -library(dplyr) -library(ggplot2) -dat <- get_eurostat("tgs00026", time_format = "raw", stringsAsFactors = FALSE) %>% - # subsetting to year 2014 and NUTS-2 level - dplyr::filter(time == 2014, nchar(geo) == 4) %>% - # classifying the values the variable - dplyr::mutate(cat = cut_to_classes(values)) - -# Download geospatial data from GISCO -geodata <- get_eurostat_geospatial(resolution = "60", nuts_level = "2", year = 2013) - -# merge with attribute data with geodata -map_data <- inner_join(geodata, dat) - -ggplot(data=map_data) + geom_sf(aes(fill=cat),color="dim grey", size=.1) + - scale_fill_brewer(palette = "Oranges") + - guides(fill = guide_legend(reverse=T, title = "euro")) + - labs(title="Disposable household income in 2014", - caption="(C) EuroGeographics for the administrative boundaries - Map produced in R with a help from Eurostat-package ") + - theme_light() + theme(legend.position=c(.8,.8)) + - coord_sf(xlim=c(-12,44), ylim=c(35,70)) - -``` - - -## SDMX - -Eurostat data is available also in the SDMX format. The eurostat R package does not provide custom tools for this but the generic [rsdmx](https://cran.r-project.org/web/packages/rsdmx/index.html) and [rjsdmx](https://github.com/amattioc/SDMX/wiki) R packages can be used to access data in that format when necessary: - -```{r rsdmx, fig.width=8, fig.height=8, dev='CairoPNG'} -library(rsdmx) - -# Data set URL -url <- "http://ec.europa.eu/eurostat/SDMX/diss-web/rest/data/cdh_e_fos/..PC.FOS1.BE/?startperiod=2005&endPeriod=2011" - -# Read the data from eurostat -d <- readSDMX(url) - -# Convert to data frame and show the first entries -df <- as.data.frame(d) - -kable(head(df)) -``` - - - - -# Further examples - -For further examples, see the [package homepage](http://ropengov.github.io/eurostat/articles/index.html). - - -# Citations and related work - -### Citing the data sources - -Eurostat data: cite [Eurostat](http://ec.europa.eu/eurostat/). - -Administrative boundaries: cite EuroGeographics - - -### Citing the eurostat R package - -For main developers and contributors, see the [package homepage](http://ropengov.github.io/eurostat). - -This work can be freely used, modified and distributed under the -BSD-2-clause (modified FreeBSD) license: - -```{r citation, message=FALSE, eval=TRUE, echo=TRUE} -citation("eurostat") -``` - -### Related work - -This [rOpenGov](http://ropengov.github.io) R package is based on the -earlier CRAN packages -[statfi](https://cran.r-project.org/package=statfi) and -[smarterpoland](https://cran.r-project.org/package=SmarterPoland). - -The independent [reurostat](https://github.com/Tungurahua/reurostat) -package develops related Eurostat tools but seems to be in an -experimental stage at the time of writing this tutorial. - -The more generic [quandl](https://cran.r-project.org/package=quandl), -[datamart](https://cran.r-project.org/package=datamart), -[rsdmx](https://cran.r-project.org/package=rsdmx), and -[pdfetch](https://cran.r-project.org/package=pdfetch) packages may -provide access to some versions of eurostat data but these packages -are more generic and hence, in contrast to the eurostat R package, -lack tools that are specifically customized to facilitate eurostat -analysis. - - -### Contact - -For contact information, see the [package homepage](http://ropengov.github.io/eurostat). - - -# Version info - -This tutorial was created with - -```{r sessioninfo, message=FALSE, warning=FALSE} -sessionInfo() -``` diff --git a/vignettes/eurostat_tutorial.md b/vignettes/eurostat_tutorial.md deleted file mode 100755 index dfa93298..00000000 --- a/vignettes/eurostat_tutorial.md +++ /dev/null @@ -1,1371 +0,0 @@ -R Tools for Eurostat Open Data -============================== - -This [rOpenGov](http://ropengov.github.io) R package provides tools to -access [Eurostat database](http://ec.europa.eu/eurostat/data/database), -which you can also browse on-line for the data sets and documentation. -For contact information and source code, see the [package -website](http://ropengov.github.io/eurostat/). - -Installation -============ - -Release version -[(CRAN)](https://cran.r-project.org/web/packages/eurostat/index.html): - - install.packages("eurostat") - -Development version [(Github)](https://github.com/rOpenGov/eurostat): - - library(devtools) - install_github("ropengov/eurostat") - -Overall, the eurostat package includes the following functions: - -Finding data -============ - -Function `get_eurostat_toc()` downloads a table of contents of eurostat -datasets. The values in column 'code' should be used to download a -selected dataset. - - # Load the package - library(eurostat) - library(rvest) - - # Get Eurostat data listing - toc <- get_eurostat_toc() - - # Check the first items - library(knitr) - kable(head(toc)) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    titlecodetypelast update of datalast table structure changedata startdata endvalues
    Database by themesdatafolderNANANANANA
    General and regional statisticsgeneralfolderNANANANANA
    European and national indicators for short-term analysiseuroindfolderNANANANANA
    Business and consumer surveys (source: DG ECFIN)ei_bcsfolderNANANANANA
    Consumer surveys (source: DG ECFIN)ei_bcs_csfolderNANANANANA
    Consumers - monthly dataei_bsco_mdataset27.09.201827.09.20181980M012018M09NA
    - -With `search_eurostat()` you can search the table of contents for -particular patterns, e.g. all datasets related to *passenger transport*. -The kable function to produces nice markdown output. Note that with the -`type` argument of this function you could restrict the search to for -instance datasets or tables. - - # info about passengers - kable(head(search_eurostat("passenger transport"))) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    titlecodetypelast update of datalast table structure changedata startdata endvalues
    Volume of passenger transport relative to GDPtran_hv_pstradataset30.07.201830.07.201820002016NA
    Modal split of passenger transporttran_hv_psmoddataset27.08.201827.08.201819902016NA
    Railway transport - total annual passenger transport (1 000 pass., million pkm)rail_pa_totaldataset20.09.201807.09.201820042016NA
    Railway transport - passenger transport by type of transport (detailed reporting only) (1 000 pass.)rail_pa_typepasdataset20.09.201831.08.201720042016NA
    Railway transport - passenger transport by type of transport (detailed reporting only) (million pkm)rail_pa_typepkmdataset20.09.201831.08.201720042016NA
    International railway passenger transport from the reporting country to the country of disembarkation (1 000 passengers)rail_pa_intgongdataset20.09.201817.07.201820042017NA
    - -Codes for the dataset can be searched also from the [Eurostat -database](http://ec.europa.eu/eurostat/data/database). The Eurostat -database gives codes in the Data Navigation Tree after every dataset in -parenthesis. - -Downloading data -================ - -The package supports two of the Eurostats download methods: the bulk -download facility and the Web Services' JSON API. The bulk download -facility is the fastest method to download whole datasets. It is also -often the only way as the JSON API has limitation of maximum 50 -sub-indicators at a time and whole datasets usually exceeds that. To -download only a small section of the dataset the JSON API is faster, as -it allows to make a data selection before downloading. - -A user does not usually have to bother with methods, as both are used -via main function `get_eurostat()`. If only the table id is given, the -whole table is downloaded from the bulk download facility. If also -filters are defined the JSON API is used. - -Here an example of indicator 'Modal split of passenger transport'. This -is the percentage share of each mode of transport in total inland -transport, expressed in passenger-kilometres (pkm) based on transport by -passenger cars, buses and coaches, and trains. All data should be based -on movements on national territory, regardless of the nationality of the -vehicle. However, the data collection is not harmonized at the EU level. - -Pick and print the id of the data set to download: - - # For the original data, see - # http://ec.europa.eu/eurostat/tgm/table.do?tab=table&init=1&plugin=1&language=en&pcode=tsdtr210 - id <- search_eurostat("Modal split of passenger transport", - type = "table")$code[1] - print(id) - -\[1\] "t2020\_rk310" - -Get the whole corresponding table. As the table is annual data, it is -more convient to use a numeric time variable than use the default date -format: - - dat <- get_eurostat(id, time_format = "num") - -Investigate the structure of the downloaded data set: - - str(dat) - - ## Classes 'tbl_df', 'tbl' and 'data.frame': 2536 obs. of 5 variables: - ## $ unit : Factor w/ 1 level "PC": 1 1 1 1 1 1 1 1 1 1 ... - ## $ vehicle: Factor w/ 3 levels "BUS_TOT","CAR",..: 1 1 1 1 1 1 1 1 1 1 ... - ## $ geo : Factor w/ 35 levels "AT","BE","CH",..: 1 2 3 4 5 6 7 8 9 10 ... - ## $ time : num 1990 1990 1990 1990 1990 1990 1990 1990 1990 1990 ... - ## $ values : num 11 10.6 3.7 9.1 11.3 32.4 14.9 13.5 6 24.8 ... - - kable(head(dat)) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    unitvehiclegeotimevalues
    PCBUS_TOTAT199011.0
    PCBUS_TOTBE199010.6
    PCBUS_TOTCH19903.7
    PCBUS_TOTDE19909.1
    PCBUS_TOTDK199011.3
    PCBUS_TOTEL199032.4
    - -Or you can get only a part of the dataset by defining `filters` -argument. It should be named list, where names corresponds to variable -names (lower case) and values are vectors of codes corresponding -desidered series (upper case). For time variable, in addition to a -`time`, also a `sinceTimePeriod` and a `lastTimePeriod` can be used. - - dat2 <- get_eurostat(id, filters = list(geo = c("EU28", "FI"), lastTimePeriod=1), time_format = "num") - kable(dat2) - -Replacing codes with labels ---------------------------- - -By default variables are returned as Eurostat codes, but to get -human-readable labels instead, use a `type = "label"` argument. - - datl2 <- get_eurostat(id, filters = list(geo = c("EU28", "FI"), - lastTimePeriod = 1), - type = "label", time_format = "num") - kable(head(datl2)) - -Eurostat codes in the downloaded data set can be replaced with -human-readable labels from the Eurostat dictionaries with the -`label_eurostat()` function. - - datl <- label_eurostat(dat) - kable(head(datl)) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    unitvehiclegeotimevalues
    PercentageMotor coaches, buses and trolley busesAustria199011.0
    PercentageMotor coaches, buses and trolley busesBelgium199010.6
    PercentageMotor coaches, buses and trolley busesSwitzerland19903.7
    PercentageMotor coaches, buses and trolley busesGermany (until 1990 former territory of the FRG)19909.1
    PercentageMotor coaches, buses and trolley busesDenmark199011.3
    PercentageMotor coaches, buses and trolley busesGreece199032.4
    - -The `label_eurostat()` allows conversion of individual variable vectors -or variable names as well. - - label_eurostat_vars(names(datl)) - -Vehicle information has 3 levels. You can check them now with: - - levels(datl$vehicle) - -Selecting and modifying data -============================ - -EFTA, Eurozone, EU and EU candidate countries ---------------------------------------------- - -To facilitate smooth visualization of standard European geographic -areas, the package provides ready-made lists of the country codes used -in the eurostat database for EFTA (efta\_countries), Euro area -(ea\_countries), EU (eu\_countries) and EU candidate countries -(eu\_candidate\_countries). These can be used to select specific groups -of countries for closer investigation. For conversions with other -standard country coding systems, see the [countrycode](...) R package. -To retrieve the country code list for EFTA, for instance, use: - - data(efta_countries) - kable(efta_countries) - - - - - - - - - - - - - - - - - - - - - - - - - - -
    codename
    ISIceland
    LILiechtenstein
    NONorway
    CHSwitzerland
    - -EU data from 2012 in all vehicles: ----------------------------------- - - dat_eu12 <- subset(datl, geo == "European Union (current composition)" & time == 2012) - kable(dat_eu12, row.names = FALSE) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    unitvehiclegeotimevalues
    PercentageMotor coaches, buses and trolley busesEuropean Union (current composition)20129.5
    PercentagePassenger carsEuropean Union (current composition)201282.9
    PercentageTrainsEuropean Union (current composition)20127.7
    - -EU data from 2000 - 2012 with vehicle types as variables: ---------------------------------------------------------- - -Reshaping the data is best done with `spread()` in `tidyr`. - - library("tidyr") - dat_eu_0012 <- subset(dat, geo == "EU28" & time %in% 2000:2012) - dat_eu_0012_wide <- spread(dat_eu_0012, vehicle, values) - kable(subset(dat_eu_0012_wide, select = -geo), row.names = FALSE) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    unittimeBUS_TOTCARTRN
    PC200010.482.47.2
    PC200110.282.77.1
    PC20029.983.36.8
    PC20039.983.56.7
    PC20049.883.46.8
    PC20059.883.36.9
    PC20069.783.27.1
    PC20079.883.17.1
    PC20089.982.87.4
    PC20099.383.67.1
    PC20109.483.47.2
    PC20119.483.27.4
    PC20129.582.97.7
    - -Train passengers for selected EU countries in 2000 - 2012 ---------------------------------------------------------- - - dat_trains <- subset(datl, geo %in% c("Austria", "Belgium", "Finland", "Sweden") - & time %in% 2000:2012 - & vehicle == "Trains") - - dat_trains_wide <- spread(dat_trains, geo, values) - kable(subset(dat_trains_wide, select = -vehicle), row.names = FALSE) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    unittimeAustriaBelgiumFinlandSweden
    Percentage20009.76.35.16.8
    Percentage20019.76.44.87.1
    Percentage20029.76.54.87.1
    Percentage20039.56.54.77.0
    Percentage20049.47.14.76.8
    Percentage20059.86.64.87.1
    Percentage200610.06.94.87.6
    Percentage200710.07.15.07.9
    Percentage200811.17.55.48.6
    Percentage200911.17.55.18.7
    Percentage201011.07.75.28.7
    Percentage201111.37.75.08.7
    Percentage201211.87.85.39.1
    - -Visualization -============= - -Visualizing train passenger data with `ggplot2`: - - library(ggplot2) - p <- ggplot(dat_trains, aes(x = time, y = values, colour = geo)) - p <- p + geom_line() - print(p) - -![](fig/trains_plot-1.png) - -**Triangle plot** - -Triangle plot is handy for visualizing data sets with three variables. - - library(tidyr) - library(plotrix) - library(eurostat) - library(dplyr) - library(tidyr) - - # All sources of renewable energy are to be grouped into three sets - dict <- c("Solid biofuels (excluding charcoal)" = "Biofuels", - "Biogasoline" = "Biofuels", - "Other liquid biofuels" = "Biofuels", - "Biodiesels" = "Biofuels", - "Biogas" = "Biofuels", - "Hydro power" = "Hydro power", - "Tide, Wave and Ocean" = "Hydro power", - "Solar thermal" = "Wind, solar, waste and Other", - "Geothermal Energy" = "Wind, solar, waste and Other", - "Solar photovoltaic" = "Wind, solar, waste and Other", - "Municipal waste (renewable)" = "Wind, solar, waste and Other", - "Wind power" = "Wind, solar, waste and Other", - "Bio jet kerosene" = "Wind, solar, waste and Other") - # Some cleaning of the data is required - energy3 <- get_eurostat("ten00081") %>% - label_eurostat(dat) %>% - filter(time == "2013-01-01", - product != "Renewable energies") %>% - mutate(nproduct = dict[as.character(product)], # just three categories - geo = gsub(geo, pattern=" \\(.*", replacement="")) %>% - select(nproduct, geo, values) %>% - group_by(nproduct, geo) %>% - summarise(svalue = sum(values)) %>% - group_by(geo) %>% - mutate(tvalue = sum(svalue), - svalue = svalue/sum(svalue)) %>% - filter(tvalue > 1000) %>% # only large countries - spread(nproduct, svalue) - - # Triangle plot - par(cex=0.75, mar=c(0,0,0,0)) - positions <- plotrix::triax.plot(as.matrix(energy3[, c(3,5,4)]), - show.grid = TRUE, - label.points= FALSE, point.labels = energy3$geo, - col.axis="gray50", col.grid="gray90", - pch = 19, cex.axis=0.8, cex.ticks=0.7, col="grey50") - - # Larger labels - ind <- which(energy3$geo %in% c("Norway", "Iceland","Denmark","Estonia", "Turkey", "Italy", "Finland")) - df <- data.frame(positions$xypos, geo = energy3$geo) - points(df$x[ind], df$y[ind], cex=2, col="red", pch=19) - text(df$x[ind], df$y[ind], df$geo[ind], adj = c(0.5,-1), cex=1.5) - -![](fig/plotGallery-1.png) - -Maps ----- - -### Disposable income of private households by NUTS 2 regions at 1:60mln resolution using tmap - -The mapping examples below use -[`tmap`](https://github.com/mtennekes/tmap) package. - - library(dplyr) - library(eurostat) - library(sf) - - ## Linking to GEOS 3.6.2, GDAL 2.2.3, proj.4 4.9.3 - - library(tmap) - - # Download attribute data from Eurostat - sp_data <- eurostat::get_eurostat("tgs00026", time_format = "raw", stringsAsFactors = FALSE) %>% - # subset to have only a single row per geo - dplyr::filter(time == 2010, nchar(geo) == 4) %>% - # categorise - dplyr::mutate(income = cut_to_classes(values, n = 5)) - - ## Table tgs00026 cached at /tmp/Rtmp4PAyLJ/eurostat/tgs00026_raw_code_FF.rds - - # Download geospatial data from GISCO - geodata <- get_eurostat_geospatial(output_class = "sf", resolution = "60", nuts_level = 2, year = 2013) - - ## - ## COPYRIGHT NOTICE - ## - ## When data downloaded from this page - ## - ## is used in any printed or electronic publication, - ## in addition to any other provisions - ## applicable to the whole Eurostat website, - ## data source will have to be acknowledged - ## in the legend of the map and - ## in the introductory page of the publication - ## with the following copyright notice: - ## - ## - EN: (C) EuroGeographics for the administrative boundaries - ## - FR: (C) EuroGeographics pour les limites administratives - ## - DE: (C) EuroGeographics bezuglich der Verwaltungsgrenzen - ## - ## For publications in languages other than - ## English, French or German, - ## the translation of the copyright notice - ## in the language of the publication shall be used. - ## - ## If you intend to use the data commercially, - ## please contact EuroGeographics for - ## information regarding their licence agreements. - ## - - ## No encoding supplied: defaulting to UTF-8. - - ## - ## # -------------------------- - ## HEADS UP!! - ## - ## Function now returns the data in 'sf'-class (simple features) - ## by default which is different - ## from previous behaviour's 'SpatialPolygonDataFrame'. - ## - ## If you prefer either 'SpatialPolygonDataFrame' or - ## fortified 'data_frame' (for ggplot2::geom_polygon), - ## please specify it explicitly to 'output_class'-argument! - ## - ## # -------------------------- - ## - - # merge with attribute data with geodata - map_data <- inner_join(geodata, sp_data) - - ## Joining, by = "geo" - -Construct the map - - map1 <- tmap::tm_shape(geodata) + - tmap::tm_fill("lightgrey") + - tmap::tm_shape(map_data) + - tmap::tm_grid() + - tmap::tm_polygons("income", title = "Disposable household\nincomes in 2010", - palette = "Oranges") - print(map1) - -![](fig/map1ex-1.png) - -Interactive maps can be generated as well - - # Interactive - tmap_mode("view") - map1 - - # Set the mode back to normal plotting - tmap_mode("plot") - print(map1) - -### Disposable income of private households by NUTS 2 regions in Poland with labels at 1:1mln resolution using tmap - - library(eurostat) - library(dplyr) - library(sf) - library(RColorBrewer) - - # Downloading and manipulating the tabular data - print("Let us focus on year 2014 and NUTS-3 level") - - ## [1] "Let us focus on year 2014 and NUTS-3 level" - - euro_sf2 <- get_eurostat("tgs00026", time_format = "raw", - stringsAsFactors = FALSE, - filter = list(time = "2014")) %>% - - # Subset to NUTS-3 level - dplyr::filter(grepl("PL",geo)) %>% - # label the single geo column - mutate(label = paste0(label_eurostat(.)[["geo"]], "\n", values, "€"), - income = cut_to_classes(values)) - - print("Download geospatial data from GISCO") - - ## [1] "Download geospatial data from GISCO" - - geodata <- get_eurostat_geospatial(output_class = "sf", resolution = "60", nuts_level = 2, year = 2013) - - ## - ## COPYRIGHT NOTICE - ## - ## When data downloaded from this page - ## - ## is used in any printed or electronic publication, - ## in addition to any other provisions - ## applicable to the whole Eurostat website, - ## data source will have to be acknowledged - ## in the legend of the map and - ## in the introductory page of the publication - ## with the following copyright notice: - ## - ## - EN: (C) EuroGeographics for the administrative boundaries - ## - FR: (C) EuroGeographics pour les limites administratives - ## - DE: (C) EuroGeographics bezuglich der Verwaltungsgrenzen - ## - ## For publications in languages other than - ## English, French or German, - ## the translation of the copyright notice - ## in the language of the publication shall be used. - ## - ## If you intend to use the data commercially, - ## please contact EuroGeographics for - ## information regarding their licence agreements. - ## - - ## No encoding supplied: defaulting to UTF-8. - - ## - ## # -------------------------- - ## HEADS UP!! - ## - ## Function now returns the data in 'sf'-class (simple features) - ## by default which is different - ## from previous behaviour's 'SpatialPolygonDataFrame'. - ## - ## If you prefer either 'SpatialPolygonDataFrame' or - ## fortified 'data_frame' (for ggplot2::geom_polygon), - ## please specify it explicitly to 'output_class'-argument! - ## - ## # -------------------------- - ## - - # Merge with attribute data with geodata - map_data <- inner_join(geodata, euro_sf2) - - ## Joining, by = "geo" - - # plot map - map2 <- tm_shape(geodata) + - tm_fill("lightgrey") + - tm_shape(map_data, is.master = TRUE) + - tm_polygons("income", title = "Disposable household incomes in 2014", - palette = "Oranges", border.col = "white") + - tm_text("NUTS_NAME", just = "center") + - tm_scale_bar() - map2 - -![](fig/maps2-1.png) - -### Disposable income of private households by NUTS 2 regions at 1:10mln resolution using spplot - - library(sp) - library(eurostat) - library(dplyr) - library(RColorBrewer) - dat <- get_eurostat("tgs00026", time_format = "raw", stringsAsFactors = FALSE) %>% - # subsetting to year 2014 and NUTS-2 level - dplyr::filter(time == 2014, nchar(geo) == 4) %>% - # classifying the values the variable - dplyr::mutate(cat = cut_to_classes(values)) - - ## Reading cache file /tmp/Rtmp4PAyLJ/eurostat/tgs00026_raw_code_FF.rds - - ## Table tgs00026 read from cache file: /tmp/Rtmp4PAyLJ/eurostat/tgs00026_raw_code_FF.rds - - # Download geospatial data from GISCO - geodata <- get_eurostat_geospatial(output_class = "spdf", resolution = "10", nuts_level = 2, year = 2013) - - ## - ## COPYRIGHT NOTICE - ## - ## When data downloaded from this page - ## - ## is used in any printed or electronic publication, - ## in addition to any other provisions - ## applicable to the whole Eurostat website, - ## data source will have to be acknowledged - ## in the legend of the map and - ## in the introductory page of the publication - ## with the following copyright notice: - ## - ## - EN: (C) EuroGeographics for the administrative boundaries - ## - FR: (C) EuroGeographics pour les limites administratives - ## - DE: (C) EuroGeographics bezuglich der Verwaltungsgrenzen - ## - ## For publications in languages other than - ## English, French or German, - ## the translation of the copyright notice - ## in the language of the publication shall be used. - ## - ## If you intend to use the data commercially, - ## please contact EuroGeographics for - ## information regarding their licence agreements. - ## - - ## No encoding supplied: defaulting to UTF-8. - - ## SpatialPolygonDataFrame at resolution 1: 10 cached at: /tmp/Rtmp4PAyLJ/eurostat/spdf1022013.RData - - ## - ## # -------------------------- - ## HEADS UP!! - ## - ## Function now returns the data in 'sf'-class (simple features) - ## by default which is different - ## from previous behaviour's 'SpatialPolygonDataFrame'. - ## - ## If you prefer either 'SpatialPolygonDataFrame' or - ## fortified 'data_frame' (for ggplot2::geom_polygon), - ## please specify it explicitly to 'output_class'-argument! - ## - ## # -------------------------- - ## - - # merge with attribute data with geodata - geodata@data <- left_join(geodata@data, dat) - - ## Joining, by = "geo" - - # plot map - sp::spplot(obj = geodata, "cat", main = "Disposable household income", - xlim = c(-22,34), ylim = c(35,70), - col.regions = c("dim grey", brewer.pal(n = 5, name = "Oranges")), - col = "white", usePolypath = FALSE) - -![](fig/maps3-1.png) - -### Disposable income of private households by NUTS 2 regions at 1:60mln resolution using ggplot2 - -Meanwhile the CRAN version of `ggplot2` is lacking support for simple -features, you can plot maps with `ggplot2` by downloading geospatial -data as `data.frame` with `output_class` argument set as `df`. - - library(eurostat) - library(dplyr) - library(ggplot2) - dat <- get_eurostat("tgs00026", time_format = "raw", stringsAsFactors = FALSE) %>% - # subsetting to year 2014 and NUTS-2 level - dplyr::filter(time == 2014, nchar(geo) == 4) %>% - # classifying the values the variable - dplyr::mutate(cat = cut_to_classes(values)) - - ## Reading cache file /tmp/Rtmp4PAyLJ/eurostat/tgs00026_raw_code_FF.rds - - ## Table tgs00026 read from cache file: /tmp/Rtmp4PAyLJ/eurostat/tgs00026_raw_code_FF.rds - - # Download geospatial data from GISCO - geodata <- get_eurostat_geospatial(resolution = "60", nuts_level = "2", year = 2013) - - ## - ## COPYRIGHT NOTICE - ## - ## When data downloaded from this page - ## - ## is used in any printed or electronic publication, - ## in addition to any other provisions - ## applicable to the whole Eurostat website, - ## data source will have to be acknowledged - ## in the legend of the map and - ## in the introductory page of the publication - ## with the following copyright notice: - ## - ## - EN: (C) EuroGeographics for the administrative boundaries - ## - FR: (C) EuroGeographics pour les limites administratives - ## - DE: (C) EuroGeographics bezuglich der Verwaltungsgrenzen - ## - ## For publications in languages other than - ## English, French or German, - ## the translation of the copyright notice - ## in the language of the publication shall be used. - ## - ## If you intend to use the data commercially, - ## please contact EuroGeographics for - ## information regarding their licence agreements. - ## - - ## No encoding supplied: defaulting to UTF-8. - - ## - ## # -------------------------- - ## HEADS UP!! - ## - ## Function now returns the data in 'sf'-class (simple features) - ## by default which is different - ## from previous behaviour's 'SpatialPolygonDataFrame'. - ## - ## If you prefer either 'SpatialPolygonDataFrame' or - ## fortified 'data_frame' (for ggplot2::geom_polygon), - ## please specify it explicitly to 'output_class'-argument! - ## - ## # -------------------------- - ## - - # merge with attribute data with geodata - map_data <- inner_join(geodata, dat) - - ## Joining, by = "geo" - - ggplot(data=map_data) + geom_sf(aes(fill=cat),color="dim grey", size=.1) + - scale_fill_brewer(palette = "Oranges") + - guides(fill = guide_legend(reverse=T, title = "euro")) + - labs(title="Disposable household income in 2014", - caption="(C) EuroGeographics for the administrative boundaries - Map produced in R with a help from Eurostat-package ") + - theme_light() + theme(legend.position=c(.8,.8)) + - coord_sf(xlim=c(-12,44), ylim=c(35,70)) - -![](fig/maps4-1.png) - -SDMX ----- - -Eurostat data is available also in the SDMX format. The eurostat R -package does not provide custom tools for this but the generic -[rsdmx](https://cran.r-project.org/web/packages/rsdmx/index.html) and -[rjsdmx](https://github.com/amattioc/SDMX/wiki) R packages can be used -to access data in that format when necessary: - - library(rsdmx) - - # Data set URL - url <- "http://ec.europa.eu/eurostat/SDMX/diss-web/rest/data/cdh_e_fos/..PC.FOS1.BE/?startperiod=2005&endPeriod=2011" - - # Read the data from eurostat - d <- readSDMX(url) - - # Convert to data frame and show the first entries - df <- as.data.frame(d) - - kable(head(df)) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    UNITY_GRADFOS07GEOFREQobsTimeobsValueOBS_STATUS
    PCTOTALFOS1BEA2009NAna
    PCTOTALFOS1BEA2006NAna
    PCY_GE1990FOS1BEA200943.75NA
    PCY_GE1990FOS1BEA2006NAna
    - -Further examples -================ - -For further examples, see the [package -homepage](http://ropengov.github.io/eurostat/articles/index.html). - -Citations and related work -========================== - -### Citing the data sources - -Eurostat data: cite [Eurostat](http://ec.europa.eu/eurostat/). - -Administrative boundaries: cite EuroGeographics - -### Citing the eurostat R package - -For main developers and contributors, see the [package -homepage](http://ropengov.github.io/eurostat). - -This work can be freely used, modified and distributed under the -BSD-2-clause (modified FreeBSD) license: - - citation("eurostat") - - ## - ## Kindly cite the eurostat R package as follows: - ## - ## (C) Leo Lahti, Janne Huovari, Markus Kainu, Przemyslaw Biecek. - ## Retrieval and analysis of Eurostat open data with the eurostat - ## package. R Journal 9(1):385-392, 2017. Version 3.2.93 Package - ## URL: http://ropengov.github.io/eurostat Manuscript URL: - ## https://journal.r-project.org/archive/2017/RJ-2017-019/index.html - ## - ## A BibTeX entry for LaTeX users is - ## - ## @Misc{, - ## title = {eurostat R package}, - ## author = {Leo Lahti and Janne Huovari and Markus Kainu and Przemyslaw Biecek}, - ## journal = {R Journal}, - ## volume = {9}, - ## number = {1}, - ## pages = {385-392}, - ## year = {2017}, - ## url = {https://journal.r-project.org/archive/2017/RJ-2017-019/index.html}, - ## note = {Version 3.2.93}, - ## } - -### Related work - -This [rOpenGov](http://ropengov.github.io) R package is based on the -earlier CRAN packages -[statfi](https://cran.r-project.org/package=statfi) and -[smarterpoland](https://cran.r-project.org/package=SmarterPoland). - -The independent [reurostat](https://github.com/Tungurahua/reurostat) -package develops related Eurostat tools but seems to be in an -experimental stage at the time of writing this tutorial. - -The more generic [quandl](https://cran.r-project.org/package=quandl), -[datamart](https://cran.r-project.org/package=datamart), -[rsdmx](https://cran.r-project.org/package=rsdmx), and -[pdfetch](https://cran.r-project.org/package=pdfetch) packages may -provide access to some versions of eurostat data but these packages are -more generic and hence, in contrast to the eurostat R package, lack -tools that are specifically customized to facilitate eurostat analysis. - -### Contact - -For contact information, see the [package -homepage](http://ropengov.github.io/eurostat). - -Version info -============ - -This tutorial was created with - - sessionInfo() - - ## R version 3.5.1 (2018-07-02) - ## Platform: x86_64-pc-linux-gnu (64-bit) - ## Running under: Ubuntu 18.04.1 LTS - ## - ## Matrix products: default - ## BLAS: /home/lei/bin/R-3.5.1/lib/libRblas.so - ## LAPACK: /home/lei/bin/R-3.5.1/lib/libRlapack.so - ## - ## locale: - ## [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C - ## [3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8 - ## [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 - ## [7] LC_PAPER=en_US.UTF-8 LC_NAME=C - ## [9] LC_ADDRESS=C LC_TELEPHONE=C - ## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C - ## - ## attached base packages: - ## [1] stats graphics grDevices utils datasets methods base - ## - ## other attached packages: - ## [1] rsdmx_0.5-13 sp_1.3-1 RColorBrewer_1.1-2 - ## [4] tmap_2.1-1 sf_0.6-3 dplyr_0.7.6 - ## [7] plotrix_3.7-4 ggplot2_3.0.0 tidyr_0.8.1 - ## [10] bindrcpp_0.2.2 rvest_0.3.2 xml2_1.2.0 - ## [13] rmarkdown_1.10 pkgdown_1.1.0.9000 knitr_1.20 - ## [16] eurostat_3.2.93 devtools_1.13.6 - ## - ## loaded via a namespace (and not attached): - ## [1] nlme_3.1-137 bitops_1.0-6 fs_1.2.6 - ## [4] satellite_1.0.1 lubridate_1.7.4 webshot_0.5.1 - ## [7] httr_1.3.1 rprojroot_1.3-2 mapview_2.6.0 - ## [10] tools_3.5.1 backports_1.1.2 rgdal_1.3-4 - ## [13] R6_2.3.0 KernSmooth_2.23-15 spData_0.2.9.4 - ## [16] rgeos_0.3-28 DBI_1.0.0 lazyeval_0.2.1 - ## [19] colorspace_1.3-2 raster_2.6-7 withr_2.1.2 - ## [22] tidyselect_0.2.5 processx_3.2.0 leaflet_2.0.2 - ## [25] curl_3.2 compiler_3.5.1 cli_1.0.1 - ## [28] Cairo_1.5-9 desc_1.2.0 labeling_0.3 - ## [31] scales_1.0.0 classInt_0.2-3 readr_1.1.1 - ## [34] callr_3.0.0 commonmark_1.6 stringr_1.3.1 - ## [37] digest_0.6.18 base64enc_0.1-3 dichromat_2.0-0 - ## [40] pkgconfig_2.0.2 htmltools_0.3.6 highr_0.7 - ## [43] htmlwidgets_1.3 rlang_0.2.2 shiny_1.1.0 - ## [46] bindr_0.1.1 jsonlite_1.5 crosstalk_1.0.0 - ## [49] RCurl_1.95-4.11 magrittr_1.5 Rcpp_0.12.19 - ## [52] munsell_0.5.0 stringi_1.2.4 yaml_2.2.0 - ## [55] MASS_7.3-50 tmaptools_2.0-1 plyr_1.8.4 - ## [58] grid_3.5.1 promises_1.0.1 crayon_1.3.4 - ## [61] lattice_0.20-35 hms_0.4.2 ps_1.1.0 - ## [64] pillar_1.3.0 stats4_3.5.1 XML_3.98-1.16 - ## [67] glue_1.3.0 evaluate_0.12 png_0.1-7 - ## [70] httpuv_1.4.5 testthat_2.0.1 gtable_0.2.0 - ## [73] purrr_0.2.5 assertthat_0.2.0 mime_0.6 - ## [76] lwgeom_0.1-4 xtable_1.8-3 broom_0.5.0 - ## [79] countrycode_1.00.0 e1071_1.7-0 roxygen2_6.1.0 - ## [82] later_0.7.5 class_7.3-14 viridisLite_0.3.0 - ## [85] tibble_1.4.2 memoise_1.1.0 units_0.6-1 diff --git a/vignettes/fig/map1ex-1.png b/vignettes/fig/map1ex-1.png deleted file mode 100755 index 7d2f5801..00000000 Binary files a/vignettes/fig/map1ex-1.png and /dev/null differ diff --git a/vignettes/fig/maps2-1.pdf b/vignettes/fig/maps2-1.pdf deleted file mode 100644 index 475277e1..00000000 Binary files a/vignettes/fig/maps2-1.pdf and /dev/null differ diff --git a/vignettes/fig/maps2-1.png b/vignettes/fig/maps2-1.png deleted file mode 100755 index ad5dc176..00000000 Binary files a/vignettes/fig/maps2-1.png and /dev/null differ diff --git a/vignettes/fig/maps3-1.png b/vignettes/fig/maps3-1.png deleted file mode 100755 index fb5ae00f..00000000 Binary files a/vignettes/fig/maps3-1.png and /dev/null differ diff --git a/vignettes/fig/maps4-1.png b/vignettes/fig/maps4-1.png deleted file mode 100755 index 294f23b5..00000000 Binary files a/vignettes/fig/maps4-1.png and /dev/null differ diff --git a/vignettes/fig/plotGallery-1.pdf b/vignettes/fig/plotGallery-1.pdf deleted file mode 100644 index d9efe655..00000000 Binary files a/vignettes/fig/plotGallery-1.pdf and /dev/null differ diff --git a/vignettes/fig/plotGallery-1.png b/vignettes/fig/plotGallery-1.png deleted file mode 100755 index ccf4dbd6..00000000 Binary files a/vignettes/fig/plotGallery-1.png and /dev/null differ diff --git a/vignettes/fig/trains_plot-1.pdf b/vignettes/fig/trains_plot-1.pdf deleted file mode 100644 index 9e81ac55..00000000 Binary files a/vignettes/fig/trains_plot-1.pdf and /dev/null differ diff --git a/vignettes/fig/trains_plot-1.png b/vignettes/fig/trains_plot-1.png deleted file mode 100755 index e634f9bd..00000000 Binary files a/vignettes/fig/trains_plot-1.png and /dev/null differ diff --git a/vignettes/main.R b/vignettes/main.R deleted file mode 100755 index 17973e1d..00000000 --- a/vignettes/main.R +++ /dev/null @@ -1,13 +0,0 @@ -library(knitr) -library(rmarkdown) -render("eurostat_tutorial.Rmd", output_format = "md_document") -render("eurostat_tutorial.Rmd", output_format = "pdf_document") -render("eurostat_tutorial.Rmd", output_format = "html_document") - -#knit("eurostat_tutorial.Rmd") -#knit("manuscript.Rmd") -#render("manuscript.Rmd", output_format = "html_document") -#render("manuscript.Rmd", output_format = "pdf_document") -#knit2pdf("eurostat.Rnw") -#library(rmarkdown) -#render("eurostat_tutorial.Rmd", output_format = "pdf_document") diff --git a/vignettes/publications.Rmd b/vignettes/publications.Rmd deleted file mode 100755 index 41476ca1..00000000 --- a/vignettes/publications.Rmd +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: "Publications using the eurostat R package" -date: "`r Sys.Date()`" -output: - rmarkdown::html_vignette: - toc: true -vignette: > - %\VignetteIndexEntry{eurostat blog posts} - %\VignetteEngine{knitr::rmarkdown} - %\VignetteDepends{Cairo} - %\VignetteEncoding{UTF-8} - \usepackage[utf8]{inputenc} ---- - - -You can send us a note via the [issue tracker](https://github.com/rOpenGov/eurostat/issues) if you like to add a publication using the eurostat R package on this list: - - * Retrieval and analysis of Eurostat open data with the eurostat -package. R Journal 2017. -([manuscript](https://journal.r-project.org/archive/2017/RJ-2017-019/index.html); -[source code](https://github.com/rOpenGov/eurostat/tree/master/inst/extras/2017_RJournal_manuscript)). - - -External publications using the eurostat package: - - * Kenett RDS, Shmueli G. Information Quality: The Potential of Data and Analytics to Generate Knowledge. John Wiley & Sons, 2016. - diff --git a/vignettes/vignette.Rmd b/vignettes/vignette.Rmd new file mode 100755 index 00000000..8f30dbc6 --- /dev/null +++ b/vignettes/vignette.Rmd @@ -0,0 +1,49 @@ +--- +title: "Vignette for the eurostat R package" +date: "`r Sys.Date()`" +output: rmarkdown::html_vignette +vignette: > + %\VignetteIndexEntry{Vignette for the eurostat R package} + %\VignetteEngine{knitr::rmarkdown} + %\VignetteEncoding{UTF-8} +--- + +```{r, include = FALSE} +NOT_CRAN <- identical(tolower(Sys.getenv("NOT_CRAN")), "true") +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>", + purl = NOT_CRAN, + eval = NOT_CRAN +) +``` + +```{r setup, include=FALSE} +# Global options +library(knitr) +# opts_chunk$set(fig.path="fig/") +``` + +# Installation + +Release version [(CRAN)](https://CRAN.R-project.org/package=eurostat): + + +```{r install, eval=FALSE} +install.packages("eurostat") +``` + +Development version [(Github)](https://github.com/rOpenGov/eurostat): + +```{r install2, eval=FALSE} +library(remotes) +remotes::install_github("ropengov/eurostat") +``` + +Load the package: + +```{r, echo=FALSE} +library(eurostat) +``` + +For more detailed examples on how to use the package, see the [online tutorial](https://ropengov.github.io/eurostat/articles/articles/eurostat_tutorial.html).
  • 2Uҙx\[6ڨ4oM=L+UOY2bh)pg&[H;SֺUb]!Oj35c偷 39(xSRܪbYaDJ,`iq1xRc(n$@18Wȫ}?ܰjرG;9{bskn}Iӽ[ڞm78@?WUQ\v??1@}25A2~zN#nObO_vɯY)+󪌑󘈒`ʅ\U`X\LJ23l"",nNK%$S2ۋ>E"|o|F>5xS Y9âF2?^i7 r7U(, `O؄biF0Pu~G̾dY}˯h t8 `D$1 D31 dob,,6؜D;nл6XSzA 89ju ̈́;3H;$1L x!{(82Q5:{ɭo[gzOtܦe# MkտhՃc3*쇗mNO -j}ރNFMыiE76D<P!.JOC*+."7 <..FH -Ċ -PzhV/cѸSˮw, ?2͍\O3og.W`^4\׶*3~̖-Сe_L&luGQoewwٻ۽\Džp!`<p"L*U" icTI#yԦ 3"e,N+Qm;H!ww6w7}pf6CL`'v,t ]S+KZiwVo<2vI UjT-pţk-bc.f{>X/FH;?)IJ?/UU%IIMJڪ ;ωHZVN/ԆuUrMm||2fKa{aF]2|}%=m)18 J\DN@ITtKb4DA?e?w$)#VG/$ qkFkVbk#QQVغ%#uϮwt;+^y0{9W(|cI+gw5>+'/dFs3]Z;vH*c -\!FȧҬheHes횵.e^F226Лp x;f~G+fǶoF D9l텍ÿs?,zڕ_sl؟nɉ;$5#>!d=fik6~EMmRQQ<ɜ ė -PX>ш`%)-1 Œv;`)I /5)"mP%.}/y捙]쾠P\^ޝ)$z0q -y@*Zm[~jO9pT-AJSB -oL|6Wlv)p 0=x|P,d|w, ׹7vnٷcRt KqY6qY,U~'Qlth&@R(&l[($bz$3PR Rm>@o>+*@\c'L9ZnBt Zcn"\4_Fl_-~fo}93==@(}sVԽ!O-ONɡbR`|yCm$2v.)-avD/+|n3IQw)bkݍ Z^0' -ON9,|[vnzjBM~uQW[,\ȒÀ0D)t4 r'ޗ<t8O# )Svj/ey{}}g;}gN I- - :N%PD X;R: TQPBF) V -_S5FAJTMfϝ"ӛ7'|ߓgqO-EղPQRdVS-sGgPN+a0bd:XiNH`/Lc&ُޘDH>3>k>&fRHGQ,S oBݧn_Y4(٥Ş]PFr\ϥ[ܵRǷ pqo}=]nQN3]XIra5GT$F hb& DJ&PvVm4+¹HQ2bm^ԾTfOr'IO"?߻3/>ITMg.DV.wʃMd.6~!_ĪW@X~ -? %P -h7,H0Y^NjV@P6?01 BH uX -텟Mtj. h'߷4Z6}*vƣ9&NTDp$SeRB!D+fD0!y^ճ0jT.TBBK%g$$ߒV&L1֧']Rڍ(/GXqEd%( Y] $S R"&SAkg& K&鳉׹tIhc^lHQƇ<ӐGQ.x`}_l^ie M?tWX4VP2/XzGZ7Vmh $G QTl[A?"E5Zr'=$#6DLp2[d`OeD~&qÿJ?gOV\\g"uWtkoRu Lm!P:QU'698䐜Qf;y Z8Azm~*0ezrZj|FZ>7Zk7WcLLtfV U6+9?s_WtSԟY\/M߬jpB5"NP^q5؟|gѣ\Z%0L|V:|P&QD7z rt d}c<# ԅFVGYf#~!ЈD{A7KvjA &D9G)T0Om"gkgv3_r-@WIy1΋z. xLɺ_+MO幓Źq Xs#whTEa:)Vd}y럐pCzp:`V}-8*VZ/i M3B tk5*(H5ЯB̿xs~.auO|B(18-+ -q mŌ=Av{g;JT>-@p~cx<抓4G0sЛ[ 6e\Jк c.v>ЫBo;BO#k"9BwLVlovcnYXwl3N ⨾& Dfַ^?y`Ϭ,\6/3i:cYӡQsghd}Ljf[obղ !_eׁ8+hf .{e=?,;3Q7sz늴ת{eڅA.z{%&# >| <4?`Ĭ֥;` -_JbO ASE]m'}a倗a<̽۸Ͱ[i^D~צ'q M%P{;PN3>G)z'2oB %1 ?Tw-liBńs2 -D_"q~5_1>}S(wcl;ְP}Z;D\z|v^2|r8"ᷓc)igv=@U(ZyBfsd2 - {"K_"^mzjDW"bzՑDw"a1'ĺ>O'OdhE >g(r_3ysu \|`!˻mZ#&Q(g_ef f3gw9+鈕Ո3ELG!TLr;"Fka֋ Ό+e:DRhc?sC8slK-s-\1%<8wB۝ezN?BMZ*'X&÷Y|}TL圉7:ߊ9GO:{ܼr<LjCYoO qCG!ix^D~E7|C'#=#$ou; -$cf15˒_YֻhC=ȷYʯYc%/ 0[W$@Cv3KqE<)(^<|涂wx$ۋun {<hgv>F 81(]z=wUQ ?+('1YsRܻ ?'2cK)cb}cc(~fμ,`x63-ۄc){pq!KiM!K **Bڒ6jH% jiC)$$AMX*F,CZME(a߻l?=oޙ;w^c_,#_r.(+5o2GNc?F  8k:\y7PftI>,y1h$ˌY<:m+Bŏ2ѿ"f2ol9Ugaǽ;~tݶ5ח-#Y:oQ37k$[)wݏ -MT ?&XDbmxo3O#T3_;+74 -9LNaMh4:FRlq^a!,>%laE &v! ]L=F-u:G`=CBlMҗҌK[9~{c* w$+gCy^"cB9?{}wۓ}">J!Ǜ3tݩ+9ޯg8J>$i)y!wF#Ǚ|ܾfr.uR4sx-6I|y͟~z3!mSsٿyv|auQ_s_xlΓv^'9rO GH9H1cs?kw=rWǜXcbνRŀjq~86ϱJGu16fyS2g{E cHZ.6 -11 P6M:G:|z)k$~q཭ElJƗ0vw;;~^iz2YVuY~镟Y,? -{lg{tX>Vϻγl2kϣͲM~yxr%U&s䆿E7fYOKn|q<6j|f_Ceji -駚.Ҹ+P!w;uF2a9:pJ`x7׏{=\=堫jFZV<D2z6Hqzt5 ?0)G%Dda eV3>$Lo"RoQb/@=5Y$@3 -CQC)"YbnD(;QQ -Nw'LϮ.rep}#˟oG՟j #YGOB7 dT0XĐV{؜=s3#vO;(.Vy9Jo>G Iퟵ6qJqT2e~y)L6d{ yޣ:hFpVroӜgP+틘fmE!HSmWr"뼁;wF p -uaT(ƘyYogX3ߙdƾ}vI F>=*[XZG2 -g ztJ^Kd9q!Ʀl!O]`Nv - -(a8.gyS.uP { Uӯ\anp뺙-DO5w+b .8nK$y$h=<"Q]F(XM49A2~cʜ&zjLt+󪿱^i -s_W!٦+ʼ\{QG?TSخ3}1S09J3FJpL~+UcqI}JkR^(܂î((@@G& gN$ؚoMۥL!S8}:]@@/|r &-`KOo#|.Jbcx/ -=܈ 1`#2]oHM!Qmm|h=F+F%F{>F \j )h *hI*hURT.Nm3u/읢hE]tRsftgna;K9|R5[pXKd-: : z u :cxN뵢K/N@5S?EJEwN$ѝoEIDw:٢өSGEwEgH|=cDDgJ9MӬ ~KX2XeU;u OBmἂȠȰŋkã-^P]. yI kZ\9>l䅧+j6,]" &T,nXX5j51X|c4kрUEU2#r>Z@RŞSgS=iw~־_MlZ/C25^oAVI,0~&@q!!/! $a7]Cqw(PZVB)sfgg{o2 *q8i4՝Ey>}H)vMʛHv3N54^^&k_ yWO2>} -P(Tl}aUKw_bϿ*l (Pk?_|c 61{rآviwwvw剶8-)Ʋ9FEXcE#vEclP{tGbgvLd;A=Ĭp]+=wfv R"$F$E2$G -D*FE:GdD&dFِؐ9yPP?(! @0JJ ʢʣ** -jj ZZ Žv#aGtD" Q7.(}iAYCyT@ETBeTAUTCu@MBmA]C}4@C4Bc4AS4Cs@KBkA[C{t@GtBgtAWtCw@OBoA_C @ ` P pHhXxLDLdLTLtLl\|,B,b,R,rJjZzlFlflVlvNn^~AaQqIiYy\E\e\U\uMm]}gd!fe1g d)fe9gVd%VfVe5Vg d-fe=g6d#6f6e36g d+fe;gvd'vfve7vgd/fe? 0(8N$NN4N ,<."..2. -*:n&nn6n.>!1 )9?/2*z7yywyO,|W|7|w|O/o_? - -&DI - - - -Ȋ芡؊JJJJJJJJʠʤʢʦʡʥʣʧ********򪠊ʪꪡڪjjjjjjjjꠎꢮꡞꣾ񚠉ɚ隡ٚZZZZZZZZڠڤڢڦڡڥڣڧ::::::::󺠋˺뺡ۺzzzzzzzzA<ss8]CxH=p#xD=GhcxL=xxBO='dSxJO=t3xF=glsxN=| xA/䅽b^KxI/好r^+xE䕽Wj^kxM嵽z^xCo䍽7f[xKo孽v;xG䝽wn{xO彽~@}a>GH}q>'D?20n/IR'vDZk{M -{tJs.23333s+3333j]ofF;#= -O3,x6< σ "x1^ -/+*x5^ &x3 -o;.x7 !G18|> Og9<|_/W5:| ߂ow=>~?O39~ _o;=?_7; p^/ݸE,a+XcGp>xWë5x-6^ x#1o7Û-x+x_^A`|>G#Qh| >'I -Bs '"f$YUUzz$f`8"[Z$سbŕxVrq-_P\[y|Zd WjdzZ$~yd3T)We5ݻ#nBNzRѴmZmEߊFп =ZƾM-[{u=ȡ?AB.х٠%`&rfijvTlk쯂4Y'j{I4=r$ʴә\FXf9);ɝ鉖ivt tδ}<_glA% f - uv.ե}uJެvqSr{dQh􌓶_A b%1I'&U51أ\ 3ؠcF]ϠHSQ(Z;CT˪foPo@Ʉ%!rGU5UaepbX>żב3-+tyA -HK64})kk'u JԵޏq"C#>j~ڒA4ԏߘ6+[JY金t6,VAeL,9 ez$CPҕoX.sxbDNu;Mc,0xQ <^$-Ʀȥ\:7xhGg}`~m*g~яL0=2ùϘ)gwXK1Wf&=5iJF,M" N1EH0;pruMi!AK̨Ϭ#S' 18eи:j 30xt₦Yv&}%d9KFZ8a/qjer=Lzܪ}| -m):`r>5$Z-cGUmΞ ⫲g.H/ykI.sE:]iJt-R @ iޮ'hir$rGlI~!3yl$ג ΒǷ?|xBh>$.dkLy@r}!gh![W%hgIl@4A h\f$HSRBI-MW"IPԆ6ݎ6<Ӈn+7Un~Wߕۿ*+)j%p9A,x.,d8zGP'ΫjT$ӣQңB=6 Y^o)д!0gϚ k?9a:EyVZ뭲z}S -5_@LO 1dJ6!sB -( SNLJS={rjVN>ZE*:#f*Y>#TD"A>b"b1G9vEKLO^8@8Nawˤg';IEO[qE2= %6ӠRsͅۓJ3Mˬִtm+ҹWJOAO"P\ߨ`Rښg~qOżqq3&/y[jQLv3YJﺇ*=/*O֣nBMˍGUMzō>~"Yt'fLe67?EqdJ<150XѐzÇJ1fsd~ʶ)G,#]/[!+&,#Np@;de;,&A))[}kt(kV&;E]S캽ξŮ;Ů{mk=7WVvULI\Et4fũaV/b|_/f^b/f{z"M@WT:) -+}p%vUJ18-Zg.X넱ZŹfk<8rYƚ<2jt'OUqӿObo -gNvS2OnH q㈟8y+p"(<-n^?K8cʶDzd:jyu[J^P В7K9|k[őg=][m~:AЇ=Ɩ5i1-׾Ҿ܉ūӉQ5݆;~f-kZu8Ou{}1=M"N۱ .V5ƕn}uUw^wO=$B9:ktTO*)uJJ){K٥`;OocQǕΉA0WAPAu\&Z)#72γl0G ~|uzo - -F6N"Ew#qA!)"l@} -9.v 5 xo :3fgɓ>Gq;-_َQw'2j x>sӏ({s~L"&ɬN픐d+)>DOeWE=}wfNp<2ݲ*Ot",I񒽣_t -z>S=J{/'cϟS?I?#I? sqډ c\,]E3^ 1Nu/d~";D!x ql /7D! QozCG?BP#GTQ^}y{H"F"bѧZH+? n.#KhWizo.ɱԸHZJ'N YA"ׯt&oRӴ"I-d/7܈(%ɱ:\N՘ҥsxGK '@ںxu3P@} 7P@} 3P@=wmdQzǎ^l;VIE$"$.Eő9%e9h.9ৢ2?S gcoTooooooooo2dL--------------mllllllllllllʏw!zC 7Dow#tG;BGGGG'_+} yy \Fd┧tEljU$;{=Wzouo;¾ 5 ,ELU-NaZ\܎XxaU<-wGeBxQ.*,rfqFޡ%~&am=V6[XGy)-;Vsiw݊1W-5n?Ph݇3q=L&ڊ_l ]eb;ۅE.jdS_5R]k*ͯak.wZ^6ӿL#2.UtBmQ͡JxurW'h .0^ftaw_w[+MȪmDgVŻ͊w[USnݾw{*~ܪqߩq}?q}?qǍWY㞊w+~ܬqOŏЭUV|iVCo.UߥzЩ:SV|hVCo:,.+tR/?"2P]*b$ Twt0K 6xzX d7y XZ @>'_¼8/}hc6s:=?/l8ϗюٶ]{-eCy*:hD"O6.?,ZOdeU2ׯ=՟=k!rO\~===ܯ=̻oe=|q׵Ai{6Snj]^9Zw8qp)OԻ3^O4,p'O}գ]1~C8 E[E)V3,ś#fk=#YOi؅Q3/91y|K4?؊sQ̓ioodko<׻6nƷ&˧Lq;>._ -C -ZÀ-2Vu zIMXn?1Kѷb=MtPMyWup3M$Oe*kт#(5`09su` At@@4(WPO_#  -p@!1t?YgL䪳rȼu1>/i}$dJFOWyD]&j.jC2}9=Wɮ8G_֫PlStSRM3\o,Nl.jlZ<|_"()*:s#hV9HTA A4A AtJ@ $*++++s9 -12'%'b3Dy.6ةOy.b6?E&Ky(Kb -i\|VJ1d!*oe>)PvJb) W/N/,w⌺QlۭImZ<^DN@ק}_'6Eqt\[UFbXl 3s"HmP T7]B*6VR-ZqΝ⟡gN T~ߜ2CNnJYm$1E}wFos] 7-Pei,M -^⢶ - koR.1IAuћpXWP[[Z0M>$^mg7wӁ;l_ĿNo`Й776l\N!Dt<1VŰ̇ewf#g --MxEȩk.x3.ZX --K%.EVgKfrfYZ!;[gMf7e=٤wV!AwV;+U0 trt {*;Cr/S9.ZS(BP endstream endobj 2835 0 obj <> endobj 2838 0 obj <>stream -HyTTWƿ- - Р{\7PqQH b@Q&Hb fq.QAp1QƤA \͙3wNuߪzwx"FӾc9+WP/Qę#K4ӄUğ!d$Ξ/:wQ)#)I *{nk܂N!)iYyKKIz]5v%dfr,`m-竩 iI&A@MilplI+M.W!ʅ+ xq CHJ5dqN-jQ^ՆIu(ϙ#;;&-i*&#~Cܮ;~h܀;Rxհ=d 3StY*୼ |IMym /47|+4C#Ah39u:ZWY`E0B`C( -6hv@{D:: d++% 1pQ_R25`RR/O(P4MN38sr+nέ)r8JÅw2.R>ȇNg?Q>ݼ7Ϡ'FsSFnܐ7q-iscU)q{'EwB|Տβ/g.׏$U>Vs_=@iµ%Ӛ].>F+dOENOm#ٯ;z|jI%mv}WÅܙ{K܉S_W]ÅB:J"(8 -J?8oԋ7(!4'i?Kx1 k0 -aX+^ wL$HH!QCL0 -5G*"tdȆԞC6jyRM9Ԟ"u[oRGM,RO4PJ b-a=M-QH)(KGOqzh!NZ$HKTc.‡4 ( 0Ek4 ;i -l~kzMG9|=~5BEam$}Ox*tų570\0Z`: RZPWK>uzK7r {ӋFIN^nJO4pWW_^>cn` nbn!FJqGkw1Tv 䅗 Iר5^p|D1 '4h>XM#4?ilTϽoo=^`88^1 -~ fƝPmHKBT&M5, -8El%4}=.Ů7{dmH+?Wcv:¾MFa[8{NžO؛|2P7)y9ǿw{UMԈ3*J)}F<To7J ,ꠔ:{mw0zU?^jeA1l5܃<4ͣƵzۯ^qG(0c"=N^_ >W|?3~8T?1?zxE:C$"=M-۫3.^;3]~?j%'rs`NsrQV/^_|~frXf a; Ff̷30G-שv+Sf]n_S<_8<]Åx}5>eâ\fprTéu;vc@s&Q7b?m+-&y3]+]Jۙ>˝Jw/۽򝟯۞lǂ-?k]Ȏ]{ɞzbd/iJ+N)th{vK% -{K1r -YAL?/t/JӇq,Q9KuZ~1_@n>f:rҋ"HEGf{lrd>0 -BKU_|_'!r(盲4\|J.+b ; y,8fq6 %6c 1(Ã2i4V5~ xm`iOػG&{`ClpH;; -;-HS|`Is \}\tχzdu=piu> -UKid֍7,cPv⯨wH\e=yS;wx^7MOqo]OSi1l;@u tMZ'^0@C! =B84d =ΧvS(Kt -;M,ws#WaS1 kCL)W=.J=ZwPmDB*Ц"d8Mv#<{!J#³UJxoA@z6Y2S\Al8ֈJ;\@%YGzWxih0C/EIbs`4HFhwm@UV~ UҠ(x9XPa\Ɂzͅ_W/Nqvަg!d-SmR/n(N-`4tJbX |G3{fcK`,p,0|  -;?L-Z0DMA/~D{P{L*ՒұXWI+{d1k6<8OV9w+gS2 vGȩ阿4L% m[GO4QCw}`]_Tsц6ph;}ϓ0H%cu`%'yp]6槁,$=&q\["-`2X2x"0 f,ǠWP;16ցfIqЖȳRU, m|qUo{y_ Q+-}Y_99SȕH̲yʦ8貃#3<#GЖ&sFJRMEG0un-/5D5'CغVSL^H.:uh!?nl= -qZ:Pۦp`]KT/)Y%zesh{7E憈0 -Fl.+[[z כ32j󽡍&k#uPe[i= =6 FxZ;聠m1eLyD`sQ(P֛BpR<6Da -?l(Tx&$hԌkȄEꚴRw&ї7TY3>ٮN"*eB]Uo|Ž W:b0ԮC:D-گCV=\o5@TJ1xy=U-22/45zEj#&AnU$CŚfݜ^Lkbb"bnb`Z)!!(b }֧x endstream endobj 2834 0 obj <> endobj 2839 0 obj <>stream -HV TTWUD5""jp_&GH@QPq DK&QLԙ: ub9Ӎ1nq $䜙?@#&*vp%ƧM e PO%PQs'MJ5YQMs:qz&%OT}$ ow!I><.d'%ejBmzd Z؟f퀮K{5%>5_Fٴ~D=i/Aox4PzxDI4f7q%9CT|0XGV:cdU1?ē{DůyGܖ2k7flmTɾ-t.зtKTDTB`.ɻٍMVjux /FC~2GAhf0Ye\Ve C8Z%Z9F mvF{t@GnVV|P1cQ3;ȃQ0Y)B ^ԇ^4PMP^+y9snA9nɭo F} -.B>ɧ8r2Oha1^Ň87d&Gg΍1cOຼKh1.zMk@:a,b013 ¹+#8L||= -7FRA䬤 יj#0Y( =p- DʢZFvȞ^d;roc8^湋Ȫ - U/[Ӛj!Z -ͽ̃CͣͱjjZ6/jک?KEYPKeee&dխq<.>[P0aW#l0 Wח:{"<8oaG9E@J&TAdjcS*) Ill 6CQ5ؘt/_WzR{z/s] 6*P5SʅMqa2*G-fڢlXjl|&5Ln& -6CVcSa} 6dܓ‰F*#S@B,(E\>8<0=+`3jQi<0nIqiyK]<ˢ󑦏Vq,EUipNjZ -9 OR6J|/ִ\k2jZUV.wt.P3".k5$VQe"vGv Fgܭut2R¼ OX>pq3xqFě`ac53Y -v9ه]Y(IODLN="8`5u4L`S h!~ 1+1 FaH?QBO^x#I*$b2 :5A -!tȆuֺ!ZaF6E P$ޤx|jy,NXB]:SO~Z;>NEh,P,>qNqAI ^~}c4'h&PӻpNFkո?Y8EƗ4i.R)Jc&%Ly[L&}Ù>?G+!YĤyh~kZ O4Ƴx6~/Q) Ө9h}K>`)u2[l;UD졉8H-7rN/{(%(U7 [t}_ppq"W #Qē7^H L _$&R#LƘG-ć Kb- '4hP|F#^&ʫ6?ىk|~|N|qc;N'-M45meڎpctC#B/о}&j (*BB^C7*H.,aP+q03¼|į1AeZ$dDFFG -/q;ȸPdzf -1^֗Qγ:Nsb{?~&WpD`'ʚġ(KR~~j +<8Yc2+|A(ewmxR`-GK)03 `Mx)2/kB3BR]Nd 7g -9 /٭rfzeB9.#TRD|Tr~|I  2&8/GDMQ)`mCdz0L< 5Z Hso@,)Y0Hox9 :bk#: D qO//pcX4c~>xLZ ^y%l;ߟ<7xY nhf4*@?V)~td?܏îbV?}iY{ًsKϿxm@hj ZTz+ B(xWf]0K<|ʵ[+4c 6Ikv]_*~,R[ͿC~ח9]j ? P+^5@^nӱ7v__@*~lТ5[TrgX(۩Β%d,_M{?zYY뙭(_FE]lJjq6/#SLQ&1s{x@fqpp1#2k+|#~'aYQďeF.Ţhhbm-vxLq`>;tHH'^džSN$;W 620iJi ฿G a:}.\Ճ /{lZCNU {Zl.?ؚ.?yk4tیxUuB訹7~; f >k{S$: ?z`&BAT,d~ZO N6 -ٕX8I`LG{NJڝS!d;Gm,gEaw)}@vm Yu+ =RA $D@bP1O<;6@XBقj6k:d:h 4# ֽ $ZC"1bS1r[ '}jB0,pDŽh3ozAmn=>\jd5m #ဿpqaݑpoʃc *h68kDmV{Z1GG(3N|&H*?B]kZȔ,OM2%͢:' 4UjOd@|Ȇ̾E==1'Я >Q\ $6:3%l 6BSS?z]x ÏyϠţ["[$BS -Ӻ}LHS>҂J&łivŚeky`-;bM6ٱgzZ&ҙi != -uv}lF;0L 1'DiOr5L++&/H4?}m؜}L˰]:˝_?\rr.zP!5Ձ4с4S> `t-7h3̳I7luآtMu=78}ox}n00zYk3|Iq;m콬 Olj5:b52Wqy%&oKlikew]ayArz:@r{n,>L"m"DT>WpwTh4U Ԍ?kPb -y#*pxzz([ 6%f}TΤR)A:%ۣTͨlLQ -A([j@ ja:Ne2ߎwa8GZ H9-(BlG0o pYr3J@3}E٬T[pwvmG_c.hR *[:;XLur|Z>5h tITwji-SX)Wx'4bR}5 540-`G(c^MQaYAS[YA.4E9[[7GzV^p<. 13Ru~7pwooq+ -UM!˪%{.S;1eMwva)<<ݬhq(@>ˈ=.Io ǹ[E#Š+cRY_?_:I&eM*]"|"~oz>s- h-m?,">F_sՇO#|wW };wy*&0z'避x䜏C#1b:q~KօCbɕPf,BG}m _BG|zK߁嵉 C/Zi4x{"lddn+x)"(ABV*H<'z;YB_Ԃ̏o=>͢.mA*:jgJu7K 2.տ;8]G} CCEG5)»OC!/ o࿥Nvcau%.ۋ:տ\GuykoϪV PSXclX>i]Tj@X(|#" -눙J'>B -lCۈ n$&&ZvPZha@ -1Ma_CKKA`'4N<^ xZ4N ~PMp|5V.!b xVY1='ɲ3tg)7\Ϫ|) 9-dTxΟZrPv44Č,YFqG5]sΆ./pOLZS\LfvWc'$H^3'mMQMIܱI*G2~HOgDl,p3\ZTi*+ gRJͫr\Y-y3E$V4o ^D@ _^2*$+aM⩫hhWM&hb쨬e5o `}jfcKjڛSxT?3VXdLKEMCI䲞 --鮎v.bd{ܙW5vd endstream endobj 2833 0 obj <> endobj 2840 0 obj <>stream -HytUǿ߼G!aKXd_"KC  6Yd =XR(KD VN{DHRAE%O ;(KX=l9}3;7J ;=/ =ҙ@I Qڹ eLtׁP'sF3S3VE@-:q#ȊqDv^aэ-wtvOOs%:K-* loNK ,>O^[??t~; z`FfAZ_^zN$v_rmp6F~ۤ6 HVH;/Ԁ J9TBKi92z66I-Oa:I.yE3B.+^HEBeb,r8$.rLP.K2M!wˣx8's:Osx==1>.?0Fnt2⍞F_#odEFqư$37js|"KZ+jfYe:XV9+ʰXV5*vڡvnG]vo=lڙ?GEDzWcWs/\hW+uuYXޠiuqzk٣Ԑ(T]Iim͚l&d5U "LɎEyH,4_i[.[ LeȮ}d!#8x* ^M(jFbDl/c1H3ryaՄYL6fYbn52[d&T5Hlw&##;*dvmhQvM3#/Y)[G4Y}pwoTբS:w§=?)\F>gSɸu/d*c9b -r\LVc: -031 9"\1 XoхxIbR 'jPR]x Th:BejI&YdS8E"q⌮LD3>RlEm)RuHPJ8Fݨ ulCݩSOEbSoCT@i A4ÃopRMF鸄oey8Qю~]+9Uze>/X}vkUy9J&@nʕrU&jF -V!l'D+ Q_"Xh$&:fzF&,aT\*RߊcFW#۫,*yWޓ1'Iޔw\.WG!Q7\U֦@@iKXࡀ#H@ "*>"BIPzQެB[F'9g=w-`&t相ߌxCe$J2_[Vηqy!іo0W5i"x3o oMdٹ6l&,C7* ,'#lO{g9IX,X9̪a!` !uC|q4;G7o9WW\p^.7j-~^é:. oB\ܒ7&.8s \NҚKu嚨+4I7¾/>GVzݨ|A_4MͺEV_|НWwH?zBO)y5u}=k:rw[6+vt$p->>qܧRP - pv KRs wR";N3HwΝw_r߸ow{x/4"^(eF^ IY+8~t?Krs]&+|-w=E(jYNh9~@Ki=Jô9[O#SeL2Sfڠ44&*}Mf˻ZYj="4KN -ZSki !eޡU5ZI: }E:T_:4"6lnZژ+;%=gD;ir^R;e#o0  p{nr'܏aaP@]Cwl45 Xp2WDq8C\$6r;"ϐɿס|E΀JrjkƢ[ps9cػh܀At}LŽe(ja5Bix^~:Ài /BD;1D#~B\%r|FGe)I5@eN4c^q杒gЈy4 -:Y> mGgߠiW_Ÿh@װv"I*06!sebm5ч_  "C<93L\ȃ3a o/IG6*E5UHbPL)' -|+nUtmVBFҖPJBQctDM4 hRK )I5'IbFjFшW$JL2ߋ)II6&MA> dސ|oLpJkm{T `ļh+Af v3$⚨⚠Lwo:Oш[7)5,\M͚U[AX.DCmL/'4;i|֊VoF2ڄfo`61X,9'HkD'\Qa. -o6[J7fR$ͮ,SzR`y1{QQTPRzmB_(D{*0.pcg5<ӸÔw;V@&m@BFӈқA $oLaYKQ}T?=;C υ Z8UTK=,ԜFvk>;T3o%زl8n006FZNjD?p/'S -̤lzMvϠE w&.`d?>A1]o1X? "0Q!Um`oNKmR/54{`U5ЮMȚ͑=di0Pt4lհ - LLt%OScIp*q08u5!V~bXDSN*tnQ8Nvύa<=NdBw~E+O-typR>ȆHhJ1eD,$yO"nlB^k^m^<0:dFSSeɾl96vS%EŒթN $AuY-] 4"q (aU})foFG X!k:ѯ~m=NUfBaXjYJR.jpB]]^+=;=,~mZkg-RSͷUWZ `@E|PUrMGpZXT!cK8 j2"e, -,4(<'x=^Ji[.D*vn:rԑ#Ojo:IOgVtK4s~r`x{pᯗ}3xWW~y>ZG/CT5cq#Uh.c⎸+I$<؃6Dm_J`ZwLLc Sq"Xh -Y?n܀?>{G'!#z6ط=_oNNo-D&m≩<3bȴ;]ut‘p9m|.C;);B,WH K}C[_G>>O}~Kݾ[»x$g+|}}첰Q"DԈ* :Hh&c86UbbU!4ɴbZɐfFotf{۝=|?&Fze9.-h rVTDOW3tvH+ڱ5S!qFtQxf\k%(arpfΌ"DLxdReUGMµVeϭܹ63qHtң'aF{po|K7-[kw,#o)kŕJOwr>/bCTI=JbSܼGG2VtpX1T%6 @Q2Jx c> !]P#XبuǍߦ{c+F>Fhs?nٻTQC& WOV=/R^x)g]cg,4`hoEKlj\d -==5{0 B\:GS2pgd؉de~w.O_2h.ro(z_L&vSa&̆0_, -.rVk}ڄ5zf#k6 N[ w|ar@`$*@_w<J^݊@z'<w6\1$F6A1LI'PTM)jAdLon&Ni9 ¡$3R a ]Xb76|l몞]cy{ ~rNZOhI /yݍ$O; JHbZeSr}SNz@SO.Oc%\ըzwkmhkvîZ]ˮf5 q ,. dSE*<BٜR}bd+l`K'=Pi 862&YiXV͔f6`Ggd>`(slJ"%A;G]e㯶9 xou /wbҖ¯_=[ċoA8b!,Y'~-BJIwHXjE|t[u4-!q6HcTXlig+WGlŞfk1J*IJn=[OzLNhȀS03cH꼀уiYYux1wk@)WVm6~[z`S6^ÊN3DhY)U0EG3ՀmBeǚyHj\:cdJdC0죖. }ݸ{¿VTxdP|wZYGw^6wQ -R{g%ՒTv]_d/򟉷EזjM&fyK\e[Bb-` 4+JᗁX\&RF3_,t<RBPz(/T CnERDIZԓn1ᓨ d':j7M ! -0v+l=DfO_{:?@9$ -ٻ;;Xݺ2>?C%l} 蚊־z={aM'ntDS3Vhb&IhR~v\'WDdorC -p*ѩ(©0,BV/&WD,z;'P_ڕzjJަ2Gtl-;;s^g&2-FRհo'}~wK3>񏬃 uxp$- R -s"ie2_Y,0|W{PT>s߻ l ²ƩfO'#bI1QS- j(MU|G )"61G+c45⣸Ui~73PJIqUy|'˛_\Kf7Nlko .WFݸv\P  (@̤x)3(40fG{;Y\6iLvHsdq$9nWEMta_<!6zAM *{+r9?kyuN$2ae.eg'ߵ矨oY7,Y0vܹo| )X1t/׮,z9 ~%#oZmjڌTxڄw;=a@57=1&=Y(>,H;œ sglf'*eAs^qwMvU*]*:WKr z RF{{͌Ƣʊ1=8pp(8`urx8v^*v>8\mKeضXc$3/s;ؠq{uۆV"@i ^\]?nf>i٪~<qhz3#ՄX0A§~'3@p2u0@V [H(`0Lؚت /8`mnM{Y(t^H(rHxbknhI^dq;b:w?^Cw uH~tMjΤG/uȄ5& H H☀F^m([trҫى$ {uըeBX.-ףzqA= n]F|2e/) -8Fu -D޸`sa&EdH"c`c9L&t“[2YUG[2 ~tuq2"Z9RLXh%`Z˛}-8xQGW\U?KѺ |6 3W5KdS>^wlc*6m`799Ain6s v/[ss֫e:&I"*r!۴,n*{,Ns,[Jj9rcOͽ7l#k2>g E+PhF Dl|%z1xb-Ԍv)!6I0`[ɜ#'PŠL󤟶ħI$ ?\lP ~l(nTu7/<5M={мϝѺU\?m1߻5ӛ+hA|)Q`WQN09,%)Gt""d+b$NgG9%Y[ R[ -nZ2$VzIُT nG&@kO/ Ś!&@%+;c۵wܻm^m7M9y JWe{đcǶTR Z.KY7( NaXWMXebnY) fU܀[Ro $Ic͢wɫT?6p3:?2rGypI&]>88S؝曱Z{=ob>xC_lB֝a -CZ=#Rwʲ$1@ByV*헎IDJC+nCsx'1O 2TJ5:ky^Ly,0ɉ~ڢaO nJ,s>Q]CV* Da -vhcӵ[8pAvf~XuNSi@V<`~1\Nw`=lriRlOv Gmc] PitHC-e;|ǭZaPkص>ݤ'D%@ktdpcgwz?wɕym -͑q{Ñ86Caxg8gJH "ĝ[H!EY0xġ4EIx I@$D`KyJ\3THME'8t,=,\_}qDc)bH3qzA0 `_-ܛT@Ơ%͟0SE`x5*0ϲ.BmPr>CY #@8]8RK4G>WWCvGU󺯽ww}& ټHbx4$$ -BG i -CDZLG 6ҌSNN!`${3&7s?{sfa^blkY)h1 66 P\*= ZXP":umU @6+Y\*G˻=i\*E)`I>T۝$\:;1Q={r>AA -fA/>J\ PmE@e$.)yW'ԯUXؗҫ!|<=WuF F("w {rƹʎ9?ufYs:fYd?]\⎕4Cݻv rvѭt;n㌷Wuz/<}L8AXa=r95P7:tbY/Ywtbg$ -V#/|mpy %Aie;jډ6EK:pP| H -nBmfE=7W|gZ5G-nҘ>c,"ͣWMݒ{ACͧt>ոkc[_.穲[֥aRN^47>ˣ'9tĠCUMsdf2 db b]iJ=_4J&=-dG -%.թ~=W{AuڬyQd@grˆy9\*O8Icd Q+F!@{{ W\C19--uf,5h}e_J5xx첲}zu/]T?fd٨-+fc8 -frˏu2{<~2*,mNg0")Apy"jBM[P}F:fǮK KP$Eu:Z$I6pDt[ <ޕͅϝ'2=IwT` ]0 [eaG_*z{&?7z-{q׈NG\ԏܸ8um&I>i'i/O.Ad `DI3)4+^\`(#"*X2.|nT$I6K"I,FezJ:| e -3Čtlq)k_p*Uvz =͜Y#g9 Q$OvqA[i] kĨ$J SQ(p1d8F NmbG@gSE"!8Hǎ(Tj. Ra( -v !ĺ睶JtR7䱁9=R38#PJx%Pr_A2J|\qGz4GR*}:r!9KI{6^^j5_p*M()LuQȔp!&'uJ}wq=5TtKf_)\|D%tJOX7.h=̱6x}_<(0=+ -~,I) -aO͕Q(:JnTC6\G&pֈ>^4LR#G),*A?hPʀѩB1L( -뀝3 cR!W?\5겆w<>z쬙i̹%6@i8c`'<їa֪FB{Ե6_ -|Tޣ9YdZ+GB: հV$b7RHpx{gt*wJQ>j Gn>\CSnN8Blv6;Uun.֟,o_rgºxeVZ-ۺa k<( nN?y;swljsIsaMvsZ.Uu]RF'.mL - -ʭ%m -鲰j"SLma 4*Ubgw@e&E+Q*tL ?%[+,ܺ(ٌU ™ -ic(q|7/zh7I[Zl+vx {H?)XOV ohd/z 'jNEj -!S:[ "c)ٝ!-Y`$18eFf2:ħC=߬g5E**޳$kך>:‹kyb |$;*?_=4-uF\ Aez"v!o'v:O^/./;IAITnڗAtD-TQ$%pC w0sIIHxtBx6f|6;#p LsB),G~{Nba*bKQ+B|JիeRZ2\RϔRz\0L9ET@E+Hyf~Wc Nl9_XzKSԂ8Ĕc0JG ];/1F($ἥ_MA6H "/ˉM64ޓUVAGԌ'<5ueN4ΜiSK|6YB&~s6^ncq{ٽk'| ԇ~}>~(/ -Svmhfx>h@܀VfDe8 -t-I@I&i)G1ɱS7Sθ"WbUO0b"ōu1&vr_K R1:y-QlFj5/_?YyDFUÊA /:B79[^R/91+?v>2`WZȃ< /e9H ]”D&IiRzzF. -KJJ5aFo6)=@h3Eψg$Rh&/\ùj,pP.tI] S/fg:}u~ws p‡QG]u ?'Pm5m6xՖrLe"i3%?M/>nlz]\{k˪1kegW=wGS7~ѝBl|)L~`d~fjvd6%Yn7qR8ӆ@U!O[D-Y' 3Z=kemHMvw1gz0kLW0 IJmg [%RL/ }Rg}Zku:;ȣxVvM7EX-4ݮ"Eix8+!-9(xP+ĐeJQl2pm( $@PЕ8>{y[< α'O$"< ڻek}rキ#7~m=ee{00O sR~`S0{I9٥5yi%-5ob&$d[1;t9i`AkpݚV*@y*Cq?<F“s_Xޤtq#<.we&sqsv]X}}C["ﲓ| _ni_b -M9v-EP |m ;s$:MYE,עr-eε\-h`a>۷V R]$fg5mؔg"K[=b6)g7|4 F~^UMbevVg"B b_c/MX3Y4-~_G0ݍ>57P!P5am݇atHizix^oқWRwf@s?@NHnJU ͝m&xH\!ֈ($Y3@VذA% K Sĭ![49MM3ٿAW“VTq)6|lQËKU-SFs}8/;5٧8R -Q -s|H\fI pa5Ah^1"2R,t - ]9r< Rlm8C`4o#鉮D'WN'*Ƶ pHVd&%{bgs,`יa<gA1rPգ XeEh,Vwx\ܶ+t↚[}.~K;H5ʇ@l2B'gCjVѿ&_~t=7.x.@ ?dh5q'd|L#[k|-6O7jom7;$y{.ocsWa=`u/&N1hc*>{`u^i?>i\ϫ :m{ G>@({ W;GxsAKuqp;#f\84I{X!n7ӸXIO>i_Oql:)h>`<xypj>$WV0/t۹z>v#(x<6 -侧Ic=Gw;2sjݗq}A&n6Ԅ=&Jo97NxQ5dOK7.Ǝ^RcxeKd_F|Izsf$)^mNM`rkK622R.6r=+E+Vֿ4Һy+]zvS,srKi&zr}G=Q{:^6_zL'i/u6!/<"ʼnld5e.[{`^}Vq9׶d|YWҹۨULvq9/ _);G޳Wܹۛi#I|Sqߝ:SME34ٽntZs&\I_4گ1%tbx-ϒG}s x=ߕ}Gom[JMnfi4/j#G=Q eyפw= /b/ru~WS#/V:ugJS:.4R\6'c~z6c'_j~'tR hɬb1ˠO$1ZWeEW\]xPy71svb!9YbfB -}ζx=fvH\발>GTtΚsUɄؿ7sU~2q R&x/1XuiyiG;*ʵԾ/׾Y4W^MIos@ P36M -(Ta@uHg˥zyTOs]mt;J(QD%J(QD%J(QD@5pbCg9;1-RT ѓ}hXA -v.kR7YNᏬ FC*]F#%H[emHO}zo'uzg'wֻ?c]:l=nJdWL[mPz[{1JOho>ae3<ʀ5t5+XYW[€5)XUkM Jkkv.` VVT@MEy\`MVZz4`R@5ޚ+j2k’P%*%uәʒ~(r2V?3;ß_ PTQ^RK#\(XeC k7us4Sh)ܞ\1!Uz! - _Tb&(Gi%Q*Y3g/-.ח*H.L9MN?涼{ϘuI;;ؿNG3?e*($8:m)ôG<Nc]ndCB?111`(!1~d" HB.(Y03ɘP47qfa6ng1s9܂ymiQJ 2B2"M-Xr 5%.,E=; _r܉*װwp?VÃX-XGDx E,6`#M،a 8lmOI xxr؉]^)?OGs/"e%~2^qqa- Gqp'{'ig8w.i/+oO)Fv (:"Qt]E&HDHEWX"ME Ab"C0!/2E9b%rEE# -X1Na0nZҲ[kYkVˮe۶m.mjqim˶ms8EPP%PߢJ CY( -J*jZ:P?'G4D#4F4E34G D+FE;GtD'tFtE7tG-^>~A!aQ1q I)iY1s1 K ˱+ -kW߱6c VlvN_؍=؋}؏q_8888888󸀋˸븁1#N4܍{ q?b1!1)9^%^5-=>0 )Q 3c2c3232?eb&aR&cr~LTL4LtL L,ϙ_0;dd.fe>gd!~߰K[biw,rYYYUYY5YYuGlll¦llllöl®þ¡ñɜ©ş9s88 K˸+k znop3On6n.ýC>#>c>>S>3>s> K+k[;{~G~'~g~~W~7~w~!" 0(8)DQB-|!fb8!n!aH> C4$ g!EHR!MH҅!C2!K>!{29C; yC?CU(?U69vcf=]7v7iMBW[,2133333333Ӟyy3#gP>L:4qẠC8 XD`+8g,8Va‚5tуub>6p BD-6vp."\Kp).W*\kp-x'xxgxxx^x^Wx^x^7xތxގwxލxޏ>>O>>/o~~_~~?nэ&tSE e)Gy*PJ4EenC{ftݜnA[ѭ6t[ݞ@w;ѝ.tWݝA{ѽ>t_ݟ@'z=BHz=CS4>i?5htfi<N HmaZ#L+tIgt!V$lZ.ȡuKȧ :FQLEiv\:Χ B.KR.+JkZ/z~d Z #õ/``X"HB`Xw8*XNv.V2uo}הoKoKl--J%aR&dm$+"tEJ}ҫ=(E$|[g5HM>V=ьQOteg -Pe= 78gҬ}!r*,w`nNY)*+]jY2V$#؝ vI`y=Dq ܱNԯ'w'/#ҙ+I+I^ %$6hR6?{N)3;$)w&úk6LeNA! $[m#Gk )= fs6wg\X #qHI (`]{k`tZ>px-VK84vEli}cKCO߾!^oxћ)]a;7N#ܘ5o$x%bWU'+޴r]silE-OHQVXIjk8n=r7 mr^h$/!\"BW&O.{Rx@}xmh VZC_HߐK1L m5`d[ ӣpZa  >AF*|tAz=τ=ӕwr`tt!\(|뉁KbE([{voIC:yDoxarΫ Ǝ| /02j+k5dpv{٘푿 e+I xnLrc)z5/OK"eY.SeVy h<'l.ZuΏ}OeF%ӐH$qs" hxүEP]dU$ XPv#6$ Ҕ b 4eS|K;%\f뜣zJAKk"o83hr25slq4AT~linkjC"ѶjAnp^\檈p2rOb;+oڳ#8}H VQFzX~(B텢DWS#M) DttSM#)Q&7‡LևaD6sk:b>Fc[ O]cCHGx)[b \,ZPa |B0|BN>X1g0nlIZL,=rt'h# Ls0)f:ho;c\?Acޱ f+N{.= %²ZN[T30lC,m E+wI}jm֎ CZ=;HNU qRI)ڙ8HoD}䠾;_G9诃:=9R-;;|HHq;{T˘|HthӋu^O %5.[8Vײl:`QI)~:AWRcbg *s-F;&[w`[p.P?n׊Zs׊Z=ˉ6;*U2{̎,?}[8ؙ^cVq)C#<R< wtl~;yKb4i _`cA2hš4ƺ8ß N#417erMjҫLUh@Mu,.țAXDM^l#WHC n7= aL03˴dtnta ( 1= hC_«m -ZI[dNK:VòHBlJgg= I8Q!JN XP0@/ˀ۲6*+Y&/6l@ e\ЖRy@~|ssgA݁2r@mx:H(,mb3tamPoMkr,}]m(m~ڱ6LM -P.T\Pc?2Rߑ8BQ~jC+Сdj]kϕV0fV:^֓c֎n+%`u+pɧm} 1QDzr4`̇#!!hM/Kio%D1"Sӈ3iD 1㡄vID# Оdq -"%c2ڕ~<>QЮv.ƭ _(W(W(8P|?c???㈣8_K$^,}iӮ9xm۱ ڀ<+X=M﹮ ;ծj׊ſSXR+eʿ -,,< P8Ԅ8D -!@Cl/ pj$ (cpbW ^ Sq*ƥb*.[EE*SџT?_jG{q ?h'[&ZBGa S l9ͪq)~8 +wۚ$0K[:&鄷 -b QE{DFBAEL#jE!ų dYq2`׆͒+̐,ON"Nn*^=, 7Íp8ܨ?P2TN5ݎMkxȁ@/CVҍVҍH^[>j=p}-.xeFeb`~zw1VG"RGQt:JՎxGim -;D8!VY,j(of*@۔_oQVUcU{Uhεq6aanYAt2F> l,%Ѧ KOeYIMNKgr^tyg"M>M5<$?h?y7.ЅW^'n<'ȍsxt~W8M!= -$hY'xdŸLc<l?n\Cߓn Bf5.O(X6,4.ac4(R*O8$o4t\ rG|.7$*}&^x68| " ?$MfgF}~ It~/yzg%\Mij_5O3|JV2xqnuW}> 2X]9#E&K}q .GSFɧ07FϦZxgcgq8.G-ERD(EBD"/\3rys? -g#g̙[=uQ3Yd'?\mn1H=pifh1=cꤘn$SIMӫ" 6_?>536|Er90_9+|ERחf-7jRu*  ˍ endstream endobj 2832 0 obj <> endobj 2841 0 obj <>stream -Hy|MkD$H"&7!AkJ3#AFHIh`J_myH$U{#ACc֍ks P0-G|zD΋%d$ggW2-KվM^hL 5mş,L>c5Fp]<2dw&?,-#+#2)ɹCgTW+#9;5~5!9#uԹ@D}9qJuiwgNN͌9QD\F'px>3nq4 --IIM\4wv<Ԣ%U|0ɻΒpW:&OZ=׳?4f-x F 8m*ٗNOt<`v;؅E$&o'd]u_D!0CYo9ˠ|V" 6#"gS4C#-mܐx̿:?c!>@.".W䕼q]abc% Kh!񧼜7O8ًkhba*!YX/C#E 7| .n,@L -SeN2Vf"8 ~FnJ9KKh9芬{[y8'<B>%|ArKZHZhEAaDsy^Kݦ7=z>Q/WCUK`+ -WѪj$5CVjZPW6SY[j DYXFYVXjz[}`nmbaM6ٶv -llGm 1(+ èڒcѢqg$"'r'#(-ܧԇҪuɣ-=] -Yu&ٰOr(e$.Zx.E]L+=L[]AzU.*P(UKK+d,Uu٠V߈.{~`Kei.>KP.CCDm]|[rb1%K6Hl3?UT1K㱏)zg="J!ut t'mtt]=R/-H%?zKxMߨ>` 'k?>mN0ı9NsvIXYf32E *DQEeSmRUchBȭ4)j?QGWVZ!@E뤵2>ja{=U 5Sa {CZ.]aG}N Sɦx/T݂IVCGoZBG~~ t&%J&vL\$#0KiЦi*M؉4S~ܕ꺶yR8<)wpVWRL4Yږރ/ۑq wg2퐣rt $hFT pBM)w#q|rgbo:{1e2X_=NMgt10lKg;YLN{vhtGi6ޫN}n>IЦmNh41vF.ZA L}A$3 ']232XVFFmt 7[A{ 9݂x-6I -[)61WK4qr؟.L-C&x^~u+;ah 67Od~4QEB"2XQ"%y `XYc`1}!#F-XG#DT_HDY#3w=nWf\\m.oUȒ)|t/>3 - W."K0Mm+:שRBM37,'* a^dFopEvG뭆bii6`29Q9wUKz[WY MÎjo[UjlY-6d  -jK]ՙV<^Z$jUAF]Mn y_ ʎ{Z:!OKꙀhY ta -$2_I&2 2@o#:]U_Qi2ɉI9YT4z#܅o(JvC;7,aq9QqoVѡڡg]Jmy}Xj5^IO~;RQ39d`_NlX5M呖F+VZb.*]MVtUl,'irU> ¶)}kM3E/L٦To^,<,]YXfͿAowأm# Qo=5eE{nL?>~|q1ThvE2Ze T:'o篊l<\ u:`Ͽ${ÍqekTw'wxr[ܪ|dd6@vrTOy|;P2j.2fϦ0UU HGFΕk\|f)@-GBlGaS@|BgqCq,J AKCY`ȧσȱB8y#Cx>\=ȇȗ!}6iS;(x -s !>>!Ի\Pc6,|ְY\ni->+QʗI֨jJ@5QW1Em{z(QCZ8:%jD'Q` 8XQ>K@ʭa%Y54yvHyAF@@全lAeDc^-3ŸƘ4*?XǎR cyN;TJl€Ei07Z0x0 899nvj`Q{=K1yV~pveH,E*\ľEخSaJWP_Bm9y1 -J[h+ vGl6T:Jc{!{/K`AWh bʇ)Q=зU:^+QfTޠ+ﰧ{XQ2c_a" `-YcZ6 P(bKq }iìFK1þ žT~@P̾gճ^=j$sطoö(\[ːYȆz#A<%mSthҠ!(mn"4$yVj݀*m"6i*"!C`b\C"6*kmuw[,KGQEJ=(Ijx)I<q}3;CO̟JJh+evcmt)ުk%ČC}l&x]ĘOcv{E-q 6ˊV1ש yNvGv@"](K]~E D$=>5Yk5,] n|%A爂;dq`?s`XQ-h2ʷ -k;D+XSq;𵩺,0 -E,pU}I^n^^GWB W*z\O>"aWU#'d7;Mf}=-X_"pod)o"SRii풶\ԥ.u˿ 1BMQ4%v32N%a< -n(>x"Jt;8C&{Yq #(x2SMXN`Y,8M^|svqGJw h8 -K\g*8cn,:n[7sp3q~}%B4+;پk^:ɡQ ,*đ2tHo,X^C/&@s&%UvN6Xm96KΈ9`660i)6ix.h<%FR uF Loot>)U#]'k5FjwkW endstream endobj 2831 0 obj <> endobj 2842 0 obj <>stream -HyTTWƿ - Р({p_p_QQ(1 (1Ycc f1F5q&c[T&.ĸ5*oќ9yTwwC.4>uؘ9/7կ@33U <IISMuܓ19%{= - `MrR_\lsp{Pg'ff%-iDrJZb–/od ԄtLDݑԄԤ)nLck9_>=)=<97[GFk\^cG4M@[Rp4&O8zE f]g[}dUηb2D3 œ{Dů{_3q^ 6qn6LUCB'3stJd0vvp/5w|e~G#1Maf3λ9ˡ|V!6 ahVGZ#m[Y^Wpb\E\F%W<&72;ե R0PWC)Q_JN9p/ܘ[dna|`y?Wp1>E|pŰ+k\yC܀x] -h$7d?ux+bx%g/ZGr('O‹,db%+E؏B -+_|%?93ɿzOQzX0S帉ԆRP.-ʚ^_d;qq ,=U=UOK՚hZs-BkGGǚ}7-MowD=M_/TҕUHNuVjVԻjZ6Ojڦv_K#X-!hK&g ֖xkRP3[Vd;`;jGwȔPБ\eFuד{! |ɖ#8ӰpJ%t*eued>ɉ|4#i!].cju1鞺`=LoGz/WV/Tj]ڪ(%]e*W-eZ}#.,q5x.kuTtfi+.Bb}j]gqH)%V, F<cdž{Fed^è27uըz\T -x?+F,]v,P8WQq,NJE;ێ[㒣ܱQXX戲wEb 8{=4YqiRw)9O?ݹL>*E ֓bk6r$'sN> -q>Q:v\s%1|brg+0HjJ ZUZjv\=9?O~ߡS'PSVkN. o i1 W{]8sao1}wqS7p~~>V(YC X[d7VSgPN&N[8u#Osjq7x(_E -%JO@x!Gu -5 -)tґA")TuGl -<ɦ\jMOmoR;#9:c u"Bk]x8+X|Mq^VJ6J72v+E(i8@8H8D3pf{Iz?"ϴ9Ii%>QI9kh ,,|KfA*544{h -~hcjjG8|,$y[WꆟTNi<5 iC.JM1a:)-ZoQGM.Ea)u2h<6Sv$WR#- z %(UB#u/Zn?`bᾜ`~G ; j3 Vy*Gyf.U"B հݶ܀5fT: sX|nYU,dyc>-=8}OtW>L U>\>v S.=uޠ./mhꉑ76xF6 -`P\k(WU⻉$p@0b ZYtzlOEܩg'y -@5MA1@23pXiR" `pJ 4aƔn^ OI!C]x}\j#8Mf9<m2\-l\-se -T:riP-O~#&ѝ+焹l\o_;3ar+:z@|Jw^B57GUOF(0Vů&xS/o%6O&W#^9%693l\̑evz/uT= a?'KV~:/="4R'i֞.`p&Ԃ_c2yA|--Sa$Oכ- -oyޔ8gs2^Vhs\^4eUj&{*iMeg`]}bp>wzcrN}c~Sȫ1 [pyM1E?\5z8ɜlS|pOLm΍8FoV/&1K$o>g-~W+5?twp%#Lǻ l[F]+sp17f, hNIzrDBCg-JeTKKL2@ʬCcrV,n=s&t+As̠jFȣ*VjGV:::hEkIbsJӑHle(&U5b̘Y(٥,礳Ky30 >y{j^h'@{f6hWtZWC/u -=$NziM 8v0.XhkA3#)G_Wdoա鈰C&R&g<:?ǟ5x&0j@Gcc3 -3?̪46aHZjDwitM ''d$.a\eIK>IfU[&"<U@^:]8 i,˖+yptDE~ނؕ?;.6qܞ}n=h{buV 1f(@s-mTF"p襪JGj$ n܃I1v>(8 -n_rBvz0WZ -mȓ{_)mXr]f]t{9j􎰇g-7OLC4Le:\9cW綸LCf$ r{WώV%fhEhQL暋vh(J@#+]dfqRT06{-yqT?!qg6;{wYUu@P~.L@d -?VRd^*=Zzo}q&;#m\[= b#+4whڽ$$fv>ULC#a="xUD[P*2A.jțylCHVCV&>-2tS!T``Ɏ5_@jp{* Yj`'?b'DZ;$ &mFt!T JC+ RU:i@B*ZMa,бҁh(T]o}96IL!"}9]s=@?"(9#e5퐊`)UNa6MN`_崺Td 7i5J|q[$CD MT2P{J5/sQ$Baj͒9m_CQnvX#p1*uĖ;݌}۳}[lٷI 4)%xu↙X-4٧} -/ikY.*p}Roz<氻UJ o3m6pS9NSz]U6ot;j{eV;`o.SuqHIZPɋ8̍\meEyڿoʾ;9:,Z/ZQ9;0CŦ+;e%@sl<]=m@VO 'ɺ^/ND#`MOVs4@߆֭&6) 6in)tlL١r$ZWgu8نPD8N?sk ;bB4ܗHjE;%?YC:Rѯw0[1;(1xG ϐ.OtK}XT4K$K,uKcl>ʹ V8 j8*`w d9OB>9}FF:4bB+kSq -\̤\{Z%h벗&ecPZO$ۂ}ოqQ]?(?f?J9Ia|,Z"_8߯sLa}QwM..;jŽHﺖ[7D*mo"w<[w`xõ+~ rŷ^X"wϫ -w]_^2{)7`נ/NYm}L /RvIZCa2GY4lHZj?\j|xE׳6SzwM#y+Z!oM:s$A9Wp ۀQgph.T.Qp#Pz緩PnO{p߿ L\<+R:^I$%?>sd -هEOw0)\yy')Uy=wyXGg(d:7INsNȭN Wimiٝ۲3 8s4W9 -Mw9g}|MJTOS#h^IwgJ|tr#W@s}BQ|.0s!7;kwb\7e:`FP .'k1xP]`Ǥ[$0Iأ D- r4~pVy͠}| ?3Um8,=rxk .o_em(ԓzC/y\=,uRxmx10䚵 Z1wM1\mJ+[U6 ci4_зߵ3w._ ^^EB=ax [ս GGYj9~l6؞d[Zf5F aj"N̂-P.L/=(yq^A*Am.{סtnQ'{Q -CPQ~LAUt15kc%[$x<&EwDfֲIK 9ey[+ ,,<`_`61f̂ɗӈdRs^-/jys\'nqsB/ e]26*Ѽ\0La) -L6uj^)%t԰IP9ڪqQ7; -)(r5el 2"6"LPz-irO, b☥(`@UCG䢉=r'eng^Y<3&_\v{-펢Wey˨pkzmd\pޛf˭s=wW`,0ƣls|HW+>KENO'8wzK`f'. endstream endobj 2830 0 obj <> endobj 2843 0 obj <>stream -HVy\U:pAAI}/\pDyL-'|"fD(X< sh/LEr֜ru~z[߷A!Fݮq9'>5@C8+S5z o19}J)v]W;SRL ;xޓ䤄IUe2~$Km7KN*tx>B{M3L-﫩 iIc?NO4F93׺<,+y3ROс{j"XT?}kI:C> -ƙ#;:gd>I=a7y׏,ݸ=6q3n6ؗ4Hg':K%tJ< ]\KM2{CxS h O&D"f6s(뼇:B,"a!hhhD;D]ЕCʊ{7F Kp+1ܩ!(zPGiHh* eWr n-i -Vܖ+pAͻk^Ņ\8!NTŰ+k|s.#ܘ}.x -ݑ 49sΥg#^^MC F0јqYB&VùP8@muMͷ_F09+)LQXl(帉ԞPeSմ˞^˲]?p,':y|U!˥|AjSfZBkE!aQq8:sy{끺E}O+5zw妚`+ -WQzj櫷r6MUP>%Т,VK%22ѲVk [ukk`k5)4Ėg˷َ1*b!WQ]덤΢羈C!O*Ǐp:PJ&wTIdcC*bq> IlB:l 6#uؘtO0I紐z\_]M`㫂Ts頢IWUbE}l і8Zl|uL -m.}m;`+lN7Ŧ2ؐqGjh3`+pBedJCX#cӇ{ m aTҺb\z\ -k)Q~UWD1b?e˂ uYGIYFVG2Q a"GC㢣ܱrx8;wq wD %by {=Uڶ4\ڴ4]%ߔdG>pXj"֡F;7D-s"ye'>|>J|Ե\W27Zk5V.t.P3U#E*KZ>zG;\c#nI#ֺs:wpk5aa',|]xy`Y[9Uuo-*?\pxaZּMNj,QG&QXEz#J0ͩ -?e C*h"r#7r䁉B^@P^H` `60"Z/dSk̥OȡvS'&5:-z -QO,kiCwiSQiQX$:/rդ;O8B?*aH1iZCS9lïp/sa,`*5t - Rm QgA]&u +7VRlܩA/`'%aM>z)h~szB -C -_G?@m  ] 3/1TnƋI$d -+R+'>=h(0|HñF#49lBac8~}&4$ix ?'&41,ЮơN*&B NB542c@R*SmS?ltҺ B:e_SˊI⧏Ϲ{{{k7ٓtu%Eol/]fweߠ ǾEf\?LV!Cfc@|1_w#'4{ȸjCX9SOK<@=HXWh4c}=,j8Xج,l`ne_Gn*oYVu{5χyzg39JaD%5X"Uޤ -F#!,jM]6ETج6+WgV_Re!#=O@g!9n"̄ˋ? &mRࢂi,zb_~y@KWY:FƝAnX93e -f|j~S̻S[ftwZ~'ծ}≵"meƷşhOTZno4&3#]5cLbt{Ӏxd5A6t3xj< J%]T'pxeP^p!!S*f#UP41hKm Oѧ_)g%{MdS1{rcgY 1 pt73 0| N:1I#;0ǩs~8GßCX*Rd?C#|<C!A"_amнA˦b%×C8r=Tp=vSsE:{XHb$%LdtUdA쎌_)@<6Eg &"cP &­4Wh1Gʗ -H؀ދq,%r.'~C }C+o<d &6 i> Nq3M񱴄}Lvl{ pI{Fy2ʓ4*G~)H#.`eŁ@pԻ!ݐz9Pz"0<9O4]>_J f<_q{\ =)KQM Ċ{_8wb$ 9Z&=63^dp*9*0Nl`Gv@nź12_dNk2ұu -Ie>8hC}4*JgBY®b|.e8xR~(|s.X+)c@Uq?|qd3'6*` -|ȹ#C$V NN)ok u,V2_1DL>ƨ>:@>v-XK[SlBb a'rEIrE<^M@nvh*vV}% -Kࠀ”82p^'A/x( :@`ґ~ v)z/+^T*.඲!8{ sk٩څgF5s,&zր7E>)Xؗ;u38W|9< ĥ(c!wCN(ǥ" D~ as6p-@٣V?!rZ0ӤC۟ ?X8?;]AsϊU}C2g)DO*0n矇o5bܓ -1Ow  )_1j~ah -H - ?B'r/闱h);\Od|6B+Q_E B޵Sڟr*@uĐLGFxcx~FkFKq1"S#5(Qo H _q\5Sfz+(E:C~O27n)= z˷W -77mjם%%vԫAnW[{pk^ۺ! -ۃbEm' @ejWu`yM-ݶzs@p?EmV}SPYQG(7:Zbm]fjMN:9J}@wB]OAuц{RZj h Ö˶~-t > endobj 2844 0 obj <>stream -HVy\U:pAAPApA!5Ŝ5S1%EA52{e9/߫?^݋e'p*i4Ƈ(A>ؗI' Lc9Ş܈wr99~qSq {sނL{>znmzGՓYR}^[ߤ/-K=ez=cXt w kb>+8E Nw=4 )q.Kb4Mż}r0$4Oo 39g|E/00`6R@mR7F:U$VS_~NS}Jc/%cMz) _R|# 2Z -ֿX\p O6.4 W$PS$R3$/ө9fP ,x: xa# {4h$ާQB㰕R^mWxgID&c%CD:,:)ْ-҇d5jَecvu[I7@c4A@Ad%EE"-6i )\Eu.%V3{߼A{i TCg_smtBE_>@{ko7ߡKGc"m &t гx[_ e*סC:'GqJJZd,|^ϻ - -(\GRq=Bn@΄W(r:setn,s̸v, ͗se|JňLM:U`=EP <22O3f8Bf ࡚Јx& -; rOʲ\D|T:R>h0sm -qBZxDZ󥒵~H+MDm6H`ȸs+RHЂ0Q hуhհZFjmqHۍXAo 7gek=Ÿ֎)$[{H˄¯^_\|03l ˀ_CMUЫ1Xuz60zɠM& -U"/5"#+q-t.L!|??"LXx[ƎYu,pط%`XEC %K5sg@`40D>1^W+ۑ^HkO&=WKGŇ 6Dk0 Fa"KHG\p۞2ᖧSKe0>q:v'LOfaȇF#QAE( <,o IsjgER,L4akw^>۳se~鑑3o0h`-܆ eH-QcC>CjDԓ8#W~UHբ'̡ERD9}R#ڏňn#Fj#Aဧ9܈$kƎ!jlM}T_a?EmoV"h1>c8;h0wCwPƔE'(]xG&hWyzY=bמF› .Dže9a.^qD=@Kƃqyc);rkxGM@W'͆S跂ӗKc)59ȰAy ><)%wqk9F7iԝw?+aJxj6~ oZ3< - -_UPK[U U36|SbRh7HOגf6Kj&ў x9Pqo)!z2ZR¹+WȞe*]q|B"5jP UCuV]p5ŠmTS唔*ˑWJ塁78bNgzW,6tvN>ϟ+F"ss{\]ni<(%Er-U/ -vZ= Y ɑFTϟ@.=m#364wRj$7I:Jp`93U6Apj \ f/|y6Ǿh7("|}umQy?@:e8 UHݨwX($**M2xm3ꝲG݁쌾"т4"^-unc}V_|Kcgѡ#0ևoJMilzEHe<ވ5¾r M7 g ΅\{xϷ,ԅwזր U6D DE8Zfy[sكD00V@XN >tY8213 c K#1^ =lQ,-Q&n#cA⽹w~r;>wNC&qX^lt6+W>15Z\Ӫ՚{IRZhF.?4e#m\,29$3RrBMKȩo~Ji wE&5zYs?I,U[TLYרTE[*RpYC6ɰ/:[-mIh}a*>DkS6MYǹ@KLZ]K9SaOD0!'|u'AbSOMۇEe^ZVjQQzDC oX͍0^`Cܱ:c -gqf)sO+[z׭"'!adH "e!2Os0H>څ,xoڈAe`]6Q kbfjYEʢ/p)0!bO -N;(4+g )@@,x.)kq6q -rDP|jB YLBOUGgXl4'FѤf`Esg@M"]""E1%z4zx._ny`Qatnb^9 : JFXXanrpdBVG H^OZf~{A}^sThJn3>cZX#֟R&v[ؕ r` íOZLI,֓HO0id-𷃔R@>0BOQy;um7ݡy={줮pRi{', ˵lrKM+dRelE[Un$>T,-5N4FRϏM't_)nXjVM]:@ t=m]h9׽v{؇HLjKLC\g3iEtnwZocR={C:h̻24uک1e,_T3l_1>uj4?4LA>'Mq&.8h ]:D9r\ehΘeT91D/4th^2j" ! ),M$];M<U &1̄p ӐC|0XKE2a_f"cJɶҵI^jl"\/JADY -E)q - F9VbvPA/P/9EKt=a ؕe{esC{CtYCoӦzil^cXC <Y -iyX5X֬:"DF u@έ zM:kiMJ6mvS=5CsmS69'3ŐRG[2m~e] w}:dـv+߿ϣ۝i G7(^C6& .\E*̕:7+c+~ҁ4 R/Smap~A B^// ??6of>Ak00؎l0BZc s`sGL@@i(!GRuH*I4-UD1Ԁ .R)]ϊҪo73;fw͛7YYBGБIcהr?cœ1[BjvNj愊UMc7e^/d)^H.V.t%4p3/,ͰOnb<%4eih[QaRG]f6D?;[Zp?ϒ -hlgWU;-E ,ջ((+ewK$fF)eW/\X[_O|ls>DoXmcD: - -t)+eErJ;XךR7rhWgz噃n4߽hj?D!NK;{,ilۼRg[͟$i,L n~6WU,11H>}!E{|K~ -RhFʖ -x} ~s x.\rY(9`*f~C`-Y">zдQ OA('e`:(.h[Ese]Mhgm'}y_#l׏OΡ]?T#R;@Lf..Ħ=qN`O%Ѽ50Nȝ.3*t>R1X6ʷ`' 2d)X."Nr;-dR 4GiƺݐC`ʻ,QkTڏH|?2 ֦l+yQǥh%7f|SAv\<}deYffv &*r8^+4S6(֪XPꅝ&:%Գ`#hSȶZ)T|dĉwJy޳ V"$>>}ov\\5}rw<6Kt"n~)0C/[1O)g?x4kۀh/^Y^bjٞÞ9˸ 1Qח0j= cGyUfǎ2_ȿ3DmvmҾT:w"~NQ;?m4:r3ic.~be[II{N'/Az=hMi8)%=)NW=#N'v^q"%uhMi4/1"jjAd$i"Adr"}_3QJfކ|#Q0$(m*mRyNmPRmGVv_=?~ccM{^R9֢.H s.-G#99z3e1Gunl3ޅ- DeQoj[V1\ǵqe"{Ԗ`wu^#k7fݴ/٥ endstream endobj 2828 0 obj <> endobj 2845 0 obj <>stream -HyXGjz![af=ˇgp<1y\ͭ[i.1 ɒ_$u?!ZG>kTUe +.TV\8zh/@yG#11w9B! G ]XюQpXύ2`)dA.l%0VA܃(_cy'㼃!2!NApN8 ! -<\}wa\ ,(S!!!qn 0fB$,Hِ -× @̃;؏ - -TQC O);=GS1 4BC?c{\a| ;agyWbWs8u7R7gkq 80 8GB#&8s|(r -C1 1pjDwO?Wa6I|'vbMO1ߐ=^8%mr<ڏ4Lt5*{gtJQ99.nٹMTY#`N>x}^ AuGd*d 2 3ɟ^CqV!S SΒ먵R(P#RôMmE.DqZFh5F&dSԎlEvTdFܠPgK\RԩE((w/J⾜YSHK Q"JP<ExDr7-q* 9pUUǿy!BIJjB Aw HSU̢ HY齷,- IH%e0^20츓Mf^޻?bLC)YzeDJkQc|x$8~Go,Oa|&)܌rsnyaܒ[Q-]%iC/YqҒ~@6>>wq܆H#zGM?GiLTe+GSUTA -1IbB+'I -TAz U~͋SSlX54)g?L{OԻxz{sib؎l(mnu0diHy\U\E-Őq8˸KL]MI6Y/͞6C9ùMKqi.eBz^~/ y}kl6k6˅}rfbX8 s'T!Cu%u}@ҥQu]V坂+J:BWU&Y2뺺W* ƉtZ8::͜N'ʉvz81\ܳYׯHSPfM[Vl~KOo =UOV`T5@ZKVNuPCH NG3MbTjF+U;IuV]]J:ATvk6*Zov305BomSC dLSRHnʘr)o*܎ۛR܆8rk1)nBL 354>E3|38S=B;88OrӍO8:C !{ʞ&.9A 4{X-T;hIsM/e.ɻɪݫ<܇_~~CZjCdGS|cR!# -@*LAT(TBQRTPY*GUJA -UjTjPMETSjHYjLM)5HjN-%Ԇ(R;jO(:R'L]dK]uԓzQoC}yz^{;@;H:DL:L\:Bl:JL'.tkbщbĢ^Nbw ޣ},z_!Il/|Dsi#`-[//%j.-U/^R*6՛-vvwtP:D4/?#9to[8I$&u*IZy %x#O_ Ok#HϔN)Go4d݋L'+I ?O$\|eIK-$?&##ᘐn>B}:,C O2a%!AH%!Fj'sqRRvB]7RsEQY!yit Ww4eɲS~V?8 -~R]Y8j.z[9| un1,\{Fk^^hi;[MiU{~>"=\çqk ϥ^T>BwzKʡ9/E?E5Of&?Pzdiq>|^¼5sf̘ČoM6uԔIIv*D^t:Xs#E(A4Pژ0st,1KpYpD ~xü)OXױh8L)𚾝-aowgx}'9 vlPGK[x,53 XSr&fVo3dTSZ?b; Z9Nm2#nQo*)9Fz93|=i|}%aєs}tM< Yun}) ĒNlxYlsFn sgF0ߟgٌ+trֹʹ -=cwLx9@;OQ^$dT!Mӱ~ ZʿK)f H8e+Ymh%%rBfgFc%O3+Ӗ# G./jBƖvxm!;1.hZs#ÛJ3B #\O"Rt_<9gFٲpä:Fw#W5>G ZJ @!zگ@9X?؏*fyh`F8ռ6ݞHG)UhVȹh!c^.plf@8G$zP@`DK-( i%hxE /Mdx]*#bt" M39/g]1 |8 m`x#br" Þ"g3{| ڇ3\SȶJ0\D^7!׏wzf1a õg.᧑m`x#b~" ?3!3@~faawI w>@(=rʟCy)ߔHfIPQ Qu|ʷ!Ly8*|H -bt-&ijY6{DI}w\]֥ 5b-IՓڇ_`h -MW+)?N>EH+P@L*@|ie (Kz6<)k%FΏ|OFHʡ[JaU,T#e햩ZE,|߇N.vFR%~[h~^.0{Dr>\DoD@= -a}mZ@CU߉y!d\={7pВk\=_0c&_ U4'z5Nh#X{6BGG1>f؞x#uG͆9sW Wp.k + W]H~d7dWZ:0B^SX3T"6$SU%8虐i|!jRۃRfH//a=׮S}w Bỉ0μs Vqg #I1 X -ngAZC۾h/pi_gkvQލ{Ӻ;bwh3g|oE77.S1|.%x%3'T>RvMToCJ4t8@dH/>'aCtK 5`޺[.)O$ļa7/C{0z#btiW}:e\cZCc_;Oexy6}۠!amw7n=%crΗCy-4pУ {cӿ$Jb_W#ک~ ql߃uM=\ {-8sH/*+{v%UPI -JLJCGb -! 􍉖 C -a(AZRFP@;TĊmLʌ2u!wGff~svﻻ{=Øh]|~X,Y#')4k"㒵zޏ7S7^q1vTL\g/r|X7:ɘZm\I\$w7W>5|(QT^l@1翇){ȷ3Gk(ckL`ޖڲ i1h%w ^uc>c!]>`?Rks_\WuC59e2}AXƧrtíALwDw3h!/mPs*B5^>j5cdd]5dKpQ-+ɏNf=jb*;Q!yGeXguUFЎĈ䀺&yq EIHm7*uߠVR$y5Ob1rő0^{̃2r)RǬ,5BV6wDxy˿HHگ2ϸщ9 cL|@2\yst s(e:i=׫o[[;qIzD<{I{\d7i!|5jkc uYDkgom Qte:uڼ^RSS=鞞}g;I>kz5iڋg~gjܩ*ӮQFs~}^ ޢAu]َB]uK6-Uq(`;/E(`Eິ:T\56QPy!q%gN:4!h㯳ir69&\'j\_~ɘ̖ПmNVz*sϣ\qU 9׳|֟7_k6)A@hes/>B3;ٯƳ)jG5KsYrI]r6@SDP1'9, iD52f}I^ӤXrPgpo!?K~sUX$O,+mN 99F@Ni{Z02f@NJӠ \9H~E!yr~1-fmu$vuHd'y,![箽;,Rnۓ9U%ՐH>kkwEߣQhLڜy''B~/Q%zRڜL߼;Aױ_azcj㓵j=Z? m Iw"#V8w fA-mx,uX{1o2X`/5g3{tW1s2CTX=OxZ ->!CD-X&G|׉^sDۣ6EO{x|\rOszxuET>~ou/FܭC [lŶg׍#.xzʼ?U3EYv:b+Dj&)N֜p= E=1bo6p3 u.ΛJ-Y -s%hj1jFjh}q WQ+qZwS+W-k-8zUTm5Z9}SO 3|q[1)J` 7D<`XO 1409dRٷ(>K.s9?җ:a__y5Ӡdc/F@mrZE {ٿ5iy9u%;m|Q.g s$qzHaypLC4UJ;5Ԫ13 !9p$54|gK`SŽ  Ld=,BqY(ߘI,zF ->ZF+P7^ pJ -:㌥K14cx!ãw< {X֊R3:`w &7s%wPsOVDL":oS}D׃U̎Fm3cGgWHo -Br\H%qKm>~7Rx8rg}lG(Ԏq$q?g`xh'j華4JWyxTf$@ ؔ-0 &]@yd^! ",UA@ApeSl"ЕPZԶZT{̓~o&/w=sjps9,P3]f' |dȱ Cd3DogY21x ֽJ 2t-D>D㓢o_aV衼?ߢ|h,_\P[k$i#yzR6KrG9?MEk;ro%1E讗ܻ^eVw\c\c,vʙl/@86=".qb|Zhadw@%~@xi';M(ȵŨH:/Z31i,S9_eΗ` e;"( 9SP>.ʥBx%2pX;wAiV 8p8p8p8p7 E)p!]JY.R+cmi6w#\lAk͓sy2r\l6?fڜH"6wbX[ms m{@q>y2z>Rܥ<} wy2k<(yK'#}H$7tueɖ/F?WܫObo -+V-*$FjnYM*|œ'G'[rx}Wܫ3g+xeYOoP~S)X_)Dxx3\xsWޘoָB*6*Fd*;iSBjQ<_lUj-)5{{jXxM̟X>Z+w?W/ h*aᑒ5#ĂJS/SdB4TF#q5ag&%FQ4@01c<sKwUJvE#^ϝq)8c87&NTPjx8)x?)89~_J5~s->>yN]TG\Ÿ_oR;_o|(3֓җF0 Fl&dS6cs`Kbka[lěx3; 3=ؓ~f3؛02,`e?d!8q0p(q8Gp$99c9999S9s:gp&EYM r+bFYɹ1xsn.=\%~.\sWrWa#\u\ M|Ǹ{m|;$4|{<_~!1)9Z%Z5ڠ-ڡ=:#:3+;z'z7/?` a0`(0 (8L$LLŴ123BafL -Y!K0s1 K ˱+ -k [ ۱;7v>88888888󸀋˸븁۸xxxxxxxx?€ )afdFaTFct`LX8xLDL$LdLLTL4LtL L,l\170/g>,,,¢,,XeXXXXUXX5XXuXX ؘؐMؔ؜-ؚؒmؖ؞ؙؑ]ؕ؝=ؓ؛}ؗ؟88C848#88c8888S88388s88 K˸+k븞[۸;3B){BYxxGxx'xxgxxxxWxx7xxwxxO/o_B$+*+"*~ϊ(hX8xJDJ$JdJJTJ4JtJ ʨLʬ,ʪlʮʩ\'r+=2 - -JJʪʫ**jjꪞ꫁ZZڪګ::zzkjk/ pHhXxMDMdMTMtLl\|-B-b-R-rJjZzmFmfmVmvN]GG{Oj鰎討NN..鲮誮nn鱞詞^^>>鳾?}7}80Lvu8wGt$Q1ӿ8c;:;:;:;S:S;:;3:3;:;s:o<ߝ Kt)vu9wWt%WvWu5Ww t-vu=w7t#7v7u37w t+vu;wwt'wvwu7wwt/vu? _ɞ⩞ᙞٞ㹞^^^^^^^^ۻw{z~AQYQT]w%EҤҤ @ e;lIfwP.{zM:JQEfw6|9͛[Ν~֨jZ6jڬjڮvjڭjگEVGQuLW'IuJN3MΩꂺP%uY]QUO]CTD%TFBPH@"p ZQuQ7!1f4-pnhhVh;m w+;FD2z7 }~HC @:AbE&# ٸC00#00c0r:rCG(E( BccJ00Sp?bcfbfcbcbc bJ<0x <4x2^x 6x|1> |5cV3`-a=6`#6a3`+a;v`'va7`/a? 1 )8 .p q\ſXYGEVa<$^ǪykkFa]c}6MlFl&My oe3y[[Na[c{v`Gvbgv]nλك=^>La_؟{{b60(z\G?Y idi1N$Nϩٜù\\\¥\|+!>G(|O)>g,|/%W*_|o-w.#~O)?_+~o-\?'5\u\ M-m]=}!*ǻ0/)81 -'5&i[dE%>tOaD$K z0r}FU| ؟!7=O,<2aߦ*P=bԽ*),k2 <ӌXoDo+q"Qb*g´"VIX~O|]m݉:x.g:y%mvʬfv KW DY%[)_ov_-V/Ll'al`ŸhOP 8z \gi>#w$;7*Oosθ{PV tk(ͅ*hK -]*eS~.LiYB"!V?|KMWӈe|xŁq[fWi$%"kj] j]2F>"u"dKVP\|" ʍ?l1~!1_/5O2Ҧd ?',"g^B$co,RՂM[o.2[g"EΡʊ4k2}dLw wJ,C՞c<?s5c|5ѳ={,{wM_Y2ĞH{6e6ӷw0OE*?qe O\7L=22H>??K7AgY9E~l(932a~f%Xwhq{X79PLʋ|ԭ|HR+0[] -VfNo/KCl7X^B A?6_Ps} kWk sb,?lw):J|4 }e;c3G?aҐ5Çdж%iےKx~@6enG\f+1x"E^>q{JnHA@g_Q]]Y~9u[鶨r-Q2k ˭B>f]tV˱`XłmE VEK,ؖX$E(]zR -Nx1rr5F¦ٚݠ]̋^mJJ=1^WxV^YY/_l'>' r~n5򈛧E{],){SABʒVhCyzS)ZoZ=6<7$ +KTkMüyiͼ,9y<%I>H4&=Ѧ&N9q mI-yb!%.u'ӘՃ.{ե^@^d_\r_u}I'˲*uOOU_u][YeIN?mu&j6qڗEjՏdoAv8KHp`̗y\ ͇gɲSe|8_;/<&E[ċBљ8j6DR OA^Hm\i]|V &Ah|KZsel>%C3:X\z '>l," -<}KEj| -.]N6u3>>AS/> -!~ȼy&5lK*X+WM5Vr4qg^)l#$S2hy':M[6F1&M.XfBBע׆5³Y,x< f6|m6| ߆o÷m+Utb5~SrK&Y -cn4ӣz_e?o.ߝ6n?UǮ= sb"e{<9Eͯq)+ՏէZIvS]uqQ[:2J%FluՌ.ykUByUVX c 6vu.6+oל_W+ -<OS諬Oe}*< -OSSY_k5| _k5| _u:<O`}}ѥ~}}}}}}}}pLc3Y dL| ߂o[-| ߂olx6< φgólx6< nxf3333333333333333|߁w;|߁w;.| ߅wp].\ ׅSO>>>>>>>>zzzz~~~~~Swnnn^^^^^^轎ҧM$nH p~K=Kr~MmR_oM~o㵜9mћzmUonC"r -m{<_F(2I$&U[ޫNbhbKQ].޴$jOkI>"V$ rEΕuKty{wE^(X=x,6÷GwU}=c?M%%B{~?P(q9x*9 -wX7Kw^֡w<ӭID:vE1ÐнƇ -ahDᰆ6mG)ہ:ɢADh~颢Ad~(xNٵh?Wv|?0=6xN㝱wF:u3H{?v;?u|#?u|#?vw;~>aϻ? D?haH0>T? (;~vFDdƒt0Pz**SߑV^W+O&wS_l= 2Z>4M#[heY )V`p_8> -#yH!#矊}&eƇs?0{#fO^4+`Uձ֔·ų6vu.ֻmbgxsm$ط08 a,ȼؗZʑO#lkolg#-&PQYcNQ*O{#9w.l9zqۻ=T͹ݏǯ~QyL;r؏Ի-7#k GoK\Um26yxp[䪅madWͫ˪0~7<̿m8<ojwOEgPXb5hy!XW>68ڠeCp#4ZmduIIi-0Y6MRyzyS.VimdizbI9 .+-b/,8 gZ n9!J?ޛN7G,7oyеӵMnYic+ܘ}5Eg}\op -+5f,ym;hπ| 7,yǺ?c8`%]ǝ3@\ݝpLd##HST7lU^Ϟ:{F2 wX 4a4[Z4N~Vg¦v%YzZ*ǥ(l>\v#lOǔZ}+'p;hJlc Dю'$.ތnhh )G$''''~c#D wך!-*tZ-Xa -tJ [i*Z=Հu[=;A=͸mfk=n Ox O8c<Yy|u^Rvۉ+w#Na*6'G+6OÓ#ǟ}i|2}h;?5Am3;l:[LuN#;om 3 0-@ 3Œcg4ÀͰ9#&Ss"-z6FZa^WjރyXfxѮ3Iww[hյ턢ut $5Եhh#X7fÃ??????.n4&h60 sރ#6^G4t2 I\w#FFdd"#&7`@\Gp,Ko߂ -[oׂ_vvC@ /"F~v܏mе|55i 9glWap|X'ݠkhaXiKV&FOG|Jg?D{ըgԍtg-U ϊ4~Zl[3~Zw޽?(t9ڭ/\ݪMAs܊8]Z-ʝ׎ -{јNaٷD)_bP 3?wITw] lk>jNu66^lfWKUfo^zBh&"Q1#bVDWļ=>TSO>TSO>TSO>TSO>/} }_Bg:U`gኘC̎";.d꾒4ǹKrZ*b_N禦dmKjmo&k3.KL7H}K"×# y)tRgȹL]V"ظ?:Wԏ\?P2c}j8.^Tz[:Xbmuex~༭hъSC>cLўx7: -@u0𱺕:VىrnR}#T_OeP>7P$^]H -\ddGVJdGSV/Dsԅԫ<ӿ#u]?eJ w#"Ԗ~#D"-_?(.w{ ι᱿fՃCv8ǎCFb{̈́XM,''^I|.rbNUfʔr\Q e\S$en_r$Ks3<,(ʘi8!}g.^:#mg3ey?y[_gZyd" q{3oT󷫵:g%.^ɢ_^?{w}ixm=xrL+ޭ5Z,S"=Br"Z+]kܫĽJk-&VWiz 3 endstream endobj 2827 0 obj <> endobj 2846 0 obj <>stream -HV TTWUE5 Eob(!( Dc%3hpW\'Θ3'DE[1nq  9g&ϩ~z>ȁ!)bi S|cuęYzp'ILcw|19uGaI +w%zе߈sſxNMLv4oKKJ7X|$%|qX@ۚ>5#؇hEg>}zRzS{6o4rp>d<^ģ7G4)j"XT=={+ ad3@9htQ&I=`ǃyGcMܜ[?JlTL?:K稄S)] ;9w $p7|dM ?-`f38ˠ#PVeA !EZZ9#m(-ڡ=:#wAw ,(T*GJ&rDV -B(z ԇJKy504V|crݼWr!q>|S8U~BCkGx ܘxh7܀ٍ.%8*nĞ6p(7O cq,db;8| - -o-o] -\ܚHmT饇9F!"p)SeS-UvȞ^d;r/c8A湓˪ -eUSњkZEiE^!a8zs{꾺Ez}OFW媚+ -Qꤺj2FmR_6vEYKeee&`խ֤@[mmvvPaW"l0Zo(u)8D0R1-~布ԎPr 6 -&;T-o -۲ ǗGcڗ/kK9N_nt)N#bE=]m~t\q9v989:F89b}X}=>>Y^Xj./-u9y~zW%%)#MUs,5"bq;+'<H]uQb>S۲s_ܪmIoT[m3.\t8\Ρ.g0BBDUh״:XEՉ\>ڑjm-twQqAɼ˄[o泏M彂m{Bn)g.Tͼr=A -kfְe,rXgPFE Dz`EpԅwPQN-EV+~B7\@<ʯPNaR#D2c`= 4|B#Fb jm#sǎvߎێ_Q8iMhj&m.aŲl.HDe" \IVE+[T!v+(;Ge93s;ι~ -{tz]GWwm2t#zO}^>B75J4聞En%E?OУx~ }GqA:dIҠPZ߆58~Ki6(*:A*z|wpoB';}*A(˖M2Q09ɢd]7 -_egI++g>r[Vy UWkZ݅avuva ㆇ 02H2ct:e1qlMr6-xs/r7u?χ΍/-$Kxwt>:dd -Qp}6!rڍ "6̍a݄/&}xRbY,k_/Sߘ o{/^l>͋We (뢼 P8>,M$ҋϏWy{6'N _+ p-K/4Eh}8Sm\j;kA# *lPa<#D7 DI-! -יѡfNLٛh? C9qx)Lj+aP3G#TAK;YSf'kw|QWG';r{J.g)>$9w9?o>w)[t|31c?u8 -Ĝ+Yff9g^hoZmi\[;Yu6jzrحY4.*YT:s4QRSRȗ)1cUL'7I{n Z{G',oܿg;a- +O=\Yf4l7ZC >ާ:6Lzɏx EM<gZ$/f牞yu |Oq~ -i`C֖ -X㐭ރP3Q Z+/>qRs.WqEl<>3? :pY'gxX]eq eTVP@y X㨿L+|E6 mF8F)AVZR\S2RmJVS}1yRh/QA汜|? -)>Ha\kf)SY@uJ*YU3ޡ[06yx?Y%o 0oQ.c[ۨ^R9jǓ&kXk)W -Y= =Mncj7npOFT} n#]@M|ύv0{y2}a/Q'N ?S$ /ySxr.a1 jj~eS_(\(!&Aً{.}h2ܗN(AQ–J9w=b9̍. A>(D[B;>M9{٩Dk\ 1ب dU(a/T, J)W1(ts)3&+hz+P!!''R|A*gF@ JiJk!hs>$VnîblVu Ɔd{A-e)hҽ\<݅}l!t2(u=A:{#!A-l#{.g`3ϨXȥɌ!3k Kདྷl̳TwW lP'mVy.urQ!U!)Ht6m,!) $%Sg#ðǧ1G+q}9K]Ybrr.aϵnOb<-؏:$z:G2)C)Y\|C/)r.% P) į:wp<^'@p@΃.<ւ v=,8 IJ<)K'W:x [ϟ=īg;&`}2I@1Woo gt>دI=߈x8p{9wX~=lu 9Oh9(r݀?Î6Q8rґ˧u߹(7pYX=#O < H2ux=&c8|s>Dug7p;6Nl3aS7 nGȁ=QVc}}xy y >]*fqs?xy/Ež^D|}9iGpC_;1  p(d nA| 'C&ց="^onoϊ KQ *|Kp4%(Sn#(U3e̔2SfL))Ĉ SRx Y8S*Vl'R.jnQF{nB&t`A0 J!/uyh nDV(u]PZEvvo֧5*?;"[:}ΞD:;Zxm uFwqeZ#흭mhĿ4_[֦E::{ڢ۵H}Һ{mښn^kC#DDȮ޾hwg,@(B;iEJ[i6H5jXA c-#:Hq5_`= T`P T20`;0` 8hN)P6( 4/:gep9@= 3ҁrEd觇d5 -=KA볁b id3<`}@^&\.Ȃ؞ b'ݚv[&X0o4l&FF&mMLL@r;0vfU(a;]{km "70? endstream endobj 2825 0 obj <> endobj 2826 0 obj <> endobj 2847 0 obj <>stream -H|1KPk(* ZRR('C4MJ:n -t.{e0\|{.FJa Αm4iIZE,6MiQ[3PCF#m:=jQ_i8jRD#΅ ]b.C߇VRE|ݦaZhR>X<&˻k;!CI!Q{1'Ef4VT~i_r|JO z^ԳYZdB ~ Y6| R4e1܌'ιY{t+/ endstream endobj 2823 0 obj [2848 0 R] endobj 2824 0 obj <>stream -H\Kk0,;G `gEtT1Dgȏ)TP=̉6w73ͬMhoNе7QF᫇Fi6?4=B(~s-\Wuޱ|23KXY:襱@,}~^^7XbYadM1W?%+N)#2s.n\~> endobj 2849 0 obj <> endobj 2850 0 obj <> endobj 2851 0 obj <>stream -H{E:`0[Y endstream endobj 2852 0 obj <>stream -HPTǿv.(K\DX( vAEp5j̮PQjh7FdIjIc1!ԶI&$6m3az88yw޻{9~y  ^U5T6,onmmɫKuO6U|* RܺL`ODO}ؗ?: d5'}v}S-3KH vj?/I4w6L`@6S+i$b淟ۖlA|A8^H/Iq>عqDo޵)8y0:5``"btANQa"9M - QL@>}\ݔރiIPH]G2:`$a3 -kDۄsf-"-Ӵ^uo%Y;MvfӞ!A~(󸀅/7iu Na -?+N~XM1JR@(pل>Ru5;ezUnj2hf C|^{ER$iH>O(~nba-(;|/?'̃a.h,v$]?&ExWE=XNwRVhӞbJf?`Uq7JaK*>%vJmqC-=c؁=Km|l4eN.fݬb-vK< @h / -w%NJ_l?n<4Vо/(V:bT iightЩ]ƻՏXKdXJձ*;Obs:c'*7$!]X!l:hJ&8Uh4~&!vJ %R^ -H6Zꕮ [ӌ+ۍmt:Wgl6U?P͜l ~Hqafi {2Mpߣn=8$lI):e+ -b1Rt"hx8Mj̲3g$'%&XM5M0$Q vRT**˖e'd*ʾ=VljV/,WG$WۘEJRBpxِ5iU2.B9TnMFYT`b3ёRN -3V2]=V}W̥\hܐwa˟\f3)˩NU'QQ[`ueD3MljjzPqFggdB_}A"JC&Exb@Z[`t^?VװX\c hirǪ^2a/!9X7Ĵ!8S ʹl[IIɴ!J#v"\*S3L Ao'oҨX.8Yz1'(9einjp&NڷQ^ Q9$RE1(7 &olH1kp B !p5)ܪX,4ZzB{0Pa‰^4!…'j. ?^2pу ;^J:„ᒉvNKfN#l&b,rvEʇDb"+'Dx U:5W=ڱQkÄ?$MgB'j7v$K8pPCDLc -D|@byS<㤸a zFY~Q]\$MJeH:}% ƒ"H2H2ħ QiA0O5U ˕Y;>;8N.1!۠%@@|A-e$*,b-(@Jd JUֱM-Ӧ0)+D-cay_Yysؓdv旔?+Kk@jɎ3^9KP*L| 'arM;\F_B, C2k(@1}4rzuSӨ~D$R"9G\|rJ/|ʦ|QD'OWS T3Z;]jumsmh35$~9(r)ۥAۂ_,Ʌ -p'',w&nL>S? Hthؽ"Ez+RF ֆkCB=(dtLϥJfetfMW{u]yrF;D򽆡+jWI llkJ-hzuoΑ-*So̭~:Ѽ-K珛G t9o4,([]L'C1*aMN(kSFc“*TanՖ@!Ǩ%2i|T6xKFzZ.e"" -G; 'y03٣*$%̠"RI;ν8A1U*F͊B`m8BX|hl~'l_3Dæʿo:q` 1onnj?tad#E) -[>gF|6'81h%^D409 !3aXsڜ3iLf7 yŧ5jJǨ.˨9Qx)I8^b>{V}U(jƃftD 6/Tk02MvA9 #̺MbLQXgjm6IL\bO7&)./=pbN? (^?@{'NOE΃*xCUےQVnsDĆ IJHH^>s|wĭ'+˾v{,궾IY%ѫ&Mn\[d"Q[TgH%R+ 8h5:d"fbkM|΢1&We*bA t:9$5R_\V\>6ߢT/w̐W~OدA?˖-_wv ,#E")sJ) M(*ݩL#_9)zbi~ǩdhs3 VI,?L?FM(*]Zjdڔr -ӴD:M0 ə%AXJRu1}X$VTΰ Gݕ0߈qWnw"z=@`e 6U{#]Ol:/ZKȄ\rm1(19crBCHQ EPL)>q|l`/l!>궚k4 4ԩTꪛvM -b Zyw4=إŅ0sĜxsK.&+߻oiW]iծZҮGBV?xCB tJ d -!%tZL'O'KM?Jw6aCm8*>>OGKhNm -Q~7M( n& J]`j7 -klkqq6,܃Ҧe1MЉ*ёRNZUK؅ -|v$9;=f/3ѱXT|ɯ(aS3$y -ӁttdR! e5 0җ(YR屲4LbeX֩?Y%L qO9<_ [sEM/yTwpS/^dn =ݩ.5wrT}0ٸ]{ᨥ_@Aܗɰ͌#Di -$6@>tAɢMjg!}Z߸uZ7yc55S&3ac7 -W$u1g8])3gf){fj >V)= -gY4voaךKvu.܅+*1gVmv?w`ߡg71m <,|q,@ sj`4v1ǒQwT.%59'y}cOZ;WmvEwSdc ldfBN}VUXt|qpv{:yNpŭk/aU{W=~ykA(hTa%7w1\1')yx#%D8}u|8–3rjvˆ.OTD lh헚I*f(JlWޖlRc얙HLy0nA q#!IP( Ņ!ms46 AEG"v -]x.3)(,6X^nY,E`6ӜZ]?'_zk%7eO0o>Aᩯ/Z|;- U!1X6{G'`V:B= -*&̶;׎ly~؞l"lwivgFIzR)xQk+y@jJF}.f[WrX1`a|"sg@3AȹtY -(68, Ԍ -cj:AlKkyEob}OA9k夁Wvo}=}cG[^PQ_|69h&:xAԊo ځg2n -88%heR?&PR݊PT#WOp*1)q3JӜbeZ=T6#+ІAЋ0X M'ҁg("#yʀkOȕB)5?,{hg0g<}fzAAgog+N7ҟoSa8 -$ڽ5h"X4LpT 3Dg2VD;@v¯l{5 !b1mAXn ڱS_®3D\ecSݖf'osl`4j[7'u{ Pجg Rۡfnc3)j 9EnYYLD@|S,EuTpNTMZt!m ǔ\oj WJ\SfT.)=5cSYSv㲠'KY<3<u>W6!"r9zGyGU>w IX y %/`A+ |J?`kGn}smö/%@Z՞J>RghfzE:u1Nt%82RӱKXVLhM?xϻ% ;&v18w -Ϝ;˝.<GiN0{,9etҳxgG;I9i圔ƻgU%{FǾl i&F:ʙ=.6}X-S-qrf7ۇ).\3]%)I tW'%O[p,rZ'7%RHM"7Ժ[WO>]ػ|MV6lv}o~8^W@ UG5ԜT!~\ߧjޫ Tnˤ -m1-)(h?0Cɤj-G5N&@00,Wey7PОMVЮP-+;ԩ1c>y}> -.Wcʥ(\@4`M?b/y`d$}X.|ہb\M<-^qnQv@'3Jcsr -\>yw7ѿ'o4yQŢ1o2=G>Kչq^='л^` 9+.uVpCt)_6F?3\s/씿*si% -/^ǜ }XLjy>zO1ؗuV|>hzPsT3{aPw/- i_jBh1w;+\3YϷ@onG2 6[e -P\D{|@ϡW  -=`./]cƝ Z%nx,ۍ57|߼G֩Wdv7֏e3' .}l?D8k8X,]K͊SqD%Q1] P:djfsO_K;!pچoմr6KP=X#r -vx>u{c/~;SV2oQ"jƹb.t1Z1RwSƺº0 F7w ։0p/zv>BfQz! 發A,c z.cCBYƙ= ~ 'a7=zQ0O5T2}a'F=P}KGcهI4wWC"UF=u ѯFĚsIwEUCbs :!|"]KO G_㬧 &s_y;z@޳5"ppl -ݼ6; -Ljh fbl10qvӺ"ʢ&g/S瞤3Q:ck1\'*MD -hc?rC8sljeZ~rՈmm﬘ǹ[%fGlh_E;B zQ?L XY"Q|}LL圉[76w{v 91b qx 1o[phdO׏y&3#Ʒs< ܍1ǰ.efu Rcf [1ȋ&j򛬳w{{8N:&gg~\2Jl=wcSo1< OgqWl\|C涂#{>s}8w`V M G?k!u7njTu罠QhVA3>BFbN5iԦfbik;ieZ6US;FQ38k63&!*־ 9{\k{}-u - 4+:Zq 0ƊAD]4Γ<ӊpcЪA sj(`}SkFb~U||? |;j|C4cwc s -ٞz.b2VΣl#Yij|bs=&~9| h٧|eg1u`oK?F"by'oai=nMkx>'" 6{yʙ9E9xW_anYMxymcG ci1Oչo:uFKRh~8/@YvQVK}?y߽ܷ$/6>  GhNDI_SSE:,O\iO*Ʈjvb,kHsI8d]̳a j}Yו6421…+b[k\@DR`&I!Zsy-D&ۄzms,-#zykQ>iZ2G(8W/ZSOsM;9WI_;Qc Nwқ}Y}%cO x,LfE;YCңԯy"n! #JΏ;~nP~ǜKi37 v1{Qb>.Ҭ'?e,T1>i$XE֒*qC~@!R5d 4H#/1{:lG0WآmqF]BlSjks BѶp7C2VD[K.޼9ڿݻc#JPOd +=~}QkBbc?:$v9bH{vgPW| )#CH_Iq~q`YQr"Y#7 a\n5Yy)n'!v[k9XnPGx?oB5fWơvRsa c3O?I.>9L^I]n>rx+1Nj7*s^*h:{-=([b2mo$}jOV.]k%n:M &}DnSIr|H6Kk_Q}m5/c|(5oj]8ۙ9Byo=qq??"WgWU1(5N^G)|Nfmyı,1+1\{\|מƑ ?e"ssȴG6H_ xD~o,@ƧX3fc -UWX/49ctHI@3`7w1zxe c&ay] RL3frqj+w)SyǢ4iNgD{Eq%f@| 1Cu#Uqbtx!ʗ8FTٚ7q wiMBUkG||||||||||||||||||||||||||||||||oF< qbz’wU)H6Yo-3Юж4d̀0^ն8mm!mԌȠHdXxTEż1OT^HwQ.hdןn@c~1~Z{OCZԦݦӡQ0Pϑ֬9nM87$G^38e'OF^5dD6MLhB,F:WGc;ٻSxpې {K/TTp[), gț9$3(`Wnuz-+R)]c0 9лdA -||xBuTz׏j^k*7mjިϴ}?{$r҆1uq./V,'b"C(y吷Vei^Hఴ<.좴2(2lY=j.ҠSSy^t{6#3 &h3 endstream endobj 2808 0 obj <> endobj 2809 0 obj <> endobj 2806 0 obj <> endobj 2853 0 obj <> endobj 2854 0 obj <>stream -%!PS-Adobe-3.0 %%Creator: Adobe Illustrator(R) 16.0 %%AI8_CreatorVersion: 16.0.4 %%For: (Przemysaw Biecek) () %%Title: (eurostat_cheatsheet.ai) %%CreationDate: 13/03/2017 16:15 %%Canvassize: 16383 %%BoundingBox: 0 -107 1825 850 %%HiResBoundingBox: 0 -106.0059 1824.7012 850 %%DocumentProcessColors: Cyan Magenta Yellow Black %AI5_FileFormat 12.0 %AI12_BuildNumber: 691 %AI3_ColorUsage: Color %AI7_ImageSettings: 0 %%RGBProcessColor: 0 0 0 ([Pasery]) %AI3_Cropmarks: 0 0 1100 850 %AI3_TemplateBox: 549.5 424.5 549.5 424.5 %AI3_TileBox: 147 145.5 930 704.5 %AI3_DocumentPreview: None %AI5_ArtSize: 14400 14400 %AI5_RulerUnits: 1 %AI9_ColorModel: 1 %AI5_ArtFlags: 0 0 0 1 0 0 1 0 0 %AI5_TargetResolution: 800 %AI5_NumLayers: 1 %AI9_OpenToView: 21 406 1 1441 1069 18 0 0 -1 38 0 0 0 1 1 0 1 1 0 1 %AI5_OpenViewLayers: 7 %%PageOrigin:-128 -47 %AI7_GridSettings: 72 8 72 8 1 0 0.8 0.8 0.8 0.9 0.9 0.9 %AI9_Flatten: 1 %AI12_CMSettings: 00.MS %%EndComments endstream endobj 2855 0 obj <>stream -%%BoundingBox: 0 -107 1825 850 %%HiResBoundingBox: 0 -106.0059 1824.7012 850 %AI7_Thumbnail: 128 68 8 %%BeginData: 9426 Hex Bytes %0000330000660000990000CC0033000033330033660033990033CC0033FF %0066000066330066660066990066CC0066FF009900009933009966009999 %0099CC0099FF00CC0000CC3300CC6600CC9900CCCC00CCFF00FF3300FF66 %00FF9900FFCC3300003300333300663300993300CC3300FF333300333333 %3333663333993333CC3333FF3366003366333366663366993366CC3366FF %3399003399333399663399993399CC3399FF33CC0033CC3333CC6633CC99 %33CCCC33CCFF33FF0033FF3333FF6633FF9933FFCC33FFFF660000660033 %6600666600996600CC6600FF6633006633336633666633996633CC6633FF %6666006666336666666666996666CC6666FF669900669933669966669999 %6699CC6699FF66CC0066CC3366CC6666CC9966CCCC66CCFF66FF0066FF33 %66FF6666FF9966FFCC66FFFF9900009900339900669900999900CC9900FF %9933009933339933669933999933CC9933FF996600996633996666996699 %9966CC9966FF9999009999339999669999999999CC9999FF99CC0099CC33 %99CC6699CC9999CCCC99CCFF99FF0099FF3399FF6699FF9999FFCC99FFFF %CC0000CC0033CC0066CC0099CC00CCCC00FFCC3300CC3333CC3366CC3399 %CC33CCCC33FFCC6600CC6633CC6666CC6699CC66CCCC66FFCC9900CC9933 %CC9966CC9999CC99CCCC99FFCCCC00CCCC33CCCC66CCCC99CCCCCCCCCCFF %CCFF00CCFF33CCFF66CCFF99CCFFCCCCFFFFFF0033FF0066FF0099FF00CC %FF3300FF3333FF3366FF3399FF33CCFF33FFFF6600FF6633FF6666FF6699 %FF66CCFF66FFFF9900FF9933FF9966FF9999FF99CCFF99FFFFCC00FFCC33 %FFCC66FFCC99FFCCCCFFCCFFFFFF33FFFF66FFFF99FFFFCC110000001100 %000011111111220000002200000022222222440000004400000044444444 %550000005500000055555555770000007700000077777777880000008800 %000088888888AA000000AA000000AAAAAAAABB000000BB000000BBBBBBBB %DD000000DD000000DDDDDDDDEE000000EE000000EEEEEEEE0000000000FF %00FF0000FFFFFF0000FF00FFFFFF00FFFFFF %524C45FD82FFA9A9A9FD0FFFA9FD05FF7F7F5B7F5B7F5BA97FA985A97FA9 %85A9A9A97F7F5B7F5B7F5BA95B7F5B7F5B7F7FA97FA9A9A97FA985A97FA9 %7F7F5B7F5B7FA9FD35FFA9557F7FA97F7F7F857F857F7FA9857FA95B857F %857FAFFF5B31553155315B7FA97FA97F7F7FA97FA97F7F31553155315B85 %5B31553155317F85A97FA97F857F857F857F5B3155315531A9FD35FFA9A9 %7F85A9A97F857EA985A97EA95BA97EA985855485A9FFA8FFA9FFA9FFA9AF %A9FFA9AFA9AFA9AFA9FFA9FFA9FFA9FFA9FFA9A9A8A9A9A984A985A984A9 %A9A984FD0AA9FD34FFA9A9AFFD11FFA9FFA9FFFFFFFD047D7C7D527D767D %527D7D7D7C7D527D527D7C7D52FD08FFAF7FA985A985A97FA985857FFD3B %FF7F557F555B5585557F7F7F555B55857F55555B7F5B555B55FFFF7D2752 %27522752272751522727277D5252527D52522752A8FFA87D7DA87DA87D7E %7D7E7D7D537E537E53597DA87D7D7DA8FD37FFA9A9AFFFA9A9AFFFA9FFA9 %AFA9A9A9FFA9FFA9FFA9FFFFFFA77D7DA87D7DA8A87DA87DA87DA8FD0BFF %A9527D527D7D52527C527D527D5252527D5252527D527D7DFD37FF7F547F %5B7F7E7F5B7F5A7F7F85307F7F7F547F7FAFFFFFA9A87DA8FD077DA87DFF %7D7D7DFD09FF7D52527DFD07527D5252527D5252277D527D52A8FD37FFA9 %FFA9FFA9FFA9FFA9FFA9FFA9AFA9AFA9AFA9FFA9FFFFFFA8FFA8A8A87D27 %527DA87D52A87D7DA87DFF7DA8A87D76A8FFAF527D7DA87D7D527D525252 %7D527D527D5252527D527D7EFD35FF853155315B317F5B7F7F7F5B857F85 %5BFD047F5B315531AFFFFFA8FFFFFFA8A87DFFFFFFA8FFA8FFFFFFA8FFA8 %FFA8A8A8FFA852527D5252527D277D5252277DFD09527EFD35FF857F7F7F %5B85A9FFA9FFA9FFAFFFFFFFA9FFFFFF7F857F7FA9FFA852527D275252A8 %A8FD07FFA8FD08FFA8527D527D527DFD04527DFD06A8FFA8FFA8A8A9FD36 %FFA87D7DA8FD047D52FD047DA8FD047D53A77DA8A8FFA9FD047DA87D7DA8 %7D527DA87D527D52277DA852A8FFFFA9FFA87D527D7D5252527DA87DFD0D %FFA9FD36FF527D7D7D52527D52527DFD05527D52527D5252FD04FFA87DA8 %7DA8527D7D7D52A87D7DA87D7DA8FD08FF7D527D7D277D7DFD46FFA85252 %7D5252527DA8FFA8FFFD05A8FFA8FFA8A8AFFFA9FF27FD0452FD047DA8A8 %FD0BFFAFFFA9A87DA8A8A87DA8A8FFA8FFA8FFFD06A8FD04FFAFFD35FFA9 %2752272727FD06527D7DA87DA87DA87DA8FD05FF52527D277D7D52525227 %7DA8FFFF7D7DFFA8FF7DA87DA8AFFFFD047DA8FD06527D527D527D7DA87D %FD3AFFA87DFD045227525252275227527DFD06A8FFA9FFA9A8FD077DA87D %A87DA8A8FF7DA87DA8A8A87D7D7EFFFFA8527D277D7DA8527D52FD047DFF %A8FFA8FFA8FFA8A9A9FD3BFFAF7FA985A98585A9A97FFD09FFA8FFA8527D %7D52FD13FFA8FD047DFF7DA87DA87DA87DA87DA8A8A852FD047DFD36FFA8 %A8A8FFA8FFA8A984A9A8A984A9A8A8A8FFA8FFA8FFA9FFA9FFA8FFCFFD0F %FFA8FFFFFFA8FFA87D52A8A8FF7D7D7DA87DA87D7D52FD047DFD05FFA9FD %36FF527D5252527D275252A85152527C517DFD0552FFFFFFA8A87DFFA8CF %CFFD13FFA1A8A8FFFF7D527D527DA85252FD05A8FD3BFF7E272752FD0A7D %527D52FD057DA8FFA8FFFFFFA8FFFFCFFD04FFA8FD07FFA8FFFFFFA8FFA8 %FFA8FFFD06A87DFD04A8FFA8FFA8FFA8FFA8FFA9FD36FFA8A8A8FD15FFA8 %FD05FFCFFD12FFA9527D7D7D5252527D52A8527D7D7D527D7D7D527D7D7D %AFFD36FFA852277D27522727277D527D7DA87D7DA8A8527D7DFFAFFFA8FF %A8A8A8AFFFAFA7FFFFFFAFFD07FFA8AFA8FFA8FFA8A1A8A87DA8527DA8A8 %A87DA8A87D7DA8A87DA87D7D7DA8FD36FFA8527D527D527DFD07A8FFA8FF %A8FFA8FD05FFA8FFA8FFA8AEA8A883AFAFAFAEFD07FFCAA87DFFFFFFA8A8 %7DA8FFA87DA8A8FFFD04A87DA87D7DA8FFA8A8A8FD36FFA8527DA8A8FFA8 %FFFFFFA8FFA8FFA87DA8FF7D7DA8FFA9FFA97DA8FFA8FFA8FFCACAA8AEA8 %AFA8FFFFFFA8FFA8FF527DA8FFA8FD047DFF7D7D7DA8A8A87D7D527D7D7D %52A8A87D7D84FD37FF7DFD05FF7DA87DA87DA87DA87DA8A87D7DFD05FF7D %A8A8FD05FFCFFFCACFA8AEAEFD05FFAFA8A8FFFFFF7DA87DA8FFA87DA8A8 %A87DA87D7D52A87D7D7DFF7DA77DFD36FFA87DA8A87D7D7DA87DA8FD057D %A87D7D7DA8A8FFA9FFA9FD04A8CBA9CBCBFFCBFFCAFFA8AEA7AEA8FFA8FF %7EA8A8FFA8A87DA87DFFA8A1FD04A8A7A87D7DA8A87DA8A87D7DA8FD37FF %FD0AA87DA8A8A87DA8A8A87DFD05FFA8FFA8FFFFFFCBFFCBFFCBCBCAFFFF %FFAEAEAEFFFFCBA8FFFFFFFD04A8FFFFA8FFA8FFFD05A8FFA8A8A8FFA8A8 %A8FD36FFA9FD05FF7F857F857FA97FA97F85A9FD05FFA9FFA8FFA8A8A8FF %FFFFCFFFFFFFA9CBA2CACAFFFFFFA8FFFFFFA8FFA9FD06FF857FA9A9A97F %7F7FA9A9FD07FFA9FD36FF7D7DA87D7D7E7E7D7D7E7DA8597E53A8A87D7D %A87DFFFFFFA8A87DFD04AFFD07FFCBCBCACBCBFD07FF7DA87DA87DA87E7E %7D7E7D7D537E537D7DA8A87D7DA8A8FD36FFA87D277D275252527D7C5252 %7CFD04527D5252527DA8FFA8FFFFFFA8FFAFAFA9AFA9FFA9FFAFFFA9FFCA %FFA8FFFFFFA8FFA8FD06527D52522752527D2752525227522727277EFD36 %FFA97D7D5252527D527D527D527D527D527D5252527D52FFFFFFA8FFA8FD %05FFAFFFAFAFA9AFAFAFA9AFFD05FFAFFFA8FD05527D527D527D7D525252 %277D52A8A8FFA8A8A8FD36FFA852527D5252527D527DFD05527D52527D7D %527DA8FFA8CFFFFFA87DA8FFA8A87DFFA8FFA8A8A8AFA8A87DFFFFFFA8FF %A8A87DA87DA87DFD04A8FFFD06A8FD06FFA8FD36FF527D5252527D527D52 %7D7D7D52A8527D52FD047DFFFFFFA8FFFFFFA8FFFFFFA8FFA8A8FFFFA8FF %FFFFA8FD04FFAFFFFFFD047D277D7DA8FD06FFA8FD05FFA8FD38FFA97D52 %7D527DFD045227FD04527D527D527D5252A8FFA97D527D7D7D52A8A8FFFF %FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8522727F8522752277D7DF8527D7D %52275227522752F87DFD37FF527D527D525227527DFFA8FFA8A8A8FFA8FF %A8FFA8FFFFFF527D27522752527D7D7DA8FF527D527D7DFD07FFAFFF7D52 %7D7D7D527D7D527D52FF52527D7DA8FFA8FD3AFFFD06A87D7D52FD05A8FF %FFA8FFA8A8A8FFA8FFA9522752277D2727527D27527D525227277DA8FD05 %FFA9FFFFA827FD06522752277DFD04527D52FD047DFFAFFD35FFA8275227 %527D7D7DA87DA8527D7DFF7D7D527D7DA87DA8FFFFA8527D7D7D527DFFFD %047DA8A87D7D52A8FD0AFF7DFD0752277D527D527D5252527D2752A8FD36 %FFA8A8A87D7DFFFFA8A8FFA8FFA8FFA8A8A8FD07FFA9FF2727F827525227 %52277D2727527DFD04A87D7D527D7DFFFFFFA8A852A8527D7D52527D7D52 %527D7D7D52A87D7D52A8FD36FFA97DFFFFA87DFFA8FFFF7DA87D7DFF52A8 %FD0AFFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8FFA8A8A8A9AFFF7D52FD %057DA87D7D7DA87D7D527D7DFD3CFFA87D7DFF7DA8FFFFA8FF7DA87D7DA8 %7D7DFD05FFA9FFA9FFFFA852FD057DA8FD0FFFA8FFA8A87DA8A8A87DA87D %A87DA8A8A87DFD04A8FFA8A8A8FD36FF7DFFFFA8A8FD04FFFD04A8FF7DA8 %FD0AFFA87D7DA8A8A87DA8FFFFCAFFFFFFA8FFA8FFA8FD07FF7D7D527D7D %527D7D527D7DA87DA8FD06FFA8FD36FFA87D7DFF7D7DFFFFA8FF7DFF527D %A87D7DFD05FFA9FFA9FD07FF7BA57AA7A8AEA8FFFFFFA8FFFFFFA8FFA9FF %A8FFFFFD057D527D7D7D52FD0AFFA9A8FD36FF7DA8FFA8A8FFA8FFFFFD04 %A8FF7DA8FD06FFAFFFFFA87DFD04FFA57A7A7C3B181984FD0AFFA9FD08FF %CFCFCFFD0BFFA8FD36FFA8FFA8FFA8FFFFFFA9A97EA97EA9FFFFA8FD05FF %A9FFA9FFA8A8A8FFFFFF7A7B7A82123B1284FD08FFA8FFA8FFA8FD05FFA7 %CFA8A8A8FFA8FFFD07A8AFA8FD36FFA8FFA8FFA8FFCFA95A857E857FFFA8 %FFA8FFA8FFA8FD05FFA8FD04FFA57A9F823B181984FD0AFFAFFD06FFA8CF %A8FFA8CFFFFFFFA84B7D527D52A8A8FD36FFA85252522752525227527C7C %7D525252277D5252277DA8FFA9FFCFA8A8FFFFFF7A7B7A82123B1284FD08 %FFA9FFA8FFA8FFFFFFFD04A8A7A8A8FFA8FFC99AA8A8A8FFFFFFA9FD36FF %527D7DA852A8FD047D527D527D7D527DA87DA87DFFFFFFA8A8A8FD04FFA5 %7A9F823B123B84FD09FFAFFD04FFCFCFFFA8CFA8CFA7FD04FFCFA1A87DA8 %FFFFA8FD36FFA97DA8FD13FFA9FFFF7DA8FFA8CAA1CA7B7B7A82123B128A %FFFFFFCB9CBF9CCBAFFF7EA8FFFFA7CFFFCFA1CAA7A8A8FFFFFFA8A77DA8 %A8FFFFA8A8FD35FFA8FD087D527DA8FD0DFFA8FFFFC3BCBCC3A57AA5823B %183B84FFFFFFCBBF9DC5CBFFFFA97DFFA8CFA8FFA7CAA7A1CAFD05FFA8FF %A8FFFFFFA8FD36FF7E52275252FD05A87DFFFFFFA8FFA8FFA8FFFFFFA9FF %A9FFAFCA9ABC9AC37B7B7A82193B128AFFFFFFCB9CBF9CCBAFFFA8FFA8FF %FD04A8A7A8A1FD05FFFD05A8FFFFA9A8FD36FFA8FFA8A8A8FF7DFD05FF7D %A87D7DA87D7DFFFFFFAFFFFFA87DC3BCBCC2A57A9F7C3B181983FFFFFFCB %BF9DBFA8FFFFA9FD04FFA8AFA8C9A1CAA8FD04FFAF7EA87DA8FFFFA8FD36 %FFA87D7D7D52A87D52A8FFFF7D527D7D7D52FF527DA8FFA9FFA9FFFFFF9A %BCBCC37A7B7A82123B1260A9AF85A99CBF9CCBA8FFA8FFFFCAA1A8A8A8A0 %A8A1A7A8FFCFFF84597D7DA8FFFFA9A8FD36FFA1A87DA8A8A87DA87DA87D %A8A8FFA8A8FFA8A8FD07FFA8C3BCC2C3A57A9F823B183B3B3D151B7FC59D %BFCBFFFFFFA8FFA8A1A1FFCACAA1C9A1CFA8CFA8FFA8FD05FFA8FD36FFA8 %7D7D7D52A87D7DA8FFA87D527DA8A852FF7D7DFFFFA9FFA9FFFFA89AC2BC %C37A7B7A82123B123C153D157FBEBF9DCBAFFFA8FFA8CAA1CAA8FFA8CAA1 %A7A8A87DA8FD08FFA9FD35FFA97CA87D7DA8A852FFFFFFA87D52A87D7DFF %7D7DFD07FFA8CAA1CAA8A87DA7A8A8838484A97E8BA8CBA2CBA8FFAFFFFF %FFA8FFA8FFFD04A8CAA8FFA8CAFD07FFA8FD36FFA8A8A7A87DFFA8A8A8FF %FFFFA8A7A8A87DFF7DA8FFFFA9FFA9FD04FFA8A8FFFFA8A8FFFFA8CAFFCA %A8CAFFA8A8CFFFA9FFA8FD07FF7D52A8FFA8FFCAFD08FFA8A8FD68FFA8FF %A8FFA8FFA8FFA8FFA8FFA8FFA8FFA9FFAFFFFFFFA9FD35FFA8527D53FD08 %7DA8527DFD1CFFAFFFA9FFA9FFAFFFA9FFA9FFA8FFA9FFA8FFA9FFA8FFA9 %FF7D7D7D53527D5253A8FD34FF7DFD04527DFD09527D527D7DA8527D7D7D %52A8527D7DA8A8A77D7D52FD087DA8FD18FFA8FFA8A8A8FFA8FD36FFFD0E %A87DA8A8FFFD04A87DFD06A8FFA8A87DA8A8A87DA8A8A87DA8A8FDFCFFFD %FCFFFDFCFFFDFCFFFD62FFFF %%EndData endstream endobj 2856 0 obj <>stream -%AI12_CompressedDataxir*I0 BPZQKna@hFq ej_]v[MYK'\.)0%1^^R?|LG^᛿H-'[jM)/zNL.~E{;G1#[ؚϾvj7>QQQgHG; FtX/I +bgCP - <4,~5"Ē89쓫Hh$Z#@,$#@"Q4ƬqcNQk!@Dzy/Ia=\(d(pKM%z$f[n)G pE\Gn`1Š>@qk8ÅLvHQ%H=FHOr3]5u4[`@[YOJ -~ u! XR3=77K8S;r Zd,8?H`a2'id,q4&'V~Gvs`7@\1] y@I%H2WI9`<5o R ,R"X=@-=;!f3N@I28nw$ؒcw~$w AC -lJ49 s@=uP@Lxt5`loVy5_ _:qRd -z& @Y?{r 9\ɿKb>| ^ߚ1:oI(Lw77p 1&f2 -,Tt)H?QMMq2c'OӔ&WI -o 5g N`,{ CM l43A%XhEpF\!M!f` P[76@nN,'4ƽBi&18Ad"gՂ'A`B̊'Ab^E2,g7PK& {VeA_ȣ ɇ` -:rQgj44SbrJUorbmѿԟ$sJh̃ƭ*h<oܿo)υןvƿE{e6i'7YkןkҺ"3hA! 4b 9#=2}YKooEٽ`{_noӟVZ>0E PGZښXzg LI<G@gx,}69x$:(7*K Me"E ;Q/6`8p`o8d𿞔%b9 8]nD0}j$Ab?߶ 0muZc?h#nh@7M}k䚁 Y @)!vAo@z;$)X9XVn c{|/J G)$c@-y?q -I#;=aQ0g5LJ-]h0ʎ\AJ?AW41MH} --sc琵Agd/pC`R}8'/#a!|pqz#ed0q$#S!O%F.cQ62F@2"Ƌ + N ϚΌAһr>[#(QQa`4Ř\._ƶ޿mA,w}bfdd}D+r kƌ i ,?v6 Q Z6@ѳ C- ~#,h饑#vAG1,:*s2<';>;֚ -N@.޿5B!5e z~܈UdC!; c[98yTSdztV䎀6~$O&#$fyG'[@"LnHؔgw.tăXpfI%h45ƿYz>!.(u -]x&B%}ˠF]P93zz ƶ@FAO/EsvF;;vڀa4_wٔjDº|I6_R&@>}_rH'P4vc`áxK)hc(r{CyĢpT.2_hdŴ,IvXy 7&N$dȚg轳#x&deQ8Jt~\։]( rV* xbA,?IW'U/%p(TAKsTNSPHJws+O_;^-a9t˥4zyN0ѠahjYp\K *k -U{ -h !{uv\T /WkmW(F^Šjm ˛rt>Y)v3Rl2 RQ.,6}}UL-D簽/O?e~v+.!Uy~ity[tSnL?}Ykdoq$]qew"t_ywOo|Ƚ'xcJ~{+ǂD_~惛Iq9}_h~`W∥?ع^ߦ<n=nE -[olq' -cԼ$.,.3#_jdO_2xٳ5f'oͮ`@٘-_C:e wϲ㤅r\UmWb -8E#>{ )Ti2%_i,j}Ƽl*fl;Oיnf0h]XPu݅@dCD2Ebq_O >q#υv4,ͿctUKSǻJvӬݓ&C m# (KtwQCQVDn"iTHNTcu★>32V}χ d>32[\I)+Xn"}mJ`,b:ݴj 8&ݤ?i3P2אra:"%GlMU]uo+P8 5L2BCK6?t Г|:壤Z%$ %пx&BRW{OTBX=],r5>0.0Z)GŘN?rs)~&rH_ϗo`SQw?VN൏bb-к*aG1*OSWlC&52ޝ\hPwm즆gZMW%[a( _7p!Zy1<_ֳ4zZ%p_'k: naAo `!|! _;GPӬB,=zz}CJ9X}E-ai s/S-ӡK3Xada/7RC X>A딃oߡxSy؛@J~ox3ه`Yfע*0 !9Sc SL*ߩ.}QI@@6-W5cCi[9As;H55H;[,Ob񤔩?FSkws-(=4KPMhTMs"6 -t?G~xZ鋛zEzo[ݶ/8p>3Oޫԗ7c!Go"|7SQl,K; o(Vbm DԴ4cT~JS{ݜ\"U/]OInMʓU19\=lـ tMW$Kz'X\8h܎C28@gOq-w@.JYe|K}P ' \<A{4I*2b+ q7v lgrWjV>> -ά{5G#^\Z0:Xn<"3=uI:_]CKy -U\&.}%87'1s,G$/ޗ0m ncnIbV[~ k2luE45w.P-=J"@7Akr^[nW|+4c/ՏjqBoFp} l{bϵ]1' ]moqIC1,A% -sٌŮ?Lyي -.0V>2 -;. JkSMv TO7E_W'P'?&wi3Xy%wW2&igKj{d»KyХ\C[^J,\*BϱPtUe$p11&a;~| -/骫1y;e23+בa˝'վ mAvnd7v,rN4 J|~l{e"B߼cA jh.ue] -zbb9 mK@bo&& R0+OVUjL="_PzXɕ -GA.ưR%DȻ^߼ވlGq_P]gE7fha,$mݍͧ|]%5)G4k׽F(w=aZ:\c@GƖRH p_uKj&SW+0[9bܘj}!1D&{<= -KO$PSz)O9(zϾ {j~XOTWx j~"JH0Sx$Bϗ2eY/?p1Zb2=>|<&,J_o c]3A\kU⪒O<3~B1 `qBw}U0ߺ/`to/nT*y5+]gEƷDz? -u|ԿK>@"^=IRƟO@m0x$+ۈrXEg_̃Y,$| \ ҝֿqݬ DHҩ `ȷ4D}oGP8C0;ZWnޥ8oy|ݸnv|Z$fS/7qey45] R||;(._"FVPPlJZGMK_Xd& ݿ۫f1Q(%ypA3a(ҋǀf~C}\5*hG4璪߾:gT?]!( -:OeҍvK=?X*$Vc 6n xgc)>$݉M[oȝdu2PyLΞhг:x{f=ݲMreTwhrB[KuIx{JF󦨮Qa=`>7ý=v7KUvjo%t)߅ LuCMƿ7o][u/ o][^0{Y@mmq?x -|M~[ɯE'h.Z޺܏77{7;7VE6}oon]PcO&ƿ2ork2pXWjhpHɘovEvJ}lHas*`oG'`F5!qv kFPWqqIG"|:2dBQЮP 7jNWpë!5Ev,R5٧+4p@ۭ9\PYkU(;KIA*2E@<Dj9 M2 ̩EDZn g S1JQ R1=KHTk4KqsD%}KNPHe -6V@ -#R_=lIt2=_E -IT, eLvu/ pcZOPavcr>).ۡN@5j`juh -hWVZJA۬l2T7qaSZ{Ӹ -+5@&uŴhR .`ʴb`% -d|<x!aY2,:75 -&咐杄9x#4T]mb E0- GCkCH/!<7lшp&nL0Xsptֳ|"퐨 EWp3[-#HA++]~Kr$^BTï3ee`aC_cF-fkÝ d+<J,$;M*NtfB8_%>OA͡7Xns6$-O`6E]BʵB B{>`kU89PN2MQ4?B'h J{+nG칌Z-"@#2NךxIhjCQb %0!cքC$@#p -x|?*P@-^@XgMcaP[xז.c܎7K3^oDCyZ}:p}G֋\ÓT0›> q.gT F,xQR(rU" 3E. Qk 0I{#4NrG 0L7IaEPz,UCr~ɣRap1*@cIYk(Kp/ZY_D`w B5)*_dHy @r^9M g -k׆fM%̑ Zڌ5 -j8pl6hEAVT ~=`MHp c;z͝[P#(`ayM@/`}"G݉{jw?B: -8u"Oɕ00܂a~ƫ_}lq%*.ٙE.;$=%¹[[\z6D\ s53 dQ -#/6Mr.zm{MOgS`΋/,xPlޢp"[jPRxՇd]~<{B=wXBSs^bmhq^'zGN1NF}$f NngݩO$ 9!: lA-HNNyz`T}sf4ڼ]f|J~O 8Jfu$qg6H##[tF&~ȕ|:_$% {4bN&j᧴} -֖bzJ;m,dCHk{SBjqb]@+C }CtD'ewEal! >Րֳ2҈ٛoZۋ "!Ūf^i~*H_XuzCHf\7þ"Z=W%o5DH*R0/O>ۂh݇z -q7@8vNht5  -D:?}y"^HϮR$eؕ~W+Mgl[UFz_rg.W-%2EHw!knٿƕF^ްj3QDzQ]% )°5Q!p~u&kjHIvoUXE\7rqֆa%CY *AZd"HGc/~b.k*me0RC:6-|mw"m"͈ ) }`FϭtjoqEnOѡJc}k`gVi+|trHW2 JՐαW@]=.E Euy= 2Ҷb2) {g٥e *#l4], RдCy@Df Ц~ZiYGg_ișuեMQ -DCHyj?hoi~+'pnHw9̼9!#4]FU*U6 +n銿ս\^O ː^ozZ-hDAnm vc; c769yi[gu]BT-/=&O*E.(vBQLJ].f㬴=PsSݥUV} -(}p՟\g)P90٬xO?L4(w0JkP,umWR{:O/o Hl!(vܛ ʪo{3nUt#mć\.^8ݮ5CuKoz圷OmW{AT}~N5(@v-E9C{p~=rkJ&}r^wl4k;Q ;ۋok'~ޣpcQB -A -WEU1ϭR䍃p'u6B])p7au5냄cٝQ`!-H36iw)&o'!\]R:W%H_nWm4PGzQ%ϣe b1;>U X ]Ɣ*HcB i!9YF:RHY>g_2\ }zRU8CD/`V0",K׉M/gRș,aJ_'dP_uiDEj{|*0@A9+=ƅe߳@zyq.(=&pפz۠i IJu"S#Vp8q#r/r`n)YTjvɎp<glK -9WJt\bra|NF# _-ET͟B6⌢0yP>ktđ b7hXMYlcœ^c+ۚ(7YxLC<2-ގ%LT޳ .8ώlh sʇv74z3;fsJJ[E*#J5ph ДRgh?WH*oxUyξW~a@75  -C _?]־2MSQ"HWtls}$+&oTBޅVc2#.j^U&_acr7 -CX(Ys2BBџ8}U zCg[aې __??%(&8*ʇpO{+H -,qjr=}H,`vQ)BV0.]ˬOա> rt?27CG٘ zƂMYI1| b(ƚe|묎MDE5*C\s:jzlvrVFH.wi2P8* cKp]huE#:+tDշ]GuTn(6ʮ`(u*Yl%#]eZ c;E#Okpn(5 ! `NxxXKJ -@TSQ2!Q`<;!#Es/@ 쒏:M3Tbr;VD+ 3qUf:Y&V&fg F*G—)ץRoХ悊dU5F7}jGfY-aq'8!QJey0́C\&2NChdlT$ u2We7M3@ŕvyѧݦ&m3ԽGH=aNMSjdeN=8Sšku$7y*> '&vŃ#f0lЩq!_.VIo3I;9B;)Z;TjkD^ [ac׻us"SwFFN"])kG_Za9y"{Ҩ7&]TkJiq𷀶*N[`c憍+ac=C(_S%eo-#ڼPMHj4TIy̔F.F5e+W:TqFCZ# P{7 YCbt+>3&GZ1؎oʊvZP/vy-[P5` -d(&~kl`;-yJCZa3L%+➉ A 2%tQ -΋}HE>*YtjYp% -.WKM1!63_ポpY]MYm$`mϓ!<)k;S2j$%%ZUe3^QWoΓ!m L ]p.6"Pq1Ꞿ#+d]Rŋ\V,DZGȰr4κy僻bBGЉ'Q]q:fCk+稡SB*Tб>5tt̉:)!*: -:SkUЩT ӆR,z3RIʦsEI "cExt~ۇeg*S#4Z9gt|R seJ]mSX1Lt̕,t쪼ݠO *8[ip3BXW?m bH}hHA4;!u42F3TՋo'a*'7i[<+q"^LnH=TW-C -]2PbT)2~$ę, 1HL60{N^$`T"pu`2:>)Iu|IȺ.]t7V\wɮ%aӮf0Uf0X']PAR&>)ɰ1SL  *fRy/Ir.#)> ;.׫] j9u]N~AgK7^]5]޳+VW: ("Иiղ0B9$guRFY(fu#GONWT4okH==9#:av]܏T3S~S':bRznc;C3% md )A#$ٟ k̥wLWƉ t)g3]JiLed4$?S:edd}QF&|\3ye⤴*lEs˾Wrs.Sdq ,C'8O|FF"Ay3$Lhqw޸fS9*Oס:i8^4?I'j4O97LjSӇeO(Խ  f`ݺ:YP&L]W a ŀd] -=3r^p$QE=uc&Twt+RRU Z ]-;J3UaN3áy9;w={YuJ[/vܞH%kO -OGʀnqTw'vN>ւiEmϹN\j% lG2g:NN2esX~Pu114Ыe:qkQM ٬cqHoa7d1DBxtʴcRS@a1eW c(/T8x]i\8OT:H/DqEĀϤ[J\n݅3U>"LOgH}:H_v8ac%9dbp 4z6`Fw۞bbv{R8.oR8pY±wrpCtzmO~"<Ԗf̯ب hLO,C*ZK2rΙ@J˫_499j 8EvۙͿ|_`J ؼ76_[K~:dsJ0z;I+"TR-sqZu+>~1Hz3ٽ -Ҙ^v]ܫFUa7"j+&ZXŞ ^5#*"UvX5)!B3 -mDi(+]_jJH -;z8f?}ɬI=N:Y)/WkcA幭 B|':d(qiXݫߒ$r|ԃUX#z+ޤyUYK=V$uu\x+?: ^4lU p]N @wUwwv.:r*-Әjmzש֑Kڵ P;'pXfHrpw7n;spV܎v=򎎥e7婋I7ܩrfkC7{9~8CO=};[ajTm#ϧW>PX ZesŴc&V΍3^X Z<\};.O}!}/کb}H!M3e1^~Sh]I\7z(by9*ؘfn1#);O\ fo"TQ\F,F;u?o5 _W ]"/[1[Z|^hoոwm=J|hl}ɬQE{㴛 R<Hwu|d;uWa;u[[=$˔lfGEzg '}_O9bE5(!{OZz X1yG]0fw,#5 )c_xc)UvvcWEj{ XWYG's?цCٶFZh_ Brɉ.x璙NUv djj%8y;=-C?j귘KƘKtnziѭU.t7$:uwBjɩpUU`^46ejo,q3zK5VSSDC6sDW>-i7ZΔc~_V& 4nkUghjg٘ɏ6G$wVFwuo;,˵*@*J@b)-ܥ1z%7_3{xV\U2ZmH3ՓBܩ3*͞<$ͩx7LjSF:#BW,9/8 K8tO; wKkFy)TR>Ƶn - uʽ~zgC^ yɳOVc))망ROi@8JzvLĽ~vMR]V?SwJw++TpW*g6oyܽ~ru;{ܡj^?3q!N>^?mC'ǎhUi +J)]S0w p wU}|J~;蒤)ShL6}~o2ҽϫyl%{a3]vѭ~ھ{N}Ci}|=Z X'kExKS{"?^?sBs~UiC[{zwZr߉\S>SO`;Ͻ~/}v;D#{c> z5Xtv.s]k>YOA=W -ãy9ý~ڻsՄX4XnƪJwV^حgzig sE{4/책`K)7*cEaÿ>=]! 4}wGRW zڽm4n%ledcNC'ٱ?k:X -Ew^*qѿjǙϐ1/_Y'+xL -6zt]+=_&me^r$M2↚?|}޺GM#],Ū*VSzxJR"5{~tSX|;e;#%d7TLVR(QQ,}]Cx}z.L^y $4D%z(k\kwy>Ǿ7xeʔDǂmr]/~^'>,Hq Bw7{N.;1C,`@At׼%}S2oMl:閍tj֟#zTrG>|?̮LܹTR ֺ _" 06)aZx жǂ<KaEYCk "Y@r4ir>E|}jEzeG^ ‚/-?fcr\fkC5S| \Ī8g%|r+ .E^ș(so,}2QdܘE`TxMQC;/D8,ڈ+}5 -1C>j5Θh&!0W#"}DP.E? > p쏀ʲYL¢[x$y`DzXŐ DX]\& V(~6YWL5=xcUv yDܧIHcza3$DwU;?/n$6ԼQ0W1o^h>cv u);%a7T+uD|j_7/E1h B /F=t6,Ж :H'ЖʺM~:4 ,n: `e*Ru[g.d澔Y'Wn¹ǻ&`E`?{ *ҁ@±4F?K$T|}ȱmaKtԄQO ˬ ZF\ /e../U\.TqC֗6|yE좽 O2_D`c KzkA\@&WDφXBC᫧f ZIzS[5%^ -}Vw  QW 8;_^ڨPt4^ 'ʹQ2ex*'|Ej{E @ >nۀG,_zLW͎1دP%ђ*n*2,_րOef^p߬M\ - Ea) }5ky4^q3"wwT [EGFr2txޝHU=  ǛkԽ7p_}xѯ ހ:w2,L&Pa r=3 `wv.y g]NY;+Ajh0U'/*2)0R03>&,4K@>W᭱ atc2vKR&Ҽ GĄЄYfeֿMΡ8 W=w~Wџ!>ڼ47uGcӺM#T`93}aZ{chGńds؛!cꏝä `vr>e5)8<DzQ @7:9Gcnf׀NRadÓ3QJzHd'uQp91#9AdA߷d_`&?Ɂ,Ql׵'59Zswceav7NK%jE|ɩq<\109qjO`Qe -Ҫ#]x KUr#'Gn^q#q09oiɑ7}ڊU}lvϐxվo|#&c#h~`40,*I39;O1n#mpyLűˠ]\y`$ _2?;jnZ8ӵ/swQ|~G >ta޷蓞XK6IHF7ྷQ4Tks84,m:\RK - p2H+3apᾇ΃ [TA`EXH٨"7J1g d sS(ɌsP׾~ؕbSd^ҸB6t8p++CR<)w߽x߇8Sph1+F){@[V*<4Po9o įa 19h) @=٘ E`I#XA@!Z *.s@|E@ATW@Z12/6Ҏpa^DN/_²'{RSJ`!`sJS!Ź.Q8Ø4=W!8Rf!0 ~Z$4w!Z B p(8,CLʕݖ -Rm:!?1.F,.03f"m.wi'r<@Q3Ǧ|(xCڜ/ ǹmNO;d|  v_{|>_>W77n7KVA \};+荻&zKNi&f$0f$H)f\U(7 m"*ptc+hSdPZ7q7El:Ν>=ѝNj|݅V5 -P|Jlt| VLh3\,|L`&v&dHzܟq @SM>7t=n_T5T~meVt` M}F<ƶ[Tb 0ߚ/YPTu+ խB$ Kϻ״!a<=$ٔ`d\;τ,dS/a*3a0e܄yJ9av5@~;?+I!x1ai'bTPyvx Q%t7rMc7,e`&8VK\&E۪A?fK2&w -TpqB|ͳEZhK3Jˆ'&5wD~ތ8z`50agwg4ah¦.8Es0L-\T:72(PuFfT}8297lց#u>UL OYWE\3][]Jx~#bnQpe+ U`WMcST.>&g -uXf1,E049(5A:ҀٸsXSء MA]{f -(ᣙYܹoJE,C倭 J`y) -Wh!c( -y[X eMHJkD:u"*_6C!WF7o#HVmuRu<4\ej]M;V WP'7lyXGhUof{2 sJh6]`9X2!@ Uw1>7Aٻέde>J9gI?ŜE}[U=9uTw 8~tSQlN("B]}xs `񼔷xV zg/W92Y\6"lRIPk,U"Vƥaj|}nA_-K,wϟa.scoԒ[X괺')J(f_,6YZP0|i$`ݜ:Đߨm}.@ɵxm[[Mݭ|:ׄu)Gj_fv(%PO XxOVIYiϠ OR D Ο=d(s-$"[eɫՉ4Lb~Z&$gՎ%ru"^`Ū*o|[uJ 1]U`B*Ut˅t(l0n.Vq+^7{0T#dgKKJZŅC(`E)Ŧ$4+tYS|ɇAlA?`Ϻc .БRs"~b6VZrSz˘,M#;ubܗnX9VcV hblL@hfvnV>$&Aq$Eg: , ZpMm+af18o\b̅͟v=Yk^+ނliGH-n!ѷn z0*/~Xb"fDcVBZ5%! [bob6&>ck)}<(b<4,AmAFff%jWx=٩oq&Uת/GO*gEk,VWq -lT: ""j\+e-zSjhWʫYˈпT -o:(qSj=#bo6sFy$QD6>ZUNbte|Δ!x^ Gs? -Mpzvf׽OAE%УïGUs<+QWAna{= Roۥ:˳Yft8|Gꐜ'cggσX*Ok w_9@V3Lst@:yq.eLz2˿W>YԿq98J)'#7\e,{2V );>Bw3#zlSW'>Uʍj/D'@JW0\/ln\ϨN\o{R+^=:Wl\ m}Hȅ݂3#ߓ@Z=.e]3L^xs3y=FA:|9m,>rE0;afՋ/Maf51˰.:0{?QZ Dvx~W -Zѵ{/Z6˜ -V$~m #T rBeX<\0w/,?sYG'p?SM7zse/^^tj &e} IoM~㕚ڲBvA@@ܧn p|:xc>hW]vf^P<w>-?nML5uOVСPC@K>CaJĺc ]e{g=ilm:߻9vw<.ʑ@X~|.%4ٗmUXIkμwdTg2I'l|i`%/{ 8k#'A8pN\5('QOΗ\5[suPY*_\ -E~N690 ̧}kg ì@u_`}KZ-"~mBHַ׆Ҷzc[=Zkͥȶl%ck͵qzso`\۴W偀7r&FNR<8T*=h&r-3][oFjM?KldZ4˺ٕFȈR}ϱ+r-zM‰k,}T~p /IG'YwiƊmH ̓ - bއ2W,|HgO; ]eSV{1o)H)(n) 8WLNF+}}h3cl -@ْўx 4/oA}fU$̊$o ̢#mI,xB+ ÞcَC@+7EkKPu-B۾Ë́_K*A߳kE׻/n@3 (ZX 1w\ſP7po[ʅ2"|聺kQ!=I߫ \ƖUh1XTD֐󐩀gyLJ6UBܶuXHf $c!qn3%,ucVt, y$bϱl5+ʍp)76>12r:\(k q.9̮B=کKjG$Wzn]%3^ϕG/)u>)í2-;1hfh>IIJ7_d\JNs_jdd)r j~Hxob<$dЏWΌ&˧/j1ӳ.G70cAh ^c~LG6g!ڜo14 \?J0\y~"^]wm&Ygl [u {Om3`|PgՆAjQ6&X: -Tդu5Lއ_yc̨r㔻-<  j| 'dpLSܩ.zs;?%¾wpBb[ -vEog6P8?UF=܁ǼrzV/Ép{r~.}kX}ąnj~خ1ToNBdݜ)OTWَ_w,w㨊!\w#|Ũ:\+!J.-Qzc4ՈTuhÜ6G5 2f0>}JҪ?( I$! &r!C 煊-$c}5k|-VvXׄ/Myi/I^ق>A M -O03֫'ε3x$Z{w׸L`?{r%h7ؤ]9i%%zwC7y!})ARzI帉A3$vhbQH۫syz|=_Mk ObQe3Nn[ϤD׭4{,ë|9p\!Y ?x/~@bVM>W]&. kq-HLgw4hA-K$o5oa5VeWYì:(4+rbWF$9똹142"9N_G1`2a^~U܉#B4B{Z W܆ZI񐢞豭ٳҴ&ֹeصK{)hn[)`Q3XqpzB!]CRH%pRqiHy;5ST <:'z985P6|t9;cn+Hë%=)"p8P]ه:{F ww~/l0׊_PRp?~Kl?s] zI;B$0JK%h)i]sZt>}$N^魴(b4ђ9qb4Ew7}f/f6C; FÌt%=p&k} C#ygOw֪~T j+%aH!nߩ'\z$g +9{-So%oGs+}Ux\׿Fgc4P38S -H!FP\:0z\LVue'H tbV U0fԇޯ8LL`5E=FN*##YYcԞdbEFeicnO҄7 $4Wn7'txᰏC"jW p$GR[aWvCeӲ: *U6^|o\MC+-~j؎@3,)|GvMμػvu#Cuf -ݟ2F'N!vy#c|~!(FγϢlosj PW4űztz2ZQU7zԃ$*ΥZknZm-!7-5>Orkoo'dt# E\G;=z^a.GpdJD\tW7Y/wi$oհ^#%&n$Lv2( mEnk}OL2ɍ5Ƿ*2-=b.I.Rv{!.KUܰ Rdw ѝ:vcבoHʶ:c2㑋ϥ:G+cC.Z2'%a]pz nj!]hÑH] -uOfVM1400:1N5)Joor 2='qV x^N)޲/ov>U>e(o -k+0wTZbUD7r+xDALҨZG乚 G:.\GTYXڋ,[eKGkJrk\mWNb1<Ŋ6?<)Wdb>N̵Jo{ꖙWF}MquA(%}>I_L9FFr~OG1ؐ+c{7?T́6-5M4+1?:!v~S?[@Db—Z#ZEޟAkW8XN[ iYGulVc+h"KkD /\2 zuav5/SPh>7|D/GF"7f(m㊣-]ܤXNȀ$ff1GqmJ/.&&/$*"Vo &b[s> fkc2FE+3 pb}8+ʉe?UVu/G"p/%#Ĩx ~4+PBETP"G -4kgFչ!AJqO^BYbAD͗y*2ZiD d9OF)Us @ղ`-]a +EX &%lpBZ$hg۬'x͎(!9+)5nR*t1 +kN7AZtӒR~hkRRUޠI%Z~ f#>ZwzˋW4pts]yo Oc{{1@lPBs +7<'i_j%?4G$_T -mDG;^xAPM/x٧O Q%qQWN֮~]>Ka{O,(x;EIJ,vrbePϼ&J1gPp`3G"/-/t Yǎ*YaO+zy}Q# Aϩ˯&ӠaRd8L`1`Ul[j43QGEndHZR!% HB:%b$ *0[2XƣLIƟl-ƎCcm؅Y@Ld5~~II4ĺIaAS)h[HT5X"y -j( 螧\bAT\>WjUcqQJRLΣ NDݒ Ȩ(3wA%(61/U~NYz\S[rB4(ȐR(tӆJ1:e  s t.|Wd٥)vjHаNyH\ L*篑ߠ=nҾS]'EtyatL|*i2}LNnae4TSy$H*}+ OpΗx?2Zy˨"2?)T]S%_Zµ.rH2eP߬~fxh6d`˝E] _&XBqEث(A Vp[=]!cS@*FuQň=J(-5gχO_]MтzE\&%DPD@RyۥGahExr-9Vg:g%%("ar5DsTmY6ъԕ>sDp'jR0b2\jrmQ6@.+2oyvqwF(2QA8a1t9QQ~{!F>1zv[F&Jyh0 cFo?c3LXj]W,NV|}nCXAF[h0mGukҧ<Քo`|b -4/+ʐ%9n!Иu6Lw48iNM 4̴wI9V;d]064*b_Q1KfAs(/ykQn@a3wE-LRo$H Ϣ.)SHV=|`|EA3oU$ty/& BQgMNEf~rVb= ST$g";O4[qUV:T+{l,ɪZP"׫S44֫Kuѷ#'_7 :CE:n L+ .>|fApH;7G^yzWYc8VM?<#@\on/gUlUĄ}C [twܻ,> 2poSAz߀A+aVS1/7ܾ}<#\_!qr!O&7|p2|\?>찾<P=pa_xo9Cqѣ{?S0c TMu%_e[ S4F|S4Ilp/_-B|hse NGlm>84LyX=Gqr8kSzxKO_B<^2} *GgtlXєw~ۂ.Jp84;q?kF7ލ3 8-]s~{99d^cA{BCƭ$m$c(ǧ [(۞i~486ee80ϘB+ܽeh <yxGBz];]t=e١'F \?쳧ƃZ 7"dLC -[緃-x<" ’Џ&_ Ќ86c=9No\:V;5>%} ǘ` ѲY0Y :YhkjFVA^=I]Zn^jA"ZY˚.D)j]VQ[`8\-$U YԆC2TtU63OhWl~b V`:4^yOθ2ݿ a,4[$qSaP=gywsi?'Ez^loWJf~94~ɹ NT֝DTt&g 晎c[h/K_R01 Kͬo疍1+zn }偆@# sy\4}!_IBAh|6tiwSs6˫q->rmDD@!{) 40.aWޟX =~ }>a\Jҭ&;_i:݅msU*:+5^ fK7>EJSB8ad{VPԙ+g*ZP'It)_D{vر xQrĖ"v"'/ U }mA $1 =%RV pL^KbyP3yjs4_C^"Vȱ (*+k-r, 6_gSOa;#Я&z:(HފU`#.3:) g/[@HמRϕR5x IkEڃQޅPh/ -iyd0=NbI'MJn0j7X -43瑓1I 5dH`\7.`͠'{'E|as3W PǦ>8v" -ϤpNa+/p,{z$.hY,=&ZoQS@nރd {Fpcg[(i='JJTSdʿscM L`HYh 1i-E&A|$DG҈\FmJ LɋΩb]~_V4 z f.Lgu(-M#>-X1#`sF/f!jfZ=L*HmWρ|@yhr?@ɹ߹ !fIp3!N, ĨUH%l#ءZ:]H&3oaǔݱb=P b -"̦Q2mK\ \b knﰥaFe0u5}@VYD@ޘvz!(X6s/umMm=Edb(inNs鹈ḩ6p ,inm<%Q~%M[6+}x1ކ36V@ i`Ns t 1WB4R7oXB'5R!>V,ɾbj!y"9#s+C -$C$b52K5.F=":LҢSB)J+3%uZ3(o}ŤojC!.6!'k8%ST:Py H8ŋml=7sZQL.% |(3 q .-2^-2 , 8E >XbaFX`T"fal)hiQ:dlm]V}%QQ/„j^9gxznV1&oiՃTV2׬50BlRh{>H݃FzǧU~Kg9p帻ٚc$L`3Fz0>}hqnmadj3sGɖgj[:s"+#,{G%@*͆`رsn*+VS1 ΀Y 0]%PKuY`1WZA v2Ԛ٨Ov*֮ mGz,U6ʪʹ}s7<Y_Z>|@JQx|Jtie>C{ɞE4 ?nOb3 -+DK8 -Rtb4)c -r2́raIoeJi-4x,2!@y- !ehQm"uXq87qJ 4,Mɺ/Ewj$Y 1JY', -gyaIsoY} bg2?970n -xګ a A/bgrLH<QH#)'+%_qdHQ,&콀ѻ!/p}Q.{Ȉq41 nz jv"%3st)fp;ӶEp-:OܧE[2ӻZ[| -\M* r)7oP/ۢ<^ۻpE*i8T%3=v&؆DKˀ*ns;vϱ5.[ ")HȆ`R*6.SqoX[wYlOå -^W p *V*keC U|J[VBq+l!Ry;$b8^a6 k%B+K ?/JmpIr-f g[d p \[ pl1"6\>nmܲl t$[\z Bl`nntjt pEwRBVbftķu(,%es,9_7. XQo!bl'IiC*s9{I]I_QFqtk^)óT<6R"Vk6bͫޘq.o^:nšWKWԢEnRz ǩZjdVasc^O߫<:ӡ2TOBKF~ ysh'QT{t9**Ny޼҉LeS+D ܱ_ʾZ2%G^.7~ ۼ!sjCAٳR_0@Pah:BnBaaܰpSsH*S.le -OxaAOs μoڋhs_9U|{Mh\qWA3oyj7UE~tMJ/1UxajSG|~k;/xԤԸ:S;5JGǞqIF< ;wԤԴEi.NʣрV?bĖ:u)y4tu;徺~f(}<9Iô K:?)٬q f,xyn5h)}M)@kDհ[C>ʚQ&,* -{&GA(4ĩtu2ޢ",s̡ |MۡY05ϫ~yȀb6f:o~vߴ?0/}؁˔ HRyŰs2|~.s3B@71b ȁ3W_{,Cly9`&G Gye2AXYP&_उ1-\Iq \UIcL0Kq$|=[ZlgểU-U[`<7v?Ajޙ.EznrQo8^)#1gIS]޺%ptd Ar`gQJ+]a7 *ߤ]w!! b)PQߌ]Wt S&L?f!i+ 7CY8/0nTzY(r.x~-5.!5H敎s`Hx*D<ưGI+-.r^U ˩m -1Fߜz ȗ Aec(Q>V_`:n+:w% 5._Bx-my5 uE^}CègH~SGqL՝Z`WZme&ɺ ~{7r` B"]J`@tYl$z⑲ k`bG?a<ѷn0Z $.F-LКWt3}>Y'9ӲWZlhS76I0S.C= q_ ~kr& |)AIzb o[S[LԴIM A5ؤWAf|ךO񏘍׷̭,i{?Fi0!FPtIy5<> lF(D/XH D]-=oh8'= -scIU\9HgtA9;"|*6Y㉛IKRFGJCG$$'0Q[FݹBB~?p"ΝH8 p$kJ;v"rMذ^5*/Ls~CחHv6yp݊f%?ϿAO, VP˧κcյJ@f2/Ymy{PAuI -wfV,x`DRkWo-fa%$G8FX/c7Lf|n!zɎ:>,*X!+cnz\{5b-1Nlm6K9I6p.HnH]0q:?6it@wh בEq>z_m(EG p5I5z&I9wſXEbT26Gwbf=.H%X[J@q1m0zLB'`"wd, -2:K[y<(ϊ8L러R5BD}bmm4G -(In2֬B4xF7|=VLIpk h8cfmw)8 .$WaN$ %H)܉dp!B2[os'ߧ]Sم0։dp!a8 .M8,8 .$;k'djmD2Ο;'f#; .$߱`$`9ĉd880&nfSj#ڳgض{'D2fN$,; .$;f`b7jG9gmFB2R)laAe iRr|CZ}2̘ER Rx?e/{_-D='BzxH%պ)Mo%^iT5`ct|Y-O M ?TX4fqr˪ yB S2t%:U<0p`kCEm/\O4fD,A`})v6s's6z0Gqڱ$nآ@Z߃} B%dc]JtgcHI}$di5*)' -M\(tƪw!S45Fh̹oLױkyCaD4K.&b Mx1 =pUJ\-e !2(]{;J/ԣOʰV]%(C2A3A7lt[~4ﲍ"ŒWqls㨹ҎSc U>ÿy${푵Ɗt \ -mIuGTlB~qhڗH,s$@f$Tңc-h^(#jOL`'CUZoc]l`i[;±yMK{&nijk/%?̒R0q| pz>l営̟Vql;[{-ֶrK;[&>Kv~ Ğc0ZAq |kY{czV_pXB96 CjCdzjT{չ0D縃Ίr--UI,#2^CI֪U,c|׏^VĿݵOᡠȝT1"{_J K<5UUƱ`fth?EgS)jx__FW7iw/6dO ԗR+ I(c;廀c.b>m!doAhMtE5pw/=F]x^T%%YJŔN9anyc{DAjdӖ>dm {`@<ϼ GL:v} 3i+gQhzq%OD {5S\V/N$F&\"͌ŎFE礎 "f%$z+*Rsex xo*U y>QѴ[Q׷:gCma V?x-: CĪAqz q>u^<-mM5SeWPd2TUs7"ӽH؜ٶ-V_kTtT[x(N@x6DFP2iѬctV-;YXU|ѻs@@9W9$?.mc8ŕaK©0y,Jھ<*܄a -1 g9#FKS-jыL%&2(xjnw - K{9`$̭2 -Ho0PG: }1̭=#j8I7d1ۊdVb&I#VB YLpP=ǰhO<O nRv_Zn[&V9]t[H&(lss,)LM~#U{*}9$qzqEV#gR`7*%&{Uߠ&o r]}*dJ}NT"M^ZhP@O^⟨)6 0#+U(\gQkyxi /;.E(w U;\hI3ť/ӿyqk0VoxT%~}NFlo`TSVQ6ꚡrLqXb[^i[:U ~"c~O$TʑyEl8T[j7iљtE:S-2s۷љv@gͨ@z -_f~[3 oPlckfovƞGI67Ք|EJHDl`˯/hJ>Ur\äRx#97MvOt~VUSNTj]l J(4Z|y {HkWgY5]LjD$5 ;Ml=OJ'HS0A^W84mG#.'mo-f°AeRr{pϱ5a{Pvs}n~ji}:ZުPIO,&Z#Z|Ԭ{u-WMDWqҐ}A|=JhZO?}ȗJ[m -W>ҭ3VY\vUdnIPz-a<`:'ÄisYi*E-wLSWZ?߇1g>T,]D,QFIV+;J4 kz?LE~c>ǖ/)ݗ=G3)`|>܀%jlt貵rjCdʟ]Cw߬&'*(!b(qե  Ob -$AC&"vGc5'-Œ9]d,EaqdWYB[xcDxIg4FR/OE-JDd\DOXOskʑѓ7Ohpz˱y{)eLn3g7 +U-!J'ș,p3:쎿b:?zm+bTAo!n:?L:?K#VMYAI%V;?z; fvx(Ǻke;%;cz7ýU"_,.)-hF^8ƃQH:2%nxwN(I!js% /(fe\D:)_a>h&OKśhi0`Q2ݲ3]vl72G^Jga{⤦Q|ZyoװZ€oXa1Gz JNBxa=v`n~g-$6ݲԼ)VYQRwҞ|A[ϿҺn)K]7KhڸrؽQ?Cg!o<"zb*ЇNaP@e)I` 2ѲyKbj#q $h57^؎? \Xu$2`pas(vrw*b^F۟}R?6Xw0G^VDxꚱ@O.T?Ng;΀=V34M}s9[&ˌmOl&n'ljd@&³~F'qtݡz}Qlw~/QzgO̡m>`: @xcg-PkAu7GC_xx-voSM*1bvU*JopEkRcq)]6.Ӯ [n2LϒΏr|pwP'Y1YMۥlyq1&KxT@p31*gDVoU2vQLso_"L-b4a^QeS-dTt]<?)\KONJisCqH+Ώ׍vʕ0|*.xXPo% -d4]SuÿV_wa|᧫/HnuqΫ ccEk+u CA!nMo[|f+||1Q :ʢռpEfhR-ݼAm8$h}PEf!NX'YX'ナA=5r.""cY_g3F6>feJQ\יRc&6|}fADWB|Y~ȶc~n7s4\:sqL-1 N%ioa -nNE{Mȯga{chmH+L5uA`z+:nmpܗXVJ0&ܨO^P̝iF6`ņJ~_,<̈vhϾ`Od;|m/F݈[2r_#N~YwosίHGYͫw Ӂ/Y<xve48\IparE>E} x3 XCG*z!t3pCOCLZQaqұٸ va̶^te#56`93/c 9/XسǏ_2𑲉s[ 7e2^OS{QESX+/ Um^Bs޼v32>+qHh.R7;iokMc0o4ӽ.x#Cy[vJ5N'w2~}Vf{$ # pR!Lpc0%Dv-a$uI,§<ٳ ç"tc0. NuvD@Veo]((Odt -qщ:[xm6Q L7CMgLLǺB7a?؞/&:hi S1qZ0>Ç>%%%L$ORV{0~PUqSl~CX F;&-3 -(D:+j*N,4`;I*kgٗcBJqd [Xg53N^e7bd{D -J&`* 4[CҘe݋!cA*i%e^T֥\{hOV%Vy`]F?}hvvAPA}Ļ\q2WvySTuƲ!fNnx -:և(r!mH. - OgB=Vw /=J^ 9` ́D].d9_Jw!mHCF.8繐f-Ħw"yj~8Lb(_jg(]lbzn8BoY[ g.OnyP5m{q'yas#@CQuF -~!Z jMVAN p\xp%; -A5)lvo X|oΉV7g*~#|@ ^[|܅'h㸕5N - cC$`b!C*y'׋1~mTnބf6?uƾ|b~uI]7T߷yV22NjGʃVFp/퉙i+Zٍ1̾Vݤuv= ?xu&@ּpLJB}.)En,?w e+D݆WϪ-dܤOP2Grn|{kXK7#񪨋qhS4M~RHխCP)|Xiil]ͯTJq Vv\&x$nM,z?eiفv! ʨA^tgVʨwQj0Q$rg$pɩU'qX BdCVLzmGNiaLĤbfDk%6sgmhP9=yK "o]!WJZwa;""~,0T%.K>g70D"ꕘd0l朂ߐ70-z8 -_3`Y8 T4A](_!{fGqsߨV3#0?v+ H61{z )5F ,𡇐p jq34- L{'ae'0[ǣ &S*Lpn9y KRP༘}CmgWHI}}ڎjP4jk;)]v*ȍ@q0&ŵ?a"˂ Ve@ֿoI4 nŴ+tZkKf( ;=բ$)t,0悋{e(뾿32zQY0R-IB>:OaMbH0GF ZSܕ%itPX!kn4Ѭ^ zR!SZN!Bߊ*Ֆ(UTƮϊ!ߠ ]l7-S]XśnFߣ-w߯=I>ܪ!C2G:np19 |WFеɟ4_ќ(L"bDSVv0u?V~.]8*i!ZEEIjTUw"9lH0k]6ʰQH6\c )P]Nkzu]0N]n!{aGĴ0܌h!̕Wd؁x=ް?VhP0K17G":kH\j`-2|a_1q& -+Bvh  `Bqp?a`+$qLZwsU"uTupķ(O-v *Wl2rEF&H#]ǖǗ|yT;{‘'˞qc>^Dz)τ -P3v -;~q8[?E"k|>>RG?] wC=ɻxgӐZ#sEX.K/\ Y}漀@*AR.\M6-%3ȿ'8T C+ 4D z=]? o6p* m1!O~[B"YIِb#e$sq@!UdԽ9(cCHL=]cbd -dUS-@rn<š YqY` %ŕփv 9(׼î39G+Э%Ǒ r #gfʎyϻ}1 +^ߩ>=0őplPlM!Ků _7 5vvVO}r:|֢P-&c O]A ݡkTF{7wbrHˈXV/~H_M+i9>II7i&y-r -Xl) -.Z qCٚ[_0&Fy:4=&BoxGRS .A Id_HhbvZwo4e?E*GpEzyp& |U&~$PrLkMCN]\֗|\ͥLcI6,!`\jz9cz#%m/)il`0pAW_Yr_1햞(A zg{_sZa$I[^'w1,[aԈCa)-%ocHToCu aWa dx6kJ{`1mHSqCaiŒė~v:!,'Xy 7ob'5Hṑ*$ɠu"oO|>ƈƻTpiSZ Emukj.?h1!?t~>L4dpXL )د?:f%r_u>?t*\Ач& -1u5RZ82wc-<"4tdЁ Ⱦ°#]B=L$l`ZfD`_eD能dX2QV\_\QxU#dXJ+-}jB) ->vxy)utj.xu&r'"M+ofQ<5߰i=81PLGLڬ)$|g -5GoRL%JN[=u=K!t}$v̌ !kk䐳뗮1z y529FWs3wP0贩>lͱ*q݄UFɿuL$529F[kdr*+tLc+wLF&LjջF&Ljb+wLњwk6u)Ԁ[kdr?rȞm~ǕF&LjeVei^kdr\0qLz^kdrI\#c{w5HC5 trFk^:#aW1b}+wL[ZFeŮ1|F&U3529Fk?qL\kdrw1Z[Nn:Kdzk]#cD]wL}ջF&Lj+wL[kdvQKp6տ5V_6Mǭ|ڑP}UpYq0bŰf딺hIU4ŐT'~׳3]|}0D;rX<xxjx.s`!NH^vREXY_Kގ=-9T!I2Ga_I¶h%"k EJpM+6+ |d,:ROwiǒ`p -0~Q>]nلƃnx;Tg4N؋p`>۱ iehOH=vZp,cOx `W{NRjͻ@x۫=F,yJ41Mcܱ=-f_I R;H\i Vlϑϝ=;߬eS_m[Qy ?_ cw'񛓫8DOl.("9wMW7"W5K9OXd^X.#ğ9>NlW]clr 3ύc,~IyI_`y5,!k5E~d.~X!R/U >jdR`wD6RM1ƻd`FVڪ<3M`&G-昏?|b LhZy^ƺquIY -i3ZBrdp&Ƨ%&)tO, -}hZMhܢju2k!ǐ'O=ֻH5/:Yh;~fFPwnԮ}X+=8؂q!8d$9N`X%Abd'#J`K -wg\Zk(NU O a8%ybҸ~V -Ä3ǙeEk2؄I|sI DyQ]INd5l=Q]! Z6t% QȚgc`gM gUӬ>r#xk>HBAlZhbd{h-x=TO -T׈3TC>c 5^m$5$Gc|~:-U.5.p횟ʳK~g?(K!Ͽ81loUf,JBE"$ -X`(a,`933 _xŴ/5s㪀U3֟x͒ܒV9@}¦oMD5OʋU18VGp)_hR:-?+]܂g"u$-҈N.]#iruޫ -"qjfҦ*07\ guQt/0[Ԗp$ U Ԏ3S{-= !Np`L{ҁ_ i9W#! +Ջ= 4EMq -롈"f*]wV.tZGuM<=up~*e,R[XjO*.Jk@o~4k:$"]zxpU&Fv - 0b{-k4w)#"D̷xYdicl=l$E6[`ɂQMI \X'$?_v?ysykd\ -5h;Ls8y4S'O#t^ERhZD3u-!_~Bڴfj0NC?I /" \OdK0.(]?dUt Բ1 `*˓'ѪhΏ[gӚ^fʄkQYU>!ZE[c-]]EuTNgū\p!`{PZg;?1jR:9pstٟ4QE+z/-=2Q؁JһvV3{n#12a (SƱ=.B-,:"V-FhSG\k20ڃ:6uwDq3gJb$1SNY8S'n_(MYmY1sfp ;\k?qL |e1B?pLջF&{E529FȹkQ_ĩBUF&LjջF&hm529FDwLȶZV'/#TYkdrJJ]#c6\#tn$128p$12j529FLm宑11529F615<չFM'529FûzպF&LjbջF&>g)y!XـcZkdrݷF&H^kd2]k$Xq5Z^kdrּ#ްry529Fk?qL Zkּ ]xؽkdrs1vL*\#c?pLW529FF 2͠W#52XǯOջF(Q\5ƬrF -rŮ1\7vLW#(529Fvl%EQ-ʬ*x¥-Z!&g?kYY mVnꀈ&se, -zu ! iqS%*Ȏ_JbX'qcdvHAzaeƂ^xآe7CYF9SDTz:@sBDMzAk+i~L=5P~wvsu!qiow;wP@iӭ]Bq0MɇՂO .WDoYL:~5?_EOwzKO1bʱKr;Gfth;?C;" !}?yie7;0]sc8w[ݴ@*{.ϻj;ظyD'x-|D| $Bn9.;6sz#`ƻv '隐,|%h;+Ը>RI戻㸯?Gwp;x%iift#!CCoS)ȥg垆XiLշuژb~nZt -l`Pۤwb1 x*FU爿8uv)u~2Mn02m' Ǟά("LI&tdM+cH^{,<|)tzا( - V!x(L1Ǟd]*/)`ɏ9I Arf1 %CuXօ)2# -m30pTUV`!s cTe2%WC -ڹGdIB ȆWҢtoE۳ςe!@uwuv ̚s@-с\J(Eã.;D{Tj#@EAV/S ڟ)ºie\)` DEY9#} -h}]+)~Y)}[i,Iv?xY>,^#ǝ+1d~wKƼ~6^^f-0p~ N]!SIӅ~#x30Q^RUZLY8 f/MKxA 'kxNl4PK)692 ?d)ӛG/6pڈ+%\A!XATKqLEL$ix3?&]NZk\=9ؕVUQ] Hݜe:vUYH L/ ؠս|XUR:tL䳶A%ex/Qo[OFffZ* <>$JaO)@iO"Β CH6͛+5 x| -\";2e1 kyK`t"pYJùOR/%T`g729Vf[|+sUk$+lq_M> X};HJ*䀲K0W?ڔvEoluj[H6~*5=}, [VkP3[Wq淢2KU]omVQ zp:x`UˑY7d#a֧ɷy\m\aӕЌ -li=#!f#u/J~4| -PFx08HDf5Oll͈^h>e WQȔJ,FAX]{&1k0yħOeYz|)СKRE6ԅW?)w])Sޚu q -}qN>Vv2ko S>KbG__2""DGX]a G.XB+!ÏvN%PA+c_0/)Xx* ċ"=Z@'!}!mzҏ3Ę6PJfe.dsA#ȵ=T` x3Z:򽭹g\X>´pU?xN{}) OLx<1{'_ML~j79^Pbt*?IGM]>FΤHoՃ!śtvhE6z&%÷6|[zЌ"N-JVc8|XV^HCٺSZ4i4Efo%ǴmI֥ 06g5f0XߘP2M1ڀ$8Vc_&II(mlOB~ SX-yb8ajMbs ?E`u26}z[\Rk|f(Q {88a3$O2Yp0Nfq|> J (KG_HX>YgD:5x6MWN1TK>fh7iZ%~M)R0) -?kɉ͆ l潦P6$$9~9E-9Hl@D{+Ň2:l^T}L1o {UuJ"99赱*7'BE#CGs9^1Ov,_z h*{~8/k@ - U:(@4P*7.Syٶ\6vP&ݙY~{L<\1uVaVe1ׯ#1rN [6X"5D6V-,<˵,˅ -cUgɧ♓O6jMwI8"\|]uu!oٚ~p9'mƒ eNTxm6꛶TU,i(~T~J9/iOhn-onܙL_W%U_YKG\=fj>R`v/Ote5m$tI ,~dD-ΕRZQdsѭ0~x` ndbz kj Ri4( - nD;tF(^f<*MIOȚ"(T)4E9؋%ČB. -b>ƃ- endstream endobj 2857 0 obj <>stream --} !uӌ3_VzME S*B1̻0r MS -!Xkj4LLa J@ȁ%R1=^?4бa9T+dL"?>Z,#%Z 9c:hhXϟ`n h8Dp!Mԃ`a:~TvK_6ar$+' !TöB=˻r|g" -j;0ګ^ĕ7 tVl֣1Xvm5$Ojׂ_Z*&EN9ꨦXLIDIlK5,ʣ)5ʷEhv ^;a,,g=p~žJN%zA\UCV -pCW}b%\4Zۙ|F45k"d %5Q#Omj2 #Jj<%]tC}jʆ+ -Wͨ6{]LV/78 w/侎4q{n("w.pK;>\l'/+dqAc]OqIcrJynwJ6p_SjLiW9p ?XFW{=Ouƒ`Ҫ+W犟xBܘo+ddV"gqT`? t-b!bVy0#Ş(<̰ -((#5&̮WΊ$E΢Yamԧz%*TPxxRנhD|dh|1Ssk(NjPYP>+ -&KhXj{լ_rY׊^TYטθp}zAN83|tS o̵mSGcy驵cb&`4tʚiN S}Vz4LDMxw{DE!,wgo̡Aޒ3cLQ:HYĕSqQ8A0VVɕa܅ x<<5MR$&Qbt+[! c l":)=إb:iVfZe,8dM4bă%76\ D΄GZ*]N&Ӊ<=bo}t( 9A MYu^YuF,dۘ`_a"9|_gYwX9Sm59UQ D(0rmw&Ճ?X}~ 癄҈DSAjLRM8< C%dG߀]//sPɝ Ua旅zD1NNJ0"̢Q rh^[#FH&4]fJuZPxpf=Q૑n.t&̤HL# @j&mV{ٜv%1bJ<ΏnXG7܇\6W0qL'JK6¼. />+z̖g/s8N>cSYڹg&"I)pmgrEJ{"^qUd/pBk_knA )̍V3'DJ@E_6{ΐ+<2`(OttB@v[Fzm!e.F|98NI}BSk6\ӍC8bܥWWY%zu4QD`v,?DKť.PMvuHvíf85*_ ?Tw\}bς;nl\_yK{g,rHcCټu1% Z#O/>߅7ϩxju$2<0\/y!d(j}}1N}n!ߺK [/f zruZ{˝5Fڭ.=ëk\~5h $52_CCՌ5K(wGq}u_rkGNA$u*a^N.|㍍%IaTD: -H= #ߌH,_83e½fȲ|];l Xp2o|.XP:S13?iA,< Zw/K\D^/ɤv2HTl9Ύ.#fMgXx.`Tq[)zABX,syGW$jKiNʜ$nOgǬ{MB~U.nS2': -u&06HvmǸCqV9-hrMF?'%SAFX:& 4G v+OW}<"n}N2) x!ኜDi9YÆMXo/f~~|Ѧp7=謸'5RgŽ -`h%M|^f81#R𤹍m/ P{ m%. ~߁G޳YA4 | UڛaAkiZ]Yc=G0S.?N\7a r `MI5K,<ݸ-;Ҵ@X#j4Y2^ -~K{ Fϸ9hQa4 ]8eNmjXY]4mA[\\^ 9JSKΥrzGHQfn2'@+O$bmUHo{+c&'/-/F2xE D#lVwˌWF?*@(5|#3 ¥m3lܻQ윿6лke,rk)be۰+m"V"jX6NSdmûu$EcRl@p|°<7bզo+9;]؉`Hל8n?Ijzy5#2]ߧ#XjʅH54 ;e:_w!"KwWi"O DخйDXieaXCڎ*-AQFBNvh  aM?UՔ , Odj(+4CAڒtq)"%\L^7ֳns;_@x^8Mrxlis״ 2H&EJFkŇBN^NK6b,4@DlȆĆiJlhj+Zh;Xr/4Ubq (IF=#h>_'o3 A:cͻDxtv?9NB:m&"@ޞy1[#e׍eL&_?`0grص 0""xd+D4ESrpOKaB_g[ԪJlb gkGlpĖI4NWǙ9*F&r˂V֙nG=4%v}:JM~_q{~iUCWfy} XrpXy͖5.%JJȦeyYΚw2/]V'bK\+먱XhV Xd; C""1*ϊfhW%K&")^L$b$o3.=BE/sre;#ļ+b@!%P.>NYE6#!K]S|]_eLzGץrDz'羉zcLwq9KGcLw1ĭs+q1O^jrx{lj\ vUj"Z1eVcj"w%Od)ݶU~LnCݬRʍc*58k"b"er};G.fȹr`W.ȹr㘧"*;[7Neuo_] \ -KC-8WbH!aQ4üZaXa&/zajMY5bOٕFwY ,ͿbhmKKb8c],eĊ-KdS7$SVlh64X1%lYU:cp R085}`_Rp<oqeԔ_Y pvXb-R, J.!hdWe=I"FKz@}rۄX*%J-վA1&^?\55a+d'e4đqZYEg0"{Ff.p^N/sV~F#vAm¤y96Xg"!`Ja<& -3rE!BAIo i2EJ?CBK%`IM  ;L]iMˑH]ibJ@cށo`hd2ilo}A'QPZWtg{UEMorAS.-M&Ln:Kͳ=TȾanԲ~CoveOGwxc=E<]OJxED ^ZW/fF$2 -ϧE {; hOdv{~Iq5hQB[B/QƁԉRG;ΰA8}~{L~+;PRf]h|Bxuawq} ~L&cW. nӖL咲Sh* vҞ:lמϯbQĿ/rĬ(U%qEʠO֔,ssZu?`n{Sk?H'qgl0gg%P-#&mݴ?y GAja^}2b&1~:6H:pUZc{KQV}FzfeE88bXk^ҷ!a`g\f:sBîИ(8''+ 9P}iz= +̡.yKؓU,=5+T׸P& A\]kIyVz>Wy,5] [o&BE3rL{Q_2[ei:PrH;}lʘ 8nɞH1D?lYIc;A-Q.PBֽJ3eɻlޑ0C/q:2S}OdH\S#r7AO˴0t8ƻ'j vQ;j^W:9.*RSM\vH} ;SKRM0l^n%_(VyLǶ\we\Hg@zVIt(oLOK^K Lrs%o]vLS^xpQ"J}d0?L u0۬[CA$t:2^9qCwB|ކQ Mjs$PJY386;r]1tlk3ПӺid/S|Tč֚16$>Oʖ-8Dzsr,8xb: [Mj, 5=um^jX ;o8U;~fiG0X]<8Dو?7ToQjoGǤϾ]&ccO<e xOZi?Z"P\ BuQ©)W#S};+!qүFƜU^H.YFgaD -3FkH> M3z$&zFL:ca?+cH7R^l,rqeDWPhݩYV4!h -Xڐ\ "/49˙{a")JqLWA±hSۼЯe < E$%Z>c`s4qA˸/1{ȭe+T>.ֵgek>K(5S1XQwoC\^%x3i0uhې( :nK +5UN8gݬ 9(|!4#L);T2ػm){O-1{Jvmv=l`.qwgqC$3'B5;o^@wqJkaYfYzkQ譅7.NG@iub/@fyJ̮ʸN,;4GV5o!!| e)aˤ_$FݬtyQ4<􋁭1c\[O oY,l'&.qDoPi%,5iBAΜ߅D {Qvv؆H[gpę0_ { -Dܷ(^۳ y}w:05aZ JvbCBȩt90^`c&V(/^0%LY -E0N=].`x2 -u. 1 >w8(==ݹ2:Y~_hca obʽ^yBDσpw] 1:#k 8G Y-ү -Y~U7,&> XR}U& L -U -Fl>U?G,pH -"QJU[#jI,&Ps hb顬 MiB7sp`Q+Xݢ`=W#9Z4&8~4pnl!ֱH€V rvAFȭoF0~(MdR$Ԃ`10Vn#5űBiPf pNZ-A؍c+<~\T{UݥM#˄z׃rKςÑś9j*.ZZ} { bT +%j sׇ2Z!R/] -it4ZZfCvQ-d3M|B j~XEs9KQAIޥ'[5e현_ ZXy# ۻ5\4jwT~yD͠ϕΤYM:MoF7:;6,B+؞4RxWS;3KpR}*{fE,ηې["1]_5pV~eWM[BrJbZЃ񀊑J4t?dA $jʽȫox'ԃu`iĎ3Pf(kWzF)6C̽P7s^ͮ,Z$eGM6ǜV!4¶p&{3Dvr [Cfה.{xwKF؆>JUPӧV(Xʧ[-"ƣJ'lX,̆ة4>[dB -o+Mt)aPz;Z.կ}Z0 &RRapcNww0J7P!JqlĽY؅!`(-1RMWTn_ޓ.OED8V- I+I,Uv!Ϋm3_uD%n]]d-[.__̏%z^ f/|1<xуkpfojx-0(ZX,0_(3JC.o+G ە%F'Y&ӷ5WeJ@Oo^[%Y-,`VK!TĎeǧyvPj⨾{jT'uraŪ?"Z{)~{?g1-@e9§$ee1=ouL?0fFzQhoxydSe|bԕ7tI -k^b3(|BۖZ3\jl|ѩvl0V 3#)"L{7eNpYe!+U$xSSIX(Ep$IAfRx;mG 'oE79[֝UA~1Y6ީZ -VYH\qrfB߫eXoHn:)}YA_fݠo? Y[ދԖAQk*:7 VXg %m)8klG^s8kiUf"FfNͶ"⬢|ؕ} H՚=j֬f7Eqn$Smj[oHWUl|U,B̘31X ̮=VmV~8jrw|4MG= -b7OkVv5߾N59ܮeo8lXO{<7&QZ۫5we[|/M7j?ָ{/\qy/ -q0~^Jv?w-8_"_ίZy_=leoj^ux_ilo9חL<>1iy7K\!#zSu(qዊeD*>(qa+~L~Hɥt\ݍYfP^T`ϲJ49'Wi**JD^Nqv ;Xt2Τn8N`]70HSp'ǎӍ=>BF~WR1M(*8Lhr FRٻKg~Sp~Ê))kaTE3`AKVrj?{eFTx–Q͉wۭ Ű|[+}yA?)DŽe8b}Q2 PãYSa%0x(FXhY&0yּ۫haa= 5zɋb&~ȼ_В ">{X `K"C|weHYQs!j`OV>eƌSoIͮ^=_YzF'٧vto_1XMLIJqe%t̝u\+r_d}TYi6@(s$7Uz7{|ӑ[mX Y }CXW1p2Y[R 􏴊87a<5}tw ]F}|u{E0[ki(Z5l{9Tgw,v=m豗:Lzbvr.B~#{9O`fוS}%JlaJQ|9wɍ\n*;1nz. {6>βWݙڴW$^NUmd4>4~:?QgSp=360Lv%]_9kVf̆u8jUf^1K^Kqڍb&_N6l v`TK(+foi6[.4k؁ PZt1E+ @@$.O!ς3ROLD~uG߻9r ,̘r%qҁ*"^k:5l$ $T3_3."eu#}QB0ѦӞШDGDE)wakp2%;h}S*+%!o(ibKꌰa-!Ŗm$^je &b+ oNǗ~u:̝HkVD[FH5qMb&*YBL˚wēI4O=8%wNI/L\dl/rn gEmf. <48Mb&S,W@4/쥃Sٶ׸3S¬S@X]:Vl+FR_0WЯ%7Hc Lg&) A -c2j1R%/Lg9~ ȉwHvG-w>\xyؤX4l&b3k֧ .懑=ק76x VʬWzm-bbMQ'ݔ9 _Nn+%wY2}VP )I=F eRZnKKA2ސRWN;l$qQ.`vi_3,fHr5ROuV?7y|j>M ȧ}] ?Q͊OzHce~jiv׬g]yARMk#o/5>uL*gOe55Fb} C(F9 -lRRu k7؊Kf%jEA2{MZo<J(LE $׿"drHk؇-fSE -,:WdF7+쪀|9[!eݿ2Z5>I 2ՈЈ>ǘNJDTAc*PF$`džjzDZ6@o -S.Ǡc>9]ݝnmNRxO]kehBfTv}ώ}ik28$)PJKz1{vOvUUC9+EIN]1* + "vn#hp=1s/*5;}`UߠƴՊaZɊa&d)=_v",!Ԥ7A j`VR"]8u@Ta,oSIZXqjSh"^KcMEH:*L\ ;\HR-)qƥd=9\gl^x8V-rL{;1N:kUf-Z z%zn;.qKWdT[$!i5!5 -d>\#?|\⬝.(x -쨓Jqz cޞ+:`wZPZ:LZ{;:>ydT9lxɡT"MRInJ`Ip\egie5HYgI4Wz4) fv2#j[V_UW{)fκo8:͛bY*qȱͩXY3۴)s)e /w)Gٴ)誁Z`=%Np\I&N`ĢhҙX-0XS,˖Xw)ւ1~b2 2y\:kX6HJX?XpAŃQ%6ieZJOH4+=5+%ӶV1MJnNF0q- U6kueB8VjhnSg!/l ySkqwQ`2Q}f!GPp[Sp+̀"}(.0p!^o&Jo5RDIMfɏr%䜍o}SH߉Ƒd cz-W,q9K, -%A۫]O'T,&jWJ=&LI:b -ְ5SɶVYh`l.[rEGS7U@lu@K -&8ͱlp&/.pUr$՗G2oEJ -*&q}swf/홱~~8KņT[3֢J;]6 I -|\HQ?G'Xw*Wa1{ePW7v1W[˳R96AAۋ +uup; 84)ERDtEJM -i}T氅7, -IGkSNF8_=>Qi.yى*XUUUЀ -hP707SoQ%Nyen,]@Ƈ r0Y'P1-\Xi8l`:IdsU5"nB{WhEaDZ9V-+/ rm3G~- m쫰;|h޸ufG ՆM0c:Ǣ:ŀv-/#2-=6zƋFV"(`XM {+hzV2Q.H -Oi ˓C2MWs@ 9`3T$%I-( -fRWBO)Bˆڬ.m0QMa䑩(f f,ە-87J蝙-{sdhן?,>bbIq=e,[l0v푖FhtC5I>M*u&h px 'wWi-u72]oIKfiNTOp#"D/`*yܝa -a=ñR((:54 Lw+SpdÒ:)ܷ 68P7/O ]T:UI` L bRX,6|"bmiČV)9 UZT=oV\9fY¢)Fr C.gAbHʝLܨwC^}dhĢ^ش5ɨgj_-+0Vj!N;lpQ }G-R7ȔʟepXIFpNU/4sMf8)Y -xv Ig[QVgv#^lIBﺺQ"A*K0(cJ?$e -5O!9O3^}?tDsp,p&dk#u4^$3*[@T{Xu>Tniu5<_#*Q: 坄;ز>U0 $EϯkR¤RQ aTinBMJ<۽y-J;5dK1+[öCGIG埨MPNwF-(?fjQyZʬt|tN} PF)A yG3~$>"xwWZi'zEæ!szZsCk[ȋIvoOk&};|,h v\ul\4 -fW:*}4?'YJ[ѷTbؾyW K"x@% - NdFcj, =|;8߲u^þ)s -,\~dZp#gO[JϣUguwEϮxo۲ |ՙ\纕dɿ7b.`~R{@7cB.\ʷ.|[ij:sJ+3[ZgJ_I]RٗZ+uv*%ωqR.N駈y+ƅeDһLUX_1X=acb4ˈ a~{ڟ&$ ^~{ -1micJO{u aEBZ_%[;sdGV_r7E="N, TAVPTTmHtjv"Nn۫!f$3n;\Ŗyez*J|ˍSIEGEQ](KI?Y s ,ya 9jpKYxgH -dOVJR}=VoԎV& w| E1uDTU?EaJU/է\ wYvKL bkse?[Et_L4*H}7ѡ4&zt&46g PGvh~N]3&JŒ-Ae^)9-MA/jrx/1th6n -ʻ\h_yugK͸n`gW4_i(w1x -Q($ >M| -HJ 4ơa"Zjwm{DY3EO* Icgva8aJHm7^>in.uA;ZNn͂RCz/{X|̀ tBqq9f(*G1AE $ψjAj@h -X5&߇R$NR#;YKRYf0YB75G2-S((VoCA^iRfIz4aqdNs)(z:wl-K.ɹeغG;CqfQ)PT3ⴤb>.-)ZEwI FE!TBO8T185 &!ݟ,yQdڭOhȭcGs|{|36xߑm)㊄JWM;m1ZșWa)o/:9Ky(p,>m ϗZ]hGpOKJ ܁}#_{}[I$/iۗtdK"EűϓI;&v)[J65:ӇMyUP4Jwuqgnal(M8<{:wlkx򶹻NJBXˆNl  ʱs& )U&k)~mJ(ӌjLk/1:ʎ/ŖBy<!/Os_dȉ5e_!oH*Z}2 ۅCE*5,qw"w;q5qHhɩnvRwAo~RN+ԗrFI&U LF%UV%ώh(+ZAZ \}ڽKl}W*PPVjhKxoQ<tX/kl>p/͌\6*q,mK +{|51)aIWJ\½µhIجML;n -[ UKa4w Epw wSΈ9~~j4>r6kV.C`|p"cV=}S9K|=>zc.!nyCnzCaQo]~&Qnj&twuIKoI;j]鄟6x\}3ئNқDv X橳+LOakOWđ!k\U v#|ו8.#ty'k%ٞz>p:'Ԏ |"?79rlPOJaB[n# -҉q)Fz1,Eׁpfr8r%YfWYZџav%]Auٕ@Tu%wd5Wͯfټf^ x땕,,A,րٕ@V]+WY3=g\B w`ZY5h+H^s0yT9KEٝ -\5e}Ǽ&XUE=ل*لד =ܳdVtZ¢LVBSz] d1W,y`v[/q[4Ṋ4T[u:ũe[<ؼ5ZuEmT'y&/2:&z#K~$VqQ5@= si/ %* 0Ck9>&U3medYNm lh{~اsMRpG_}9m -[od&dX3o66`6F^Qy]&*jXWu_T`1Id>#XO8"U=ólpD?g|}7fpóJ ϧg* .q7(]ORWg |l黽FJG ctay_v VlUmUQC +븧Ɠ%7  >s W ,\7]~q9  -`X_ z7PٖGkjYy=Ðt3ɾi$e\(ʣC>P\3h_̓[^d7v|'-gbu$ր"5 lFkn]f\pb eU 6\p gpm4b.7N ̺VaR5-Nn {ԇ7bliL"%u_M>ђP", &5b|t6Tɽ{~ວs)47>3^wC]z'F"5SO5VSH?5*-ڙ."-e}Tnhgi%5.jM~e H+bv1RۧA}6H'hRϻ -e; Sr 5 - haZ6-l(‡"K]])W%÷_Zj6|<p!XIQ CUS9>r[i9K0u!­3ŅX -_%pcTŽ[nY%;n=?gb *[pթ'^ܯ -ʠLݓa|ʤ<+nYϝX -A -H:KdBYVU[=DV۪%JJ-jHދ2!ovN 3E?< (} -[n娂n՝X -LN,A[tq+­4 ^V:^,wOzXB+d[R,CԎ>Q-_Bξ3bCkxwo=}lmn@l̀u)G+e㷩&jSI/ޡޝRlT֨ JsuH("J!2*lKˌ3U!]*1a* 'u fvSJX]*.%-{^{|6t u c`>Eس֋o<`J`ܚ.0)?wp#4$<೯NrEA@no}E) y̋` -\J]bKG/8,Zna wW! -kJ[3jKY\%\g]%VbJ\Iy|TjKP-i\%Vu:R[F,;Ε֦OgNƞC򳫽" 5%cTjԋКN,*U ? ުpgM -|S%3_,~W3y*E'e:_VorjoAn%uz|yvɭSWܢkQ@m[hvuT%Td.<̨^d*pjFz[}6fh4A@hz ᖲ.TeQwb *RͥX -w$q+­uWrK¥XٽX -rps5ppkx# lGԻ[eJO7jx%p;KPjx ]h?+ !4*Rl+|.iw  طE t_Bњ2ՐsOQ3U]2m5v6.4gl}JpO0,~,u@3h"[^m(;/sn\$ar0Mz8 6PYg!.DD`OMlPW}[jhK||æ!w7xaq$oc -ܲFknT 66\p O妀kn]l -6^7\pcn7 eR"f{Ulfpm~JVguJ\ -۩va?@,0ad =v3fNOƩp]ce ʶ`XհRƭGlpyHq4Ͼ]~:Q 6qܒ~l3X˳!ڀ[oc:b6aC2l6v! -z /mK0AYxbŇj-kv#=ڀ[o,Q#%913e\ʮ@wyl@mw,!moMpAF|$aV ~:::lX=6yzL@Gg0G -Kr5 \(n@AUwP f@VZPPb!ܪ ;ZSg0*5͕EҀ;X) R'e[Y.)[&?k~fZlXMwW -A=IP,'9ı re540> Y߆> )؞: cb⯧-rw/_jY#7X]1sE J};n;6A`P3_ZwLz(?IFq_n(Զ8/}6u/5V9Ziն /eڧDdal%gi -̀[XksQr?a~vjrĝ@X:&lV -Z}V -:j%#4f:Ux˟6 jSmCX_^#`;( lg@Lѷ0z|R ]=/С3%Y: 3AVqnQ|9z|ai7jPj~l8/YQƚXT8uNm77 H}yU i޽1t؝+yۈ D钩is;l_WgƬoit!4 &_g=½:}EͬΣ˵izbsw'^䷗P+\+{ݪ 9_4DȔC6`Qs5y]t51=Vgxį kZt$s,Z &noY$0g03gj#Ma_lv"YK -[۠ی۠z5Ikn:l˘[bU9^ѭ|kTE(nBs`iiό;@g3>yl3 $O)m̾Y`@6_qXUH8͍ɛ`)6"6(Ƿ1 A,jxYgI MHÚ`x"?O{Qom5M-V+e$ZnVuJk`ϲ,l2Э?oEցj.${8зicl݅A4#q0;4Zj#Kun\ !o?z}GCM -QoyXNlJmP`Yݱ AMtW%6(q`${kB!.wi/˼G[G‚&Z=>׻V-,Qzm7O7eESatp22 (BmeaXЛ2]Pmb@!al>Q'>>,s_t)7 S-V' zHn8Q5 Q?{. /Ϳ5tSWo.5nü -^P㖮6%0F931>h=ױҟ#9ol}3*fD_3;l" ^l(SL>ԪJ!p2hR -ھtu""|e@_`̊%2} Ws- +4D -_MQ,)؅^KSXa1^ǐk q z-W_)쬗 -0.yHߦvy1zgC0[AXhѭ ¼u-_z-Uw/sx=:=?#Geu0+\+km?=hSmlҤK>wnZ &7k>z{0<=?jҒk -w-; rUpl ԵOw5#rA嘫-7D嘋 -U'Pw9*^7t u&|-_ꆼ%r46?wr yQw9µBxפ!Q _91_-5%52a/OfJ\?wSQ=wrsXOsԣNdU̳&p5!#JtJ':#V{۲s:Gva>ײӹ.+҉_QX{CbIbj!&~aްޠp8pN*&C$;iP=h Q/aGD|4ïyYMZ$y^oqE $|Г`qXG&$<i9Es -4xO0,E܄{~SH0VbbIw{-u6_۠x-`&6!6(W bLA$E}!W2 -O[QƕJ=>rnvfF/&J Fܾa )櫧LEUHEK0,Bb4.{#dr2v;|$w_U3Lha NrRhAZ]-HC jC f>·/:Z7=B bo]Vf-C  $^C >*c5YD[@oy[_v#ɪ8$э0[4-6 L5dʅ:8fffZ0tQp~-`5C 1 -Gf(켈אIg!"5dҘ"^f2iJM\Ztp-J. VҮ*Y{3ֱj$9:dgM-@.r2Jo!5v.^7y7v,hs꾨8?i !(?PU?& rC]lԠ0?y+JЛŦn~(L˅id%^X<Q)5dήy3mP21_{Me= (`b9jL{1=>Tc*wɴۈJ؄? -vHm@J&,5}sP56FcR@O m@!"1"/*wv"ՐwE=3fz5딀űuamvG:i#,xۓj/dOjX4l$Gn1`%{?ݤHBXC!Qw`Y((U6+M+1-딷;-V;/ݚDH\04*U3 -Cr"xU]qaǖ`|,dX}V+=^4enF^kj'5]W%/kY-֋5k,buXv"o*ҔUf,"1{{,c;/AP 'H9?¾ ne29`Bn31hJf $a+Q[fVFQ[e\p5xwHr7Ԗ3;m0]k]`aB+C؄j{ȭԖt*e: r.@ }*c$2Őu;5< K؂-q񝝷.W&`PA]IFCXGr4+㞦IlY7Z??4VsLK5i2W\k463hpsp̠;8l8fЂ̈c-bK`k5;Yk宍'Bn,*Ifج ݰ㈏MLC.A2Ծo%HILI#G\<ռ瑿9JVf: [f+it7nΈ -${ cL%mk:FzU׶6d:ZV A׷q4Xt|"\O[e=>wum*NGΔLw)V+ƗFkwGG{v7e#VX_`#V ljqV"RQCX"LKW]Nqd[e*խɜL~{.-z| li=[}!cnK6dt9u9uCrǷ Ajn!DLnPC&Bdcx9A!٭oܜG Cyye^lA^+G=W] Ϟ$*0 a|0D֛Cק}TKdOn.4|F˨Iשnv=D!8.[qGamT&o3hG̅Qvv NwЭsy$.msm%uRm+.URIM(9$"|D@_ck{ "%pigG)L:]SiQcۋ lPEgPw9"E]J6nD>C??OG;gBS/bͫ2]5IϮQSUǢ kܣly -{(4EwQ.l?;(KԐc'E_[ѮY_~19H9;SMga59o*7yKoDh Ǒ7w{C?FwqH!K=цi֒"\F199vyTV8)?sjLM~5՘b*]m,c^l}#2\eYTqqY}[}uNz;]0SКgynqp,bkl'[lypLw?<rt&k:o(9NZ9쵚w'Md盧]e3J; #)8W; Lğt`Κ"Sj\o -wFLnu%{BJ-?2Nj3ZWDg`6F+`8}X~(n#Mq=u9WIGpVrC͍^꜖:^5eC%:׼ȠqSksU{U_=whbv ,1 5E0ʛZ{O!e"|c0V2l۷_|${ܥY Kbm2m `;]aݣ5RmqLyhċ"s%^RWnzzkW/x ||_Yٗg#'/- T`9)^WC'!zr]U(/9m^o}iWwB,A,@X&,tbuvO'lvj̐qjYd0JP}~*Æg!u`[[6MPsi{5>+JPa1 -*FϮX@lTl$QJA*ឨf𾸥RL\jIsCϥ&deccHJ+** -EGNEk@ `g8m#~'=; <ܰO4=Q!)v ->nR+%nы PDw;kU!$5ܜ{j YkX;]W66I-p]^4FΓ5;b|9FbÛ.4jl=?F v̹c>fu J=c>]Һ.4\hlNŒa{ r`X ocGz7F8Wi`O*ጩ` 𸵥).ض(} brydp`UDaa9,3];~`*f %"iT@J-҅P?~Bɳpn/J>.% B~zB篌@wkLnjm4qa2z{09+VCz%0j(c!brTɭןL0(&_VknCctr6 +91a{=J<.J7~{1 wD{BS:n(RMz=[`O~$wz e{>vst&ѧkٝ(7=-|ȉķ3>Uf}\D;x6K)#jOcjaT<%4+ -}bDCKH"<'w>_ڴ蓫9MI.'ۡ3Oe"; >|OQB8j+>7:P19芝L5[H"?F,^]x#'W-ox!w{72<#,!>_h&2Fոݼ4AtK-=Pնm/:-C/TߩJcp톩ǷRa!uvS\߻njo6>Jf_0J?LUi^-v9uk#wڼeQ;UQaʢ-,05RYZϕ؃{JNZ'R𤾛V{c,ַ8_lo;6e3mcmf|̡k3piڬqom+6/]Tbx7Us\V-} ݈j N;[af>hl7g4focma=0wfTA@ f'nq^ӌXLۅZQ͈Y {@_ha F[+Ʈ{Ma:|Kb̛?Due*IyIwҼ,2!lpH)QZ=XöǑo$i~P*dGYKh_ _[K@5 L$P%.ۘPķ-xar>NƄ[Xp*NF߁H'jeHe+2xUp}KOٮOu7e3Ow-4y!Rn`8Igﶴ?tzXk=`Zq:VBhTl_#"W3fy\05gX}62U?=S{U^v|xujV2V뗝؀me'6`/؀m,M3y9p6^qhqh7gdJk5\G ©SvۅJGWq̻;r6v39,J{׮zٴKZkmڙƝ>9j铣Y6Y]h'Zߦ=p- -Z賝?꺶R]YUV - b.A -vJjR~^mHiONn* ՞tKB<_ej%edgr”2M r^¡LK'gqU>7~{ -NK;$9VE>[DjO>Pl`5"dT}dk? a e|:Lh_3On;hUIW:x(K~ .,,X$?p3X[GwOץ2-8Wgu:=PjMB)_aɽ6> \l撬`緰,w>N緰=o"G-Dwu6ʁ&f.T㚌ԻHZ(+,ojǝqJؽI}8LIt'/sjN~L-xA,Ï~{zk_uA'mWm׹9P*OTY]B&ڥ(/ -vDk@1?B2؎eweuQ$yBuVk|eYMB \pp? C箕N &jAriBXv bN+kagGPATh;qtCU/?oůd2HUꌁ"Ʋ7~Ur7kIgGj1<aqB:r;B털_`*ǣ& mP5{PLq -M›Wn´9 GU}]H&׌?_ ;df.yAQhDǰvð$Ը^;E!GFTX<6@KY)JG(Xٛ9<-gI78{߹:P-zo;x_ވмϤ-h_'ZJbR+CZꢅgl/⚩<۳+e)RW{,"nXC5oKY_:pDlB #}r7팥ZWĜ6.y~^px޿q8QWɈf'6=2gYbzzQfo}n)Aax' f~T)qwǹ qYxkBu8+v毎/A,.=H۔0_rŷ/(WD{!r"y REaCm|"nv0n55 @E Xp l`!yk'x@Rpz3Nc|^_q -խ֌ݨM9!&`-B!C^|8[xp|zc#`=Z)KG7p r~yV0-ђO G:eL;7tvcvwRo,⊨%#-PS8>g ᶎq\YZkD×^NdPU-`qjNOËka GjO!@Q)^M9tb":s(leMK]1}0 OwRsl!l8mia.Bħ #14>CB&)jM0WECqpclUZm𑓝!Y{^H ćiDk1F=i݈yp\N>4LS[`nvQ'j\ehH -ds A meyVJ%6'"/\_%U9Q3?b =nä6,oL`toeOŸuӊ:!'/daE2ӏj{qb7[奸3o{^΍BfG  RJ͑M޹xA;UOiiQyAeF"Rxv8qIfp -JaP -m - K4PqByY=2תP:aJ 5B;HnƴЕ:1uR|v$9j.tۼRUDaX/JZex\$52sZקS} w5~mMEm1w)yϯMdObgƓw4?F2).#AHAjMTLX]y$+CqDp)r!+IXm+sxX;Ome&f&K J"$2B!,I%Չ#z+( *[i/E_ɓN%eR|_ۏxxo^[G:~ܿ_n7l_on6Ӵ2nOr*dZl}Xnq%CE -v#] CrCYxk0E!:mOE&l/$y*g))Z Lb8'EUqed.(tنC7{L61>a&xu_z(`& LuUæ@ѕf^Z'm_jeN8$Þ*"%z%;1qNo3+_ځB.7rԤYKVWp -ە:vtf݊/j7˝8JvB0APڑA@Ȗ){mIeA X"ΏQ"#3QCsFZ130-sr} mJ;o *4_!$iZ^ObPbm eDq̛i;.62|]ƽ3m3lt ]n S I!*]+͘2lE!r_IPQQ̈KtG)֠T.d@`I@Y7#N,zlvIIT|OLB3, -&iQ#=CV2. Fn|V@F(i<t< 5{~hﻂQʰ R7 I|faO=āzߺtn( L D:(,Ŕŕ}zǰ#L$t}!_;V{ZQ߀6hK4^B -^|_f/䟏G:sVDF=m=[?{$Yn%ir8ce{]kHZZuH. EUPo|E5̰3EqppGOGwO.gd҄~OgOu -۾}^/f^~x X-S -ƕGidK>b NbO~ċO>Ow2O—?_|FK nD " RǧH+Rt@j6w]o56]?sĦt>~?Kʿ/Z&?yaz:O|wH+*Et/ŇW_|;t}x7?o6]jITW$ż(w;f7LRbOćxoSÏG?4#|o9??O?@h?>w0?cW_]/_{4>GږƮ+OOx@cp_|#z?w/;0ȫQ<1_nQ˗R}߾QC#?H!$G'c/},UuHOmER6P'7T5NxCU?l|V5n6W&zQ FZ8qW?PwkmAkmHEaZ#_m臭Ey⿴_wNC߁e2?g/7ʃ/?{{8;??o>}|w?|o{s~we3)1߇F֖/_/Mvw?_} ̨¿?6<'</ޥ~xg󩸒\*x|c9U&LMai.~}m#wS >=S2!ʃ?yWu6~!ܘ3Rۧ!b m -dNɶA^&m{ɺ '[]m}*1bLn`哷z/d:2wC'}~NGHCvz6?|?aTRn'#.ihs9z+i/v_~ ڋz+io4MsWӼz圞!/io49ǜv}!lگ@n,*5,j (?9xidzIr9kfnS[P\ӟ3^`D+l# ߗ:M tr6i?C2O@ex;!@ OHZ p^Ҫ E*epaT^h}f9Z]P 7J O(MC8<p̬nެ][P!=D\'Mf}u63':vX#~۱ˢM,QU_/yh"@,-kz6X /I_yKIcXv~D~Ʒ]nb2Q0jmbַ^Nccb1}KO`Zn31MrulXvخM̿xbұ#|'MBbEXz1)XLulXvخW/V7iKq?׻xYʉnX%Tt*vb.^z8OLOybߎ{%T<1=ulXvخWNŦ=0ScөI\,{ǽb'ֱibib^yA>!16,R,^oe+ib,TwرX+6U{sc'ֱ1ؾWT/6F16OLyb&ֿ&;Itz`o,{ʋwL}XXvخW'ɆMGVbEˍj1Occb1}䱗_:ӃbXǦo[kZswG. R̻S./ЩI=I=q1sN-7}z$a:[ዖHm˶2m[oض4rZVf>[>;]F -I$SvGOg#݌۴-;pn͝NaZpB߼m.^ǐ`4  XE]RyaXXeD:^_7xlx^>S^|?c[oLg;}?Bl$'& iPH@ϩ>ǯ?o}c RǓe>2ƪeS`jNƘy pG@пy{)#G^lH}ϊ؄vhO6{z&#p q R/H*X]:mC@KsZ:s};|x\.Mt׫E9sjvU_{r&󞴳76nf;G -}_zOk܆$dl%#H<ӟ9S?+l ϟ7X>~B!g> ɺoM Z7!-fN6C"w#ɅPyhX~jN?@^MNN& -`C '8pmMv"~ SÎm[кcԒޓ$vBMNdTyڄsv5,1SqZܮCS~4 aMpڂWj/=ǟ x򨔅z$[W1N%+,lAq/;vvF ɔl؛$bM{J a"+yQ}7d(6 <0Ro;vYGä?F[=B2KC1ho* 6?Dhc޵S-z_ :v$St&n6Xrӯ7,1簣)&d'#d[Ph'(v.Eѝ@e;z?zGS2z] Z":ciCD> ך -lDv&fy:oWW6ezШ?zKCV-@}޿ˢ7S-ޚ*#i-ۗBvqB [V '8*+Dښ8wM!'CiJ:wޙ!ךB~7ˌ]q'-vXv诟O[0qXo1 -~#S$,l`1-v)vv;mUIʦҴV&@ri 2ئenvKMNc&fm"UKŶ+r^Ŷ-KnUKŨeHaѤy.WۏyZ.Ŷ-K:e7 .kLбMدf~o`?^$N9o`y9$om ͔}lY/Ίx>@ Y'༬6 zg}t&Ry&Q֐NjH\ xKl)x*|,>\rL,hXkcPO!!_n;D{ p -]Rn~۳r:M2Ji[ɳ>8zlcŷc1ˊcnm#b#dvY|K=Bb.aabhh2f% &U*@:]ߢGx䋈ޞڪaC]>9 :vY|K=LVmKbnkTC;mh=R;.oG(=,l&l^9Dz Ȃ^ch+=Sv-#e-ب"&+;r B涷NEб[QEnB(LI:r!}nMe-r%쐁 -@|"3i6Be)K&RY&R]| 9bEzvY|K=6H(:8_mn8FnmfBV:DxM\PԨFfӶ$dq(ve-H rXBAݍNOP!'ݕa{8e)+L`؈^&f\;+4tGXL Ӄ<;vAؿXQ 8jOQqgo,ѷK8,yƲ>o,5ʒDK -sv0Kf|eAhٹ3",<I~UI"1>Z*v&{9h[.WZq9)q6e3Kw-rʷ]LÁ@gojJ󄵅d _ -rgqEg0 ώg| . -tƇ3s0f>ۍPc˪ -tƧu&<ׂ'JbE+l.&n)ԨyidR_ vC>T9gO;X@/|+eȸɏ"!7k;Xt[.ogϸ7 &يg ZNnˢqLQfLA; [V8z֛yβ8eI;iT6 h,w,7Et\6JD6]"*ÚpNʰ}Բ<;p.lG;F-U8#*qejل -:ۍS) MUՅ6a ډq;:y\:Z 05p8Q e([0n'upQuk?Bb)wXJ"oε-VގyX+/:?>8wa1juEs~ly$ lTp|围cjfe a}1u`RF(}PX혫,zy$A.^ԁbv5B.NFbQmۓf=(;DyF,Y!V9=r m! :Å[FP*02%1n"u}̇ +/QUfT|mM4BJ }NUvWZv}hE>rO䑑p&1+7D;k VCށIO$cKQz38<+eLnW+IfxIh/g,7}+eÿ{|s=#G}x(tF횜"{a'rVM.~$)L -vYG#W貥]r?D"lu Hgy[.h|miBZq q֍BYr6(o,WF}+Ge#ɼ͛qaّ`dur\o|C68&Ur7 0Ƶg{yf`+h1RGnϒZa6ٶip}]]cb6o8Y)Vj>kBR]WH64ias[kv,,tG~uRiv礧IصZ'e_WNʺ›k]7iD6黺lXkhj"itMФI2c^dGu@ũf,xipihMo6Ma>3ǂgTd;G_p$ S#:7oK}sȚ5]vFf:k -:A0uHEE'9d:Fbf~ S[zo$C/VgS#+Gp;sjtm9N䛖މ|r8ȯƑ -|s ݸKY\]{_K3şSote v r9v,4)Sސ(0M!"gE`,$QF/>J{Ӥ: N ڗf Bf>/>',pX+'08[,wԄSD% fQv|ȥv|ۮ _J,6ƒ~ۭɪp;Lڄ(1 nc#.!۟h{Ą&4cțQ6d?'m~(lgKSsHQolÁ%6!o(LsƪBMq #:p:w@:p:wh:wh <h~qٔt+cdE+^UV,f+ ׻{quOn~/#a J j6Sv,D>nw,=/6_<5woRQL?**}(,y5M‘5L+]HYQ֔;^^82arC|=|}-KHhO򋷞\o+<#Sç귖.Rjg()?o9+SgUK 4 uNMDq둚!9aPxռ4<2a;b,Y0zSG҆ٴaAu?8{[, ( JvVݷ-ٯ+';yj#gְ>gsmk\ad8(BwNmKHꁼ gD &IUQ#0J)e1. 89ȝE7z+$ȷQE[v6wRG^]yHkxɍׇ0W5z^GzVRk H7RЭ HKwHB)[P0$n(omέ]ug[]yZCn1NX)HJDQ;&92hpOQÊjĵ=.HzM+D֦ -Mw{u>jwŤJ컜J (.jt0@I>^ƤOx}å Fc PB`؁#s *blʷ ׂY4^ay͚M[]!{ U8$qMG w܂n,\QY6|Wguh\Z !|0R -Fpp#] c3 3)q;JTKDCQɯf56J'cJ1ѠK*tuGDv1AyP4?^{-,qŵ{^NY2eo4‰qh%75`ؕ&'mfq}kH)y]8+3uuPXg'@3#G>SJ{eY`VRTg]$86hq`{ARF߷m?Nr= ~ӡ/^U|؈$C^ptQMCaTկDz4NkKN"<t9/!y';L7w3تx/;uAR$Y_qokuN:%5r {3[Darj|k;wV<Ϯx{\Q-~+͵UG:PNovyVw -*#atl#p-kYo¤2 ( cLycqta$!}\U"i rcXHʔJɳˤxqBHQ&(qH) Adoi@F*`:P@/%0JѱJ9DkA;ιX鼪i5ESEë _G/G61F2b^~c†8, &~LM8lZxk]2](*=Ss \uTMgک AW@zS@IA7&gU}3fxcmj#%m: cGY<ҘkN9htHIa)tV F*po4%]00[{eZI-^{J tmWMQڱI$S-|TBSE] +c"]*gA\8紾 =qyЪ9J1lgv8%0RՂQ^@Uqw_i(c@r0g -ذ'CwDÂ$FF a*|`t Ҿ-cU:%%HV*:^Ý|Mzu}ݺWw+=|-3gě2d, k,.2NLJ*VByXq29e&:jn :/bcFݤ)W$?a W^V5YQbYS3%󫱁i&Eȣd>\;iN9:;|{"{|[\ tuѮ/­wZjDh.>]c5Tu]p3WBw!L#wc.ح٤#0cԸd~;zKz:ON{ s䈖čHe$ߺOÈ*[ -o,cRa<I&I3qjT-h.ҕpus#IF|d~Y6`f^hD;Qsޗ:hE-ee K޳ >q=%{Jr# 9B_0X4_G!`j#9_p̡dTDQnh<1)>HK€AI>k~|~}ZNw ->o#v^8qތ HNF/GY]+L̍D6NAbNNCEtEG2M0uQgGk:_Êo`5./ ^,Bʣ#IܩShȝsH!dSXhK䤲<ثUd*|)s Irhz1~iقu U;E&AQÐ5|1*9Ŭ9>dbϧ*TY#S8?aӑ؁L5YxGO,$hK2: ǍI|V&_nj˞ e1muuuu.'.j/յCUw"dYrqO)>WvXSݒ:TW]._+װ L}a[:rXʚn֫O n6a{w\#w"Y ʐH72{;$*.TֽZZ6cC~ )Lܦ!Mt.~k!(1d߭DLC6v$Vd?'AHwssm:m# Co (*@Ż܄f7u+"Y>>#E0JA!ZHd)xxdvf%C4S40ij XU,V$'a(X)i-2I' -Nv"qJ$fb\ÝuJLB-/eӏ;d Y[#aq.hgx;21emFi,?++&Gmz8(#R$:M]G~]?׏գzv>gTZb_gM1߄~u r0, O+vco%9tOnȬG^YVֳm^jV{2p4\)Jȕr\iFe~̧[?h!cQl۷M7m<8V/zǬ;wzg-cWqG>|w;]s ( \#6021R * >K頝D!N|Q:Q/ҌO~ږS t 6}&/2.-#$^(QʖRfэACSUKR 哶s$myVS ƚ -'9$f%,c _ 6(W;/HNW2]JTظxׁcڶ$ 8Z^ýb;Q-`zQ5ڕZ{lP6-&Z岭WK|OM$>u9\ -z#^lpdXPqTmBs⥉6Et4]ls\tI|LoGʍw)6k 0N)DŽVUVd(W - N7os&'!2Ge8Gr_Fvω02nr4MW9X#3W{/YI>늯8%YM3l-dJ¢_cxPJQڟ2*e.sNRm\NFHE֚2xԅ|J -d\#K/KOn_ؗvT=%H>/sRԮgq|zmj_IHX՜$:6NTXmBUIĹ"6gQÊ!"9D/U 6FO\`(lXrEn5acXCtRn@HnϚ^GGͫ{Oe3j0m6jEUK~9DHD(x+DfzT{)ӦPP9 SLYbDYMSD0iCZ'R'#}'FvIl+L:oz#8ؤoK <QUƜm͢$Fh$X'I 1:N?ec ~܂vֱB.U 5Yϴg$TSI m2.i#Ԏ2&lhGϒ#wRa~FA(QUhZh&)G;ObI B"3;08;8'NgyzigEc{Z< ;u˝:2lHލ㾷OgZ3!)9LLٰw; ]00~pzaI/KڑxcE:5!/ڐ<&*֪QdZa^'aaXp0 -^>[qĨ@dSiXK-FG2ƱIFYkO.E}TJ@;K,DR/U3`^xd]'$c'T}]s|whKN1sek7<^pUZINw׏8HJoX;qSZ,U "Z86gGk ]J)p&kߴ[Qڞ"  ZpߞKwꮼ#Ł;̭@8.@EC*;sY#P}ɸ̴[#YâHXFKӆGٸimOI0r*K!MFNZ]]+nEmk.~ zup>Z\aqD+#KU%,[I30ͧܰJ5Ǎ2?i'V$RJ299[S+2>隮zZձVZZ\_knuZ6(ڠ!VqaW]IP;}"DtHdɭPDfk1;Ib ZLybsAaN2d.$4W o| kP}ZSUԇ.RUwjg7|U0gmWۯ2S bQW7^;~Y՚V\k?Ry';I$os"z= -$x ^LDJ8( +a#pXz\<ᙱORg,d<;"m%^l -X_ ҟiɮbnǸ_gYyp0D;'ɓdԝ m^C`bH(W>;t]:B䨌 ;q[,j/{#Ƿ]TPiA=6^$^ozGP]C4WW^`zmQ9kzZ"bP: WswtC]y\>5 (hd˄LS0@Ɨ|XHg'}$ɃL;s;7]!ތ"vƦӈ6Ys.kRPl{khwezrr;pYd hCb QXZyyVɓwRچn^ۏO_ 1`/.dʕQQӳEJkf$Tjl͆9I[[k{{ #9ӳ -\x'{-|o 7{}13\B0g wz}RK{sLf< ! $IynÔcBνDN?ؐl RiŹQcgX8deZٛ`VIge\^Q A<>eU0O}>n[npD#A㘾$f_%y-5DA YW-e$OGHP.]wHk^jKUM4HݞcʂLF7q49V!c&k_Y ٶ~96 udtOnÖKop7?eGRi0QhjI?ZEoޤ‰ eD*kG+ۋ gH뉰Udd .x"uKab!-,0 -kޥZ(\5 -R)GW.h|FA(Hf?{B4vTDuDf΄r &Gl%#;މFDzdhe(Z`QXa2F9q $E9P kxI -3еXƫǫ_ϫP!zW6;" $"Ʊ`b_Xs331#ԹBńGG rRS6b8j;$J!XjB),IX4}q%\."p9h Xb@rbU> [Ѳ {RqH;SyD$li >L;jlLTkʫ5`-KZ^?+F1"Щ֠m'ݝu@T*\4v_ⓖziPB2@.gL`Aʘ3f%bUЮu\X4"-!Vo=ߐ*6G668NHJCj#l~ f r`Z8 A41/IqA9syFw[U[ݖץbV%e֕gv UK#m7PB9ݔhWM"K}շ,O:ȘFĐ -'rڔC>;l7#aQ4~ΑFp)cpq=5dz)]BH/0XЀk!/s5(G16i&\I$dԀlK#لzkȁ.<4,!E:R*vuZ,Uq@TsP'B躔e`I>*U @[YH#A,z}O9~⹲|,>xlI$S%J.S*iȰ 6}odT)U*ᾪ -*DA+$Ċ̫۬A4Q4S򡲸W(j`ڲNB r9 r` SSz=9をSkT*h649݉lX9Vꐕd^YWj~_)F1# =Q0!aQ{gG.wc(VBpZW !l/-;B5T`P+\c5VJ6x|={u&_-&?DbrAEq}SN$#/y|4^dY5;8̲: ZU|}5F5<@%ѣKŁDJֽv$jGI'ax_) |x&^ǝnzYZåijN6!?wRhlQ( YtHuE#RMՒ,{ =jEvoÀ l3jȺv.HXK'hWsۀUCYT̡-0HAw'ck>уq3ixM%r[;*xO$8&)v]d#boe_l, u3J %'H&-rY)A!1KUisV PNotfhKl^TE6 d-#/wns÷nG32 F˙k?C3I`8y(0+eXwozPhx2.J$ . `A"& D4!(0)fv+:dsb{ 5KIiSJ^ mS†/j;j3/2sfxYMb={xcaw|i;qg &(0Dr<ȳYvF.NB1r;'`FjLn 7]FkDR-Q_ȟjUܡW -a?5b%֎UQb%qa4J;ypϫǽMp+/26I4LuwpN9AW8]Phoa)Iu]F-0Bo"#vFfZnI+]b\_vo#nnުbĴd$'LH$zI`),9CNIʒO(W̦HɤiU q5tOc5i\dv->!ծߕBNɱT&{J ݭcK7呱*XШ! =B!Z[R?M yLT]2;uMg%Pbޑ Y]R+jZQݞ:xmnۭ -sO5;NB%@<7탪Yo9[Zx [m~D"=ѭsMz9)DtRz. 7[ʜ/2 -Ulh݈-_ !␄>Jj4K? W0ȉBRӆoViOTiL`5=^zǚv^ Xj- ÉȾQ(`]->4rb}Jè$lЎXa\ FDϐ;yҰS> D+H_bQiչnB r2+JP1{Hw}Pv*8\SPԎaJ Zk1Tޜ.tW[HA. dޙ2:~Q*y08NVzc>:H'luqNֳr>e x.8hNwZ~cZzifA<} jNqВw*jG,L8,{̃pMALg $jh)qE`l58"961:C PćfG^+*|Z dM{1a۝:ա*-5_jW{#ē%!Q\yϥAx(rhtx,HLk}')^bp.ʅL<CXtTp1"-112 l;?Mpwܷ76 I - 1-\7yc#&4#`"w!/oOj:}B-:ELރzR#r+1֏j)0MqMWǰBjO2 {٩ʔ $ʼn[myܖE(#n5uiDG3fއUrPeDN>J ֐p!!j*j- lo:I) aitJpq u4sL+!&FUS~ң -Npu$rG3ONwXwpNmwjRە{\b#>_c[yJ-ioXx{:C_bMɲtQ c  Z$W"*w_8:vaHJ'\Bdb)(v#1$=XMhzԹVlI=e:c\aE]DdYtV_[hMsFt 5!\͝ a5OP3m?~U:*4?q/>ڑؑ"|sUr||]ܵ+y}snxV6mfRK~9=aq:Ӱ3hfEd #>ZuP32ǐTG4N2.ӣfN8qzD"0IxBIKiB*{@C9I0qg-!'Q@ǹ)ɁjQੲf1~"s2LwE:VThǑ։C'{F)>&{uiSI1dq{&@"5$sh~XsvnIK!F!\S 6;濛8"s5-t!P&0qtn%$xQz$svqɼotHZ@r3;aC !-p/{Ɇ9T99 $vE|`#(9Z?#, kĵbܸV+eJR>+e^}܃NwMNe~|r7VeMUdD@@Drg?rT:c 3UEDq>X2$=-,ŠVZL[s+o!ȕRx8 NGMQ@t<\]ϥZҬD4 P-]_V.2kW endstream endobj 2858 0 obj <>stream -5'3uJJ04OSUyOcf8b":v{%+F@bXߨn ŵW1d;X5U𚩜ZxHc*'l5 وt%F#mq[KM7j0Pq|)C hdûoΦQӂp G竅'tQ@j$5c|H}th`T;¥q١eFbDD5(! -C2 7ٰ\t<*>QeE8=y -=TŴwߴ*A() Z4%w^0EL`Z hKY OpJIZ#2$8蚪(VEʁDd 0Ψ̰@gS - NYps^&P_Ev9n%=ܝNF긊QRGF&ΑvD^8?>0v$$C%C3dW,X֕:Tىט(h8ޛeKȢ#sb!hrwO:>rH% EamIar#|>H͔ e£WD&sػ×NƸ4-$kӲAх|p$4:8ɠi{rrHCVhJuy4W0؃7Eq2EkivJb|KiYOnAylO# =zuŘ\שK|_|_|_CZ˱_I[5yn4WрοwqtG|Ώ 9 b {SyV j*?s]k)ۍ(?n+sA] ~E۸Q7/݂K58]޴ڊy[Pd,vR;D8D,͔tHI.-uw-YM71ZDZ:xIɦ(F?i!rVk.qx|@]TfN'igmغj8هs̑m1*5Ś$ 2b]$Khs:nE (0c0W5j99QI cV)ݞJV詽FC(hfK00IkiSB0,y , 2lEf;6<&F֬Rg˷g9g7zc֪g:Ưw -GxHgU{=dq;4 0A,'3y<&h*У=&4{E~Iέ -Dq1v`h1woHBˇN’1cxT v-$ -氊fEiG܄}U/3T^4_5PC-o|K[*C*ȇ$D[v\UmA"Bc* И] SM>J?oat / QTx -~4Falҧh6wl -ZbM[ܠ!ɝ99qt _4 3Uq?G9:+/ 8OA4K~X2"WO!i"¿J' ?2:.\WD}t0J1k.&6Q2T*Nssby.):'vs\^T֋޾>[bX>53OqJy1R<,ZIy2k ͒dhiiS7>K Fkj35g]5cCq(}D?74`$%53 )EmR+4Zb49X:,aKjܐD8z$j?%Q)x{6iXa iM)q?|rbi;+ϳVg]zV$^0t3~y]} -o p$gILr6hӣWO~njgR`1xeڏWMJ]7'+՝~ lk0'x(VDn24],V+6[go`2Ȍ"pXUx(}i9<1y˳ZŤ<#&T@|^v֢ȑ}iZ'r=pOԟS*eT^~ƫq$8%t641ul}ϗQ+f ~wolp$1!,^ -Dgz#/!q* -UH4$&mYS0-g ءAk"d=}&5дkj+ n-Aa@XM4OUrOu?% aXdRjh`Z0 r-QI}G257 N7' :IV{%&W4m -s``\Vҟ#>l8C"n#+8G 4q=xBXmEejvI2X2.u Egǥ*|AศZ2iڮ_ڪ+CGZIh^f+mnIyK[RޒO̾@)3sŬ겵Fz>GWmmяӠ!4A\ETl6\(4C'7J:80>zeG986ι;G.<@oe,4km KOt4- i0?o`E7kլM+rn @P@Z۱`]>9h0 4ZUخxe>1@+TT$wM'&{z}W2?dqk~G fE}xEQS#o%`$e5Y h!5s, ao'4Nq4@>$8."R]RcmV,57o͢gk{ju̻4 m`T/AVi -19$AD(GWШ m)2NpAc;d{j%H:FmPb`%t((MUV-}ay1>t480qC>*ЙD$KMiST\l-"rۣ4~ Y}ŻBUҊ]";a` x{82CDó` Q0-ɵ+dJMl :FjڢEHlB<_e?ub7Ek -k Z\0q#QՍ/A,M"E9}{ʻchĘ_y}|V;D/U;% BҵT7mR+4)&C|=6@D3in -ޠ҇c-uܞE3]6*M= -3@2`,i6Uڗ<l0Q87f>@\/hQFBWBn"phWyI .E@*kףy<I<{txs΁<ۀ@M\@7ԝGԸ7_y}=ωݳf - F iՎ8ؔ]g;3:@/+ܸ)q\OEd=bjz3O*fD,7sSY%fj%OwɗfB%/0c,*\ H3+aÙ&ўER[ms.xNW/l}{7PT#JwV/k9ggѺt2M#v,%) &-ZŞhSQ@lA#;c:'w o0F{V 4#42iHtmLѽPs!ETS;my7lEsKhjfhE%{zL83e H'lqHP ^fUY;l.tJ#q+`'{s4Kt󼹡N7ٻŲ~ctϜ{Ƀp]4_q?s""p3 )h 4Ih!-Uf1`aF57_|W.<u~G8l'%Cl֣DZ|.QMtdX:,S6ɛ/:%(ndOّ'$\0R ⽱Z}r>S)BzMM74)iK2|:+:U(LU?}/V_^b)i9ؕ'Gm>hprl"kBr,h ~C^}x;CY{?e!$re%D$١[*c})WTYE0.Q՗r|djYYwi=ў%#O%,{!-Nbh/y}p F@emgV -S^8Jq3ͼ3+?}&)b3!{,Tq=L[Ϸ Q  ;bM1 -I;.$:Olr}t='!Oߺvy_8EȞu_x?Q=,r)I-IL/ŬМeݶm=7Wk_>sz=P,B%: H9 Vݏen/|Vt8#lZaJ˝F`%.(-$nbc05Off!$9f"iW{m?ƣOS?ډ'((P&ޖf1&[Ľs[BIWvkv"bA%1Ĵʞ_⭬Ny;g흕KOƽŽ~<^ae䨆lT9]-;i̹qw >xufBY=+5<-H h_i-ա.qb6Hz;R棿>b{ $/kd`]%I$WzrlzPOʕ5O uΙ2/ރr=;ڿެor|sސe>wnk)cI͹"N»PłTGBuwC=28 ct,y(T>gS/Zvн)|UިU)+;$!$Z, scIKzQ/4ưp&sجWkN8^Ι'=ydKuKӈ o臍W 4Ŏ5u$ -iCuQg"sQed@U0W,ȾP,IQ|~rγb*OL -7@(?A緡wl} 1X8}- u )-ie<4&`M)_b' sz'Ƨmy")(-Nu|;sDZ>g;:{,GGtB/ -Ecɹ J V(ݤ=|F=n UH[r1!@ٜgRnp  Tdc@Q #︵ʺk8X In2}Ȱ,z}%:Z9k}IdmFbGf؍4*1DjFCӴvㄑiI~ gVTOM$3A<<m}( 3LĊ0_NX2U\܊':x\Q1t8mBZ { mТ Qa-Jlz(9:sN{` OTs NSY$ӘMhSkt-پE::&ۏxڠ+ 3|F'Fݔ{K6fE,Z4+bj|qM55,4 p6JEOp҃<}e|;3t=S^ǡGK$A%-"c:[4^z.],$/͒"۷>!a"-ڶSovx|o)hS>u*-R(ƬX+&4Z?Kqfݏ!EօQX\Oo=ۮd{ -z`G•4RqGJƑAǧ;as szsza?xX7V-g&, ^T\Ie7d1 `HvL"V=(Y}u7,t -"\po ixuu({yA6if=Z\Dq#+8R~q:lోV{~eJ½`>&{xc6Kdtpsdi7 #Yݥ@ɂ.0dXhH@+ ?qڧFREccef)t{g=y?Na j^C$3gcnR{%4~p>wHUoE&Qn %WhQv3E0 J3=K 4ÝK '+X@{іj-o>U r߹sJ Yi.97 ᜃIUEڨm?٭\PoԬ˹jwWw,uc^܏cE킶gyqPU5W, @Kw-u RZ5Ea G]vѺF6"ɁZmIBYݢIql옅pEk_~Ş<#1)4qѠ6.oYMoM߫7 ٫t޼zgyS~g=|6}ܱ=mzY A{ħC-lUh0vfuVI=}1h1^pbh&bzD!htu̬熔SF%h4k~Ca` Jp)ȔdɻA\Bc"$ƙ1NqmpߘǤœ덗x^ϻ|f)=KF֬b歑1>3lx| -T΁'>s]*]EvSDyH_R.ΙIbٽ׸ r%ʒ*zȾS^tXB"яq~H$ zwKPEsi(?eMdaMu;=G>9=9ve-;w|LN~<B(qV ȮW*<]{Vd!6k*"Q-[igͪ ҁVbt< ,dzVUz0d $=mCլzG5œWvuzjnjxj٘6L "pr ,;kC~B{8=Cqm}x~{ᘯ71Ǩ>C;|/ (MuזQTƆRDk{r BվB#,ppl X8ba+|StG_'o39y|Ւڰ,U1!)nTIx̻4RFNF`O>Nw^t 0p=V'[<mh1$'kzyZ^>uM>럶R҆nN!ZO73\S5%>ikW{߇=T1휡 3 +Wd[Ov][͚ fxab?B"9򏥓 i, DδdE-N{ΤhI~%' = -N -5yѤ5yqϖc޵\L}ui|ڙSӻ;j 2qT_VTMn`dwՙtnwnsy։I݇v]熟׭m* o^?lQ[wRJ{J+}WN_b.9&3SFJ& a6U1lI<WeϪMY -"1YZ2ថ#P`aЬVc#UoVEm=_Z2Vf)}wcUn$%W^BFȚZ)|hg MAĀGkz׉o'= w^/$QamG'MexFśwܒ[QeDP:fV--k>.\P _Z7s&l׍ǦAb>WdvHƱ^OۇhR:9d)u- keν{z>_#>) #Ohy,}a -y+~$[!SIE(5ucSNf6'i1K *袥8E4u;Rʣvo};,VbPA(p -+TM4A[4-oQle*%4h= P$X1D)9%Җ`,L;: -!ͪ4{Q -6h I]|cg#$@Sozg1{gwf⼹W7#U@y{G|ǥÒfdc4F^"P]HoGϺ-#+T;n|*6BĶ~7 -4EYM=[-CEA߭p%5ņ[hriƟpմMآJq27cNEml/9[CvmNg<}t P0h.B؋Y3i?S!sfX0ئ(h%56'e{/h\6T||N|Rg"_fy,=YyWɿO}Փٌ/hfK&-ku4{I4Ђ+?̖:ɨ.iGKwTEAr?'*h - ^7r1wHsQs2eI]e1ڐ#u^ {_O]W#K&8kʊK{9ECU+G!M;qkt0Q`{3KwDChHXKXyP$j}xЬeY@>ϦqӇE](SnK%I(^\x.iȽeZ/C>pgqц&饝,-9Ki<8pG(L`qs'L8+LSFAc\m2Z^H?Ox38ˁs~'jGLStR[8zj0/su]:~k:hh(NSnףqݬ" 4tTș]@. 8Ftg+Jb (ұiVSNSsB~0*01"2YhLU د8KmLݝLf`&*^!x9IB ؠIu1h@D~Ajij*7P[VfEDYV"jt$2[⧰d-=TSi('#e*RjӓYӡM(Uf%bKZЂ85)uF|NUbڷly-ȱZo06ĹԟEC5ٵ.S1 Hw.XtRʣYF3XҦ#2ooBa}n϶@=id04(&rftQY:emBX9͵/HX]g>fٱa.#G=EdÕa[rCgr*qqT1Fb?mLl;˵5ij]\Ƿɬr֥&m"Ia75SI1XMi">̑dX>"2$IX$USJA$oCnA.O"!Wc$Kr Kd暏.%&}hIC̆հJ}3_gpϘ;ޱ'f={=OQ~yv<^*٫^vZhf\Ճ~<wu³~.<8;jfzozoeϨoH?{ȸEo.2>ջM7hBU8D2@'; CHh*0=W mUp|! 7k!k'B$ZhqQ]hBLt-TCKi) mʸ$c '?ywj3t:}mX3&Lmj=GlΥRBtDǾ{*+(7`Zk7ZIV&dX+fW.=`*{@47绠! T«P)ܠ;ix2h 2Fa5(荌RJqiŕSo7IVtI΀ oZbTىG񀐌$]k&=Mbm| -7nʍ'rwMZ{|&Pw3 $!4Vd8goO9h!&Χ'>eX]j(:y `gѴ!ϖb-m3*Mb$+sZbWE35nFe ny -Ӏ,.m,O@#ioЈ9uM<_Fyg_{ \iR(ꉋh6o'D(oTZ݈tU֭`c1Y8N" 9N t\hq[ߓ@@c>p0jب];qmֽ_a0؝ԕcxYo)DjW'k7E5THZ8̫4IRU~b&`xq0>|pThEˁS҇Р}{J_=e8n6/BS'C]'CR .ۀ _73o _YT12Ҵ]ԕ4-ߴӈ,e1&f0P$vjBZW[)L;S}S<=ջ9ƻ7w7<ߨW*77n:A`k0M"!c-YHf[(Kl%,uCLy.ZqwA1Q1p5К(zƕ?v>8zο 7f&M30 kae IjwE7qt* -qc CpgZqO1'uъhOg]gr;aC?A4V,8E|YO} -IL50_oHwiE m"-UqyJ-tt&؀fO+zvջhz㻉^M<%au" iDCF$!HD?c b8:,!2VR W$g}:/zPVFJ&A 9+xܣL>>7_rgw6WW5I*q+w\|> _7i/>< Y2k 7)zҊ>+8 --`h&BaTじ[y e{]_V{1}.Q,@L1N Vu%oi0;i=I†.ACb؇,~BwzvZי]ɓ*~^gEZ2ws5e[7bbKɖT%4EKU̘<$ݞw~8hV7 18n䋰c_fgN_Y|~I)Y!¬˓l՘WYlz?=Hﮅʞ1Z?guS> fQ[4:x[kӀ2*Y(-Ԇ]wId4whR֌v>hliLD3x6{V_1wqhAi=U^u[}joFe3n)My.f>t,_o -i|bD.@2|7w,̧u)'h/HvŁh -/a4G4Lpd݊x+y'}|;^Yj`CAjN -i%iK@.yX]&fKu>_olP4v9LTm11Ѩ\ZbͶ+lz`qa6Q~:V[}1jVUk =lyhU5ii"3+QͰ]qk_az1 R^ -IDC {H5pų"nfۅf@1k`= L -<)Rks_ox3'Ŕ -*I&A@314s=KShL祝 ?8)3_}=evA_k@Zn 6*>s|pWRa`~ƌ1k fp - -$`.5tфCH)`SCx֢b氣%J2˓Y)|-y͢!qfg8I~XgݜE.4ьvMTZ \WRq+SncCz+碙 e58h*7PstiW_,ZlR{ TּAʐO{,(4OaNc&MlCF6CwVS|+P{uS;|25+]Z? _*DұOKZFkB2(OD Yu.O_7YYvg{]|+{_WO?Yʳ%MTLL|&gqr-f3(.0NgΉlx9VgIM>}[S3=x*8\v-Ug5M'<3$R|1=.jFhT4&e7p%eFưr&Uvrם~iϓ5f0~ɗѷ -?| +?޵~V˺h1]+"{ڥ?O /_#𼿻3YtR51%ži̇C#h/t8Xוn~9~BaWCBѺT >|;7י^#|e_o3 XjoxΫt.US%˵OvIKT-돬rV, o΋/'W*4+o{K%uFϼPZWqD۞_aE`"R[H*&!7¥y|)aRTc+=˒$zfN S+wZ_g/") ̪EubX>Ӈ9-ܕ[ߟ͇7z{ٸ3a)<+JZGEERCzb*]3''4x{vd_ ObV{ݿGВzcj9#c.GtH*E2b۪팞 X4%DZ4|BDN%--^ݽ؎䌽FU|E37IxSM09ņcyz.N4RnhQq-7]'tR[ϐ|°Z=N$ ~Qkyԑ'46Y -<|ͻ0^ʎ5[Ճ(I—#`U+F/yJm_c?&_O\?\)o7xA΂ 럣Fv_.c=mc3 *:hU,iB1,ZkEccw[ M/ð OX܈/ p( ACuMc" Ek0J,ZƣZ6k52 Ch= -Mj1ָx;ЋfPDUqP)0EhԏkLk̿Z޾7_Џg%H%MljbAN r%_zսd_d76Q^*by:V g)lO=yS@p lElƾJsV}ڊ.-釶=-Fʽϋsv7?2 'n) ԥش>#M];mйVLCoRʱ*6Amc]Ng^_M|xt4iA\tX]0qY?M ~8,M%W1k -"a=뚯_;HbnB݊u&,ur6^3 q8a:u<{O+wyw郻a`#ö_$ļhG]oP16)C09&ㅆjJ40 AwXEk*!+p%~sE12wne{Kػ;?֞kp,͖{<(=F004W f -5`Wװ ~c4Tg#ű.HKxi2Wi;[s%=$j{E$~>V4Nq4 ]o+l # g$+YoZǏ3A2ք4DzVq&7h9"vzAmw_͸Hӷ, i{2$| 16m0qzB!!8H[9XЂSh-buc7wI^T$`^ -qo?قϴM.5"-1Qc럂G Ϙ7$ -5.Y@ҺcXyѬx ?YvVbݎ= 2%"6ٮhf maB ,ʟR]xoa[>s2*X.-fdXuX{=ԙ`|dyW|}tJԵ.]1.#3Hƈ12Vd,Lzyi7͒{{]vu;|.:sÔ><ǧ(ެ[§$>8*UD|3>q+z$~)9l8A4{A3kߴv鼆mà2Ll#,ʄ(aN*4YM[Z_4Qc0;t}"YI:lM,c-qҠn򫡦c,kheNJsl:ސom>ikIௐkR~D%WIER# R4O okV?p}aG,% t <0I0b:o_(,|]2%o]4K ob ޾hM7`jB ìЗ>t@)sAݝ-̲"5Uzhuf'EGFmpݿVhr'LC,Q|2Y֢ 4T"N44{;ìVa[L|$,[A-oyidfqCEzZ]5DZ ۯMf\v-M݁}%~}gQ0ѢC[MhRX7?QxE7$,}AVV[I* M+[W:[x:x|KY\#}hC[% Vb&)g-ZB{~bk- -[LH E~T0c"<dCl*\=Iط=CVs?j#""AjmZ0&Eh:%@hy֦ czHLK%B2YhyfymP%lS.g=M7C5Dx*8 J[w"Q P7rL\4a~m6E6yj4j mJ⼑140|X/jI`GCHYluqG_Hq̇\4 6[ |@>v h&m*aAζ[Uصb\k+UVݪ+StmeںZ+*2%jHE^S̯5 .bk(;`VR_#zliqPmYeΪ5=v6/iW,]ߓ|OW~f€IsmKhD Uf&#rh`$^>jFHdHzJ9  al(Z:©X A!b/g"H(M_7n׹mۗxKrZІ"D.:yڳDeIyV)@_h,K[96]&)"`/)HhHXR<`e =915AP%~Va2iAV6( ψ>%/?CNA4MHEeh8$:,}Z p*Mh\*I!,%L+iN!&4 z< )B܆֠,Z)YğoLVc:%`uLD5/V/DdV)B%) -j1ZKO1 [籴3YV=eM[hlE ``ry@U@>>C`mO) -nw%戂؃vW$`'r=Js- !V/IHq<ằ&`7׍E? ~m mW m)hI.кUyԮ@ Vї $kdN*4v44(C@TU`6%@ ǾO:%)qoHb ?7,uT(H^8 -/ |Ɵ7bS<@ɧD~*2Ln%,v;ˏxtwMQ=FGc(ʀAnŴ"XJS3a=tpKkID^ 8&j"Qa(!QNQrqv )҂Ц8Z"{X62?V:1'A2j,Ȃm6]ӾD5}'K.ij,VR?c7K0odŪ'\v#r5lC?vP;qD+)VV-5" YkqoS-%DQi(_Ҋ4k[+ZyEL N,+B'~+/H U0 u_ 0@[vhME*H+EɳzzՐ@-5$FeВ6Z81$GK'ThСޢU7e{pr]؅BNnc6oc6oc6oc6oc6oc6oc6occq|,y421͉@2`9<5c=]dzM@3JŒ/wL cfSIJȆ; #")H8)mbRkj -EKtό1M*(n/*aJљlٞ(|&;PՓb]S0nڑEF}<fw0K9Q(b2-qRyJ͗7_~/+ =*i¦ǥ Q6^y8]tH|DH:HS̷Qw(P 7: ȱ^T6YØL*#˧XA(.3 RӼ1ʷۀ yfIZ./58-=N2]?vOἾ<`HOhLShPP T:;{캹KdnE^*_b1`C旈JmgA rԮ)edK=?0M|4Y_hv-ގz\F{q'[A6OP)u~z+~~r>| Fr ؒ`H TC:MQb[ 3s~&_*43Ht{)Sym{Ļh*P7B^M !e4({I >Zi\`fTS)D郟8TIpP+wߙؒh 1.x vWbk纔ќcڤ5hDZ/{ѭz-TİwX -hb}g C#xsԮ!XԵX~L|=,^=^N5Ґ"ЪȲ$k"V QdO)#G4~xGQg{mKZ@3TVP͏GO:5I^4WAyu'˰ژqf?W?DY=8z~ϞUq!`I$QՄFWއf9YDSݡ7 qVvDܪ<ʓڐGfz:T>$0(OOFܰ ;YZ'90+<(vDVdhXuD~ǢhH:Mn( -s-,l MZ4(&5i8l"هidM{EX<.o dG`AQC d٬>\d ~E${y7`65D[4]9HRd\|o#\Ā76}Y)8h.ZQ L/dTL.喿&v,Q97Pe`'"[s3 7l414ށYgca{1S"7 _m[@TZq$ a4-rـ1̨ĉGM \uc8Om‹ D]wE)+Ț)+Iv͠ײxvpZAniEt,#"(po 37-WxV[[[[wC{pPCZb~_0gy* (y?4 K{m .pS &Ma:@4EdӮEvuߛ݋ai4k-wkfP]y<4kya(q-^|/BoOɮM_1v7?$*p UYmRX֬&y0GN︒|wKHت aoghn']wWuJu]񻦀?}0HIe25]}yÕߟG۶XӦGZ"@Ӻfkz:<4R:c7o}3Nq}"z4RF& KהRS(~M}[If,R0O4QO)[_nl,zkqXGwLAp7[6VnJg ZeU,SHRwg噒ԇ: kCNOY=%H)-sa^̍yASC^ #9t8P+{O 3##-3^a0S}i:pO%9ƱAhle+eX4s`gx8Jb22</5hzoPpyMn sҢPh؀׆l.k+$ӣُvtjUI-uHhxƼ0䢧hM9 =_V̋aI)~:$ZPXEF9)WY?yAP՚@ 8h:8? !'4KEDJXA!jA,%ztÔgS>aO5hѶ|EBKi  ţr$Ft\UI3*2V)YiQntLT,XR;vsФK~v:[TNEbPUd-٫b=Ad8hR@t:Dũ+g y y y y y y  =:d=7B/躜DpV_{C"prLo,!N=D?4 >;#kmtw2@ C>V&W5u畺ޕʇ0{A/،rzB*JCDZPiUnaW^x)4fZc#]V[Էj(u2h4iצ*sHēw (ɨ.-;{G  hV u^bāXCh&ub+vk%TWǕh^:XrGꈵd4A - ;v6O}XxJ@/ -R -yZ+9ީgΏ/{><'_}o3{6~if=OR* 9vveH\&eʆ $l,sPAsAI;ƱZH ABˈra\ks=r]:fqGl^-)daCpq|zd)Z"T'*<[ ]IOzbוίb̎WoY3^}%8y;-j#F9iAiUvQo=9sq>gzq8th>!=PPNJ-@ 4z0}A! I(.5 6puA"K^;m18ecj=!-_4;rbS6;%9ɟrN>!_U0D ﬖrA9'Yrȷq[)54nm4TmDq҆c;,[cC 4r -ow_oj1y VhPo'+D;7vY 4aTIJ!dd/ *9+u |3 i[E2_11洁;J,Һpgf ;N6h9]gk""G[81Ҵ9Ai:.̢,N>7rifj?wSpژ6 6hc1&pdv@0 1@NxT -XXxSVxj]Y3)w S[ZQr6л$2_\8p0F%(U@+ -kuTggԦ 'O3j1Q9\وr5AI5 u -`fGV`)eD4x(U>Wgmwz~Dx%Y$FOny12KF1l)fxSS1hhOCv-։.Fy yY6@ $|=~Zۈ3J/=NzlLfѕۆIIS͈<"ZPs"MISttƎC!rTY%n8r[1ՀͣȢHgCEw]֔F %ug] xuc]wK)pR*1L$fLF,`Ia}2X4] _Z>3gڰ_B_~ uYAvMw8΅F/8#g\psꝝw&NG90ϮγBհY}T>h] zKʩx{o8׋/' 77hxTHtq2T7`캄hͅc3/9nb ATSLV½[)F|h=n7MC@3/gRKXF^4 )_5# -DIW&H6JA'AP7ޜ}NT2}dPߐŬZL PA45!؟ E)jF sװ- jC Y~!Q oCjIDa}2/[HL&W DǢ4m` Obя\SQyIj - θizw{ƙ|Nc;N妚)ZF7,Q4C9.WƹLz3釘CbK(**+apIQLEVlK_)+ۯ0ϪD-JKMgH\@k+S7u+--szK$/$UaU XQ&hq4L90kQz̀fK`HS]HS@m_MD5Ľa7px-;񤪭FyUzԦbYYݗL:su"N ZIz3QoA~yz}I|f:ǚ { xZzZmU{ΈpB4 0 --U>[$Fhlyh\E)"c٬턤 A`%(,I5vw,^T)6;w0>vҺĂE0%QiqY&K!,\~KDAc#+ܨP|r0/ /] p&tc'fsqgɳzN>BǕ{}y+͸nF{` #ONExvQzL4?ÚE9n".褪@ A,OF{5m[P?lz kuŕEe1(D>;~>Т@| ~EE $Җh(NQ&j~' --z@׋5CV84On]qw.0cK2/aa,W)eQQiJoozJ*4>m#p5ɪS|_[EW%3]W# 1 -YP%S\uѺ\Y%Tdzye>/z{h*~?a&eK f[ư?&]?q[% (zIW=KrLPS 祋Y^̆,@,4ʃGJ M=urZ_˩PM:IGp8ŗBgiIMdʏku]OK䭤mɊ7\f =٨*<` -j8bIKLnEB]A׶;4(4jO@UbCwrj"bT\4)'@dX  nE -+;4ٰk,iR:՘76ۨ>֩hSWOG+:+O+cJu>YO7oez.6Sby]x_:A%~bʍ̻wY6X}ͩ^>PK0YxюeyQT._[t}yq0NciY%i(0'WMY^0պku.In8N\ⷒ9Am/Dgg[rX9LSqRQMe"q%'| JW;GX=VL*@+j׿ y-"|iXS:rE\Ea qdBEբfzvqCkaCQ=ၚ\?Q+,`-\$p5QyCd}m-vɤr?/>y~59QHQ:@ v/ j-w5*$^QQaGY)M|c6.TVI|yG'MrffDJ }onJ3TC|%Z%۷%n"u۝f -f똲LPQG@muȷ1 !͂ 4ul&^ XuRhv|Gr&٤4&h ix&bOR[J?Ǣдk/W Q=!_ ,uE- "C(I z )tIo?zńtA͒uqST{/%Ow2B`B]|#kv.Oy.Y-(M? -\Ns*f̄^'V:3"Xº}GĚL؊ҤDW/tJX6V@(HŹ-VjݬJ($--W^^#\Z埰`>pT=~6вE\9Y+66J*ƲYZVʀW؞fEc溵lfA+ڹ -%(3H.VP~swbvs,zE 4tXvBb+hCV_*C̤}tYTO*N]*:g xVjpЃp `.!X4٣(U3z(ǵU>+E=YTt|eC 0$JEޱ\5CYm-0ݱڃ[u> -{Z*DBQQlRVI9L+,FrQ`s",V*2N[UR#^fUaҍuSuy6Z(ģa hG>Ѱz0!䋴Kذ9V_6:Hr CN{=?_}(alNSZADUc(p45醂m]%o< f>Ԯ6*Kհd{{dՇ 9ʬ{J7 (j7V<ї%^W -_ŘtՂbbV6MPNX'(zZjZ1r}Lg/Oy.d#/0ab -]D uN4LaثTaPK*4B}mjnq'c򌉱 2rx5AuYA ɓC߻Wh=dVN@t\`Mkߖ=+Z帕ҊJc#75IY%AG,]@u1VsJU;D|,H3V^GnkW\Wq5NX2|8;Z,qF! &zy"ؼ+$Ww. -N|~<~lΫ -V1$%{'&+V}%~Evou+%oZedjT! b-lYVvLRP/?6d,Y(׻`X -ԥ?vtgKok q)x¢{p+rF`V3LyXDS`lcyTJ\iA¨/?8"Ђzp0*GZ S#(2m Z|S"/@fغhZJ hV -qx*VYQr؜`>JhkV1h -"䤦=q\H+ ,"@^4mƀkx#h4@EsxZ fg9:._7r'iE(<. -%< Yi)C` ON>`+tn#@- e,[7IWzb.;Kr,(yhvb!ڲZeƗp4f NAo{ 큃 ָIC.C ~EXz wSh7_ vݷyr{$ӏx:Q'Y)ȺBV5[5[5[5[5h[cALxjB%M*2d=s.BmR(L—&Eῼ^7ďm^?JSW@ٛ~×ρ@a =$cSzpbf/kSw߯)MWd4 -զC2n--,Q:b\ԛՎ/N8&C]; ]1,eb.@"q!"EY^!@T<*~en[3&Ӳ2t= ~RhYoZk{REYIyH-K0&6-Q܊||weic˚Y*aeXQ4)!?)ROy)(6T.svaY>;y~/K{&B'ˇKwp,mFֿ(iGe);Y2 ctAQV,'*h\bK3;&Z3۹;Oz - &hAjiR /KP%eyI$f;+Fz;O%[L@c66(p -R-5N C Ud|P0O"Y{fzO G.vmwQƳY 7bUiF˺ nqcEumv$̪PAaZᑁr]W뤅8uZ=|E~#sʖjo)qZ٧ ՕViRkGc͍n*6{ RH 50fY@@@@@?`R:%{:" -<Ɔ*Ev'Y7*e ѭe&VS8`RERgv} W#1߇$P2: bpZɈޢkhwW16F*j⃈Nj}L)鬳ZB;?!\RRkEQ7_"i1ǸⅼLRon&_ε?]զ߰Pv/M~}ޖ%b;+KjLց4V [U{pCإ!O[.@̉{ݝ{w[$Q1ŦY$k^EL@c|ya`A3dR94~n5m6|㝴(B Q v׻4<hNW@I'-1PJ%DٜCjN.Xx6)nguw8Om{'d+C|к$TfLR{ 61)'r mok[ yf,BPR ŏݺ&J |(ļ @LBAA !UZ=а9r- -CeQXUKyuK0DЪcW8DonYa;>29ydλ ,I$Jem]7a&!^s) qItt3na\\]<bwوcvENSIRV$6*qIX5 -ϪYn!)*4.DYC; p.(eDj*{uq%٦S&. n24RSZ{;n[=Z)zI *4ׂtG /r.Bjvbx'J6yyMـ:K(niƄe^xwޝo1 cN/9,H% [`!4ShEHճfi'8 @~G\UIkloyqqhY$kruZ0V2b0@{ZnH~D E"AYaxzuD^#&de(Ȋ qaï-ь *cØuUy҄1&2 -$k9ڻv_Sx|ÀvM .|t .뗉]ʀz\Z=lzզ3Z( _W>ŏzq]#58UV샊ӧ0$Fb8@Y4zCM J+Ir̖8"`=[gl[~~_xxn馂lXI eꁸ@zJkM[&-l;&}jعгDLW ô|̌iS^}z>c뛹{Z4YZk̶X$g/Moi+jHkY m6pg i :=kc/4iWg)C i@0n,^oC{gc3}a|DZl-˿!8ln*Z*jqaRJPfN;A~O|uuzw_w߉a/de>{n$ B<')!-I,uˑ,7zӐeFOH/#@Si0>rw9̱\ږ?{B8#xTj~A&4:k}"@y5(SEqκo/h^ 85/74mힵ"yq-.t])=@)P#wn&+ZICA{9+|El2I(CQɢ4 hEi8% vᥕ.>@)⾖笅?wʈn]~}k⺦YRqӳ`OP'BZZ{Wb2&A!deguvs(Y\h,cLu\Z]?jQ6Nz]wg=̙k%-7逸FY2r[Z"۵|C~nbKB^~/3{;Z7􋇄rxu[I@x Y^8U.(3쇭'Q8N /AM/diME1'.4iWi?ul-@Š8()~_}0z mȾqgY`ᾤ;i9hXGR>-XŻiY8zqש*!J2ՠPhB L0b Qb^1) 1lJ`.R.dgЪMoC"pvV, **S3UplAZR bMrIng{~^K / ψzaޛSRuۅQӈ0U55 jck& 8^%-0܉ѼXE/%;i,|q FNᖞ'+ICevne@\ %=t-dF^-Z;ZBVhstR/O.KHYT7,2NN;My$N=-)QX 18:DK>~o;5Jmm̜|/ȯw#ʘ;mGt¸ܤ .Ul :"ңjr+ktkVlK+J#wdɢhYr.qTci -hZG5Z ->b+ -bΓ&^ LqŮ`hX,V>#ud9Zu/?"e]L Te_#umˡ]f !}vϫ]2֝48R&ṁh7'̳SsƳz<ȳvkNs9a {Ng!d7"urK -=KXR`[.9cIbR3Ҹ*Cݞ('5go)ȓlB~=:_&sM\{ !Hf#^"]]]%-{P$̢RgW]Ke[DVtu7 [KUןuswB~s_{d$&<$;WNú-|>6'r&۰j2݉X7EjJŬ o*i8z>S1%x%+NQ `h O)II -~VM(Mub>(9Y?V5f^l{;iwgM^818J cY>~LBeknم6EeIj&f^۠ef+f)Ji$4 t¢#RNR,@Rō|K-&rϷ2M/=NgG~#qћZQJV.ZԳ.fAIKٵ̩gvKaҀ vG]ŝ9=|*8I$cqxs#8j+ IkFJD&,|d9az,:ӂ'M5lbSV.v`ʦ69J Jha`G^tY-)K/S :#U94rOwP|O@A"pIwf;!w(!mg>"R=RuF6{ˎG grB[Wmoydy $'V`2h2JB~jm_gm,4%`xnާw[#WNg oeI}$ =+Eţz߉,O\W#3& hՓ|6n=k9sDvzÔS)?b_<,=aY(K!K2-qՆp7eŽNr|ls|D}Ô{+t˳y/JY -aYe$'psBMy"gKMv$:}&N'X}'ly]^X,N^n;aΔwdG3:* &_1j^J)qn+^*ع1vgO9O=ߏwmrp ;kMM7tA&Av9+~48ZehxHb2ƁP??k;І`c&7 41$Ic9N|+ŽjM1i?}]oaժ(K>4/#$;Vh֤],)[/ o׼!/E ѩ 8.d+u2/$$X Cs.VӅJ?OsZdvH' 8]039;͆o3h`C{r׊;x \loŷ1p%Hc0 -Xa@_GS}ASUJR$J4iqEi,f໢N{7|C38<1 f[TI}u\ &jRK,CKؕK4s}9;tY 7;^'DZ!MU3üI"Hn6aFŴ'}OxJLyNyN뽻whw.ưY҄2}&Z"S8ӮJ!`i59P[ec;N`5-9$8dzL[Y6 [`c~PМ5j4B?\R(AVU͂E=+a.^)#&œMtA8)bGvLbaLЪl5igX;mީNw`=) O=L0؁9ijwqr7ieI>7FUv{mgO$w-4KX$R AɍEb:U.sFP6>IQLc#.}hv7DI,9À_ʦ/Sw2&?C3{;]Q=~,]¬gUaoulacn͒`1G&%I.8Rõ#j{a ١5FWUO$ޚ`.QmOs'[[lMٱǤAlTI +`ly>W@Ex8BOqgnĈd yK6-t,}jL;Br~+l{ tYI>s3 7ѱ2!|wp r@o$3p_ \u=,Ån}م&):2dN SC8Unmd+: q~튀WΠKXwUHA959Lx h>_;{+0Ì.z=qqftE_a~ 0:&w?-_+nwn;F8e={W mY~~\WFoKp+ItK\ezf4v)Z:jEwF~"T;)+i `ןB(|^$E킒$ړ@%Қ&Q- Kਗ਼<ը,sgۺA (~υ3FecB_Bep[8'~v.kt'AMyK3և[?˭wa^VJ.,$:"-+ uUǤu 1۴epVE} -?6=ĕN1@R@T>9De9 t@ՒC[^SG9"#h5!2;#Jd4A'-j -娮Hu&46fwHzŦIYKX E5=UM&mqȲ#Hs-R.ôq1aŃ(y2ѕd+ԳE?f={JE(v+ײ/ nw{>D}/IW gܝ}gO|~qGGO.c3w,OS2/q#'^ōäˆN ^#;tĵrZDS`Pi-tHYOȺ((" ·p 0ܑZkɹa[?^U7FoFgFf+{&cy|'] qρw:ݼywR5ؿZ*"M -s"͉ڜ9Os4 *C&W _ߛ~ /3m\x*h5*+-2T0"'hal4E@X$EEAI+!-Ѯ x.N͌_onٝwzן~~/-h:HV![({QH`%r\FӮN1{]5pS־j'CgSHҡ: I~M+FoaIک{م$D Ħ`m+}߈"M,[) EB!ojɴXO -vs\] O&42GT%ILxb jȆZfJ)IcS&(2 1I -㯝=~_Kwkn9*EAӒaF|0;_$ok|󿰝h-$4ƙqc˶6a M>ڊ\WɋIQuv>4wݕHʽ*!34NƳs蒦joF{ T_2:j,SZUbgBcˢDQZ*WjvKKG/53ۂi8^$e #zP0L(XGyqE2_@$oĊtHڞ</|{sh槦ľCؗ_^o~MvvnlWj*隴q"Bie乙{ ~ߤzق{vDZ{9~e>ep3<3u]bVxQ 7AgHrvnX ?;aj/텽Fay/|]Nwzg*!)#k&}JLD3lNx- 9J;7ᐖ4[C/ZS,+$(g ^ӿY93(2q<ũي}rĎ:.mBY0t3~RHQ}@6flsYU!P -MtmHe䪦5/`̩2F\U^ʅ9ut\咖TwR/p`+33,C?+4|$ڕ5{`UdiC鴺/Խ'ٔn' ʙ<9veOŬe~/!-OByƒi̦? +/5*YXmWB^'|oR~q>$ZP8Qj )D́,xм-+\Xu1T"! $=OzݚQAKhz.=E 򉇆iMYd yerM@ DRVT* ѴWКXJWGyΕ#_LkZTom#ĝ@5%O EnX?ݩk}x^H%Ͷ_lӾޖ; yfFk{N+lwxwzWޕ_|-LaS^:ṅYwjb.;SxSCM}#G}8"]{]%x(V.ڕg}qy]7ho`JS1XGs{>{7~FкJ*&WSbJI#*PRMHs%Mn_Y2.0ɼ4x+^D˂ftL]mj]vI[(cNjpm 2w\\Fϵoy#` ~=<DEDfɒSC- t ]"vyF,@Y9V \Yd+ ba]3O+Xt=8о4+Ƕk~xL2ä;3L yG?'4vHrʊ yE1CZa֓Vk^nA -{򢕿Ef|Ɂ`\O,@EiW}"LrV<I2YG}%>R^&)7{s|[-7&ِbJ9i۰V"r;K,[qcډIA9o~p, W!i>ZoU.ta<[xIbw@PAaEANtOlA RͫN jG4/J@u5AN@^}R/*!b,08|vduz•LRbCR]av=QTG!IvðpLGj(%feHTd~%]F1+V+ ِ,SC!ڤ-4J&ۜF׭f)}Fu Y+gI޹O5:;''sʚ:uȚV2j%2ٮqPkCIzS9[qȝ*A}sP?tP?=kHZ -Xyh-.ҁtp{ưL'ߵ<377<ı^63ެ%Ϡf;msvcY6o X7 @12?rC,VހcV ̤IػRIZ8wjI&~&%BlI X$[xOV ͱnm^T3MtxFEF.wTM sU DEOZMH?L8B3Zh$R4Z7hުS+=h]V$0ERnH}]Kϕb*KZ9Kjh]͚fN9#ahB"Z쓱q.@;9!AJ{A0"Iy p.`Z*?p_4/!ezLUp{B#&H_S i@C2'븦$ś%  PUA3bؓTFgTf\y,A+za0 - $HF*6+Bc~6O*I;T9Or( ]L!hUp}*IA0o~o/3VaHKĹ;)dHfLŸ:YC1e5,:qu!p ८ԛm*wڅg(x=" - YK48MA9XUMnB^s@z$4R.o!k^|s!EOAA=U#˳ć׿7q$'䄥aQOz2ٓݎw/vGMyWBՑwDyVŖw_yj;cRW>\3£^ qP/bEV?*|Z0hE8WPUP ֛;`vjŖJ+[RPVYyHdҎrtRVBtE |#4 tڧ/5q}+gt$ -. Rqo@U h+%Xb;HP +Iכ,Aq;ay@DO'@+HyŌEޢdoGOj"x iY"Ųn~|noAEC{sgW{r,+1itݹ0S4CcB^/_#KI7]|P˟ox,n -+N ɋRH$'9> -3qN.Ƞ1[hx[Lgv25湴A(j3ً7)עP@%c)%fG Z,ja++]xU#[m+,ɵ1 -ΒhD[7;XUSҊ(rmQ#VW `@" @@!D3I+c\ی=Tt$)D_j%9?a(j'Eg nHyW%*#FĝcJh.HF!+F~ FjZiV뒃SVjVT̹('m ]\Ð'* +SҘ=$i@AhHx4Ka+sX=Vِñ |8fhZ@/‹>(hѳB 600%+D ۈ4GCvv"èT]kPVS[E^9` #ijgy Fc:&CdTg"8.\W"y+ -\b3 !qT 8u3i,+Y&m(/ ] fދ>t+2ʢ}Ʃ`ٳǚ%5QѤp"ِJm2.`>@C7`FCTbD}(9tZC8Y&Šzţ-mhG[Sŧ0ZNQs,MC[0x 4DtVWVpaYv7:+;R^XX@5[>@;I6QG*\c[ad!9to]m4h6X0~26.k# -,3XrG"u={޽jjR4&!>ZY /=ʉwO,|?70p ^6sÌS<fzO-kQ4;jM(wl"ڸE1vENܹs}eZ{|_ !0&hMhuc{( -Ф1`ͥ=ee=K8iږs:W<5A],ap4= uNq)gwQtǥ'hD>AOApT?E1 q捞_$@ƍ as4PҊ嗳R>]xYƫCb9kv{ep&dL ߀*nn#:^ԌtAH26|R3:;,-)?M M]1|4MM;Fb}/.Vu=($v;v{#jsd{D3z,{io}S+]dΖ4×j C"2:-eHK㴰pgs v Y7.m$]pd&0m\=|ق4TClfzLo?b<⅏4C|r3-hi=+[藩Qٻ1bfBߞƚ͞P1I:uSPpuf(X AlHn,HN@*2f0wH1X FdYToޞ{ᰐjK:1w,C]0sTV.O7G~2H:$7pM֑!1+g&~VZZj74g; x?SJ1sBT۳uc@e1ĦQb l+z2N]2$d6܄Gz҈@ğ ٨0u)ӖqI_jA ~ ֟[wvb64= V߰7P j t/-'>V|ģ%9eW8LFr[hLc1v AbFaw#u!}cnvo_zvgzvwܳ)9;q+=!"OfMzRғݥ}9ANsɧIv#h~+hꙁ&Z#$UW[U]va ꩎J 9F@rG'Ag{q}T) 7q]hD4h/cʦtiCNhhBo|+dj;IR%qrTZ(I -7pTkE0R5,xneQZdb-ah'ۛ-w -H0&f}44kc|Ew4仂P)2krl9r/i={O]@Q -CHɎ&܊clOⶌa=%yH)2 -HGP"hsE,l{@\"59H =8'IPA*.FVO_FvB" B]B9IMe3-e;i7Ag<U "$Ե:m*jz?ө8$ň {6Ps 8ϲ @:VEҴohHR5yau][cY]4E[^)ߠ*Fh@o"C4[C4KBHڃsa)cˑc%y1](6'Ŷ8R'v9ql}Ns<7g (OôzH 252TqQz1gN"MR0 3Pfw NYøp+ÆX-s-  ;*UB[gek4Wh0ѐARq -;*b7XRFmu:YEl׼j-CzD9' ׶7 .z׷_}Jj~w=='d_%iqX6ii茛dуKq b fg1H#U -4kqY0X0,%Ɍi@rTA3$2bA9 wV$hd h:: Zi: ۘ3iX;N ̯yҕ<.[v '`S))K1PZKzxܳP @<’Hao,4lF3C \C )vuI <ՆHH4%DNSUA W/㚵>o=|fvLUBk -ou) qXaXo6Fk9w“ % JjCS-R'ō>J4և n*!c27 o]׊F[6Zs'J3)WI`qZiVUi򫫽\%BGe4= $bX1:7#Vx{|=}vr!8?洋{9^.s9^^5N-¾S۫Uپқ?P66ek/Q"Q{ÝÁټz@f*|tEC`N\& J=^h.$Y-J'݋7[*m^7ވxލ}-m^}y^Z֔i &=q'(zufRyK)Lwr!HsV<+H -ּ#J-`NI <㜾Y{^pzQc.OK,y̗6 -ґz^Pl{jw3.ͻ#C{7KבFWp+O=Vbf(wNf2b4x&{q9??om2iYV} lG7S{;4OKO#z&EZ1_uaKn$)m4?v8ەfko4~Y$7ThC!f ,YkFɅIb[J)=VQM') $T5r^֊uCltn%ڵdMzNs4о s1R@;zvkǩu_Qer$vMhL'yV>|9>Ovzӛ\mn58RU 1XghRf(2gP+Z-(١^si1xté$ -ZlgViČ"w h#a|bO{l>FT -gK-pKVxǑR0+=ZC$kypvxW琖%$ VCf -(5\5r5t?!gY8Zūy6NH,1YEUMZ`F_~V0ahȑ5 ozo~μt'}n^}S=H~ђWܴAR s.au치}WKF`T{7vg^xfgxfgI5fhi{yX7˚Ճ9Q‡Sy8ߙ?b@-u^ ?weqaHR$F~ Jj8ߙX/xBcW=;#QȽ[YeY X.1ts!0Iێ|SI{N{?DĺbuZuh"bH)M.yLFfrUi΀؊f1[ hl]2[+Ԍߓ=xҐiɛmӖD4k/C+:C«&#ο> &-4<A,Ĵ( YI:a;+ZX=.T8bNvo6oHڲ5S1Fri׺4o]rAS$QRRm7]PvьyW͜h%I1]|XNٮn\p^0Λ95ϩg&wȋ'{qg/>ű(oV> - -GLgQ^u]GtI_uSmzz,~ϴޭQm;N-ɶxTӴzVTQ>O?01o(M/DL) 3π = Q`yg$~z{xzozZ -?ΆB -bՃdOdk),q4ˢNZ:o1De)a -Iд:K &h3hKX|7A\V˜*H]>As3ށ]/AS$ -q0Ң/6#uAσRs]|:y WMRpՅУຂ$| $>k&7ig$)q*Mc.qyΟ-F- N =h J'MЂ(X;\YņV 9)gYݓ7,ʱ6 UD!zù 0d4,0B u )PBV h < K[L{',<0D1D4`6#"f0L03iUBX6gDC9Qǔ!bv,?"{A$hDcc -x<$6|-Y A x2 (fG -X xH(B1 80-i g|׎tv;x.25eIoteĒ8O\5[nE4v;En$z c#V@No.vD{;mSy#,axQ !";# -"}:϶Y~M"Vd*>wi - iYYQi; pBas_".+%8i/nТ:QYAvDgNZMd'z\ 1O9b߈YObE犠VGeY ->i VE2ZGI#hYC -,y {nQ 9ТtƠ&1(jYtQ]lMi_& CU1]Wmے}c:c4-S4c_Wq3!o4ciդ %DeL18Qq+~AmņKHIѭDžN+i-?@*MI5uӄIpNj` gPaXѢњ &έHEcYa&G1D-%1 SӢI3L 9ѳ=;ԳW=v=;yWz?|xe/vilD;, i0[i>Ns&jhCi]L!! .^Mt} چT M9=p( DA f}c92iVmHbW_2r);TO*f  %'G E2i8 +8LƛKu*H 7W_w AYv]XF%&V|7˕d_Xv q\o=&nf}ڻ݋;̳<γ<;q{1c/ǠXvB{>&4yɿK|Lie;K5fa{>5tVFӎ:bƒْ|xbzLIܿU;#(c8H^Z ^O+ޖ QMa:rډJuO~) -ԪHZrg&bFahQ9,$.uUB@ n\w -xYˬR͢L>e*G+ >g{SaA7R0sMVv x$k`i"ԀL̝ίvg"@kw拴HuC ¦g |MG%L} rPhn汚)~, -~}/dxdye6HP'~N&ªe;p%I7st"2в F4"T$)/akr`l-6hmX 2F,\zę YV螳ݳv-4n7S/o;744j+#; 9>stream - '_f F44*Z b_S o)Khe`KB#% -Цp&y8Ja~Aj_ -|M;_@0Z>lZ:HSQqĮ?%~ RFzP+%@vNsZijw*cP2OX0f`ݑ0@ͺ/TQG 9O۔|>VRIUTsU_^u_EWyNZe~Mdٹ^ ǬO;fejd/_B.:sKѴ(3WE%nfvRx{ -ѵ9n,k8GAPg{*6ـT+6C -4,De1F'ЮP&'Mۉ3'@ -w NSϵC|m T -]I\IRYxvS;ʎ-K4"Uh3ieAm"NU|#>!1Z!%M;SڂYp- /V|@;߇rw%$ҵ%5pҬKLix㰌%נY j h0PiF_NΰvB$(2]SW!tÿp2<< vtwqC\M4GF5]]&o,X,KI7@*k/Ѯ6,5h@5J1N[[]0eH_q5Ø(1iƲ / 9 ̎p{Kq5^4c'AIpjaԫ"1%DI8rޑb(SC.Hs33fA 9pH/ .ţ bX\N$AV&d(){f"Ӫ`#K0 CCm<-gG<.#\|^ɽp%qLq;XgT="!iI5vC!®2 x@ OZkpS΂rA8(E1 !98@:ȒPz;<޽A}sP?tP -Cߥ٧TWU2u#EZ\E{hh-Թec>7 拃V##cؕ$Mھ4ʹVt&mr]@2$ -<5WaOpTUؔy҇ta cۦ D C'M'JN>@-Rl1@Kwdtvi:59e%MY-^/wA ]z䎼.*rt&;pT ƍDɄɄ1]pҋ%NaiAjj(ںs*c@Mrqw1g WC heTT*eL$#H[\C-F4`E_ xܥSxkLsi Aj#yuҒNC1/Lby`IBVsq.94GSD1(V;fEU;kMg'-}oB1I:lza>A!K Z~}^c$ԒnA3O ~lP}@GBa #P,B# ͂eT@rً -S9i6m)elD3~MNHT1dyƴ`Dn̙w]Y]ZVQc]ʫňBO -w-g@BNg.mZWwy#GG8}v$!m-u @NRC -OX4 H*@U/bG(>@pHd!Im~C拧Ou=Tn%j`2ď - -ЊlQh&| Ѣ xO!ntc$9.ZRFZU% EŦ$$6UJH_"XX̅zE6Ǣ^^*a[>pzFS~f(,c]rXlNeR>@~¦`Xk_EaEIS)/M8Ebʉ"2kU -_A .N '3g)+$w,(\Rt@T\ G+(e!K "X IAJb` Mˑ/;qFuj+ -a Tt˼QĜ4'񔘥3]}H^.;zXph;}Xw< 1ADA5O ->H{c˕L@K0ze|;!HCt&gT -#^EXD"|PiAcМ DQb -b,sk:OI$vB.*'I ->-1ZcSj Hҧȁ0솑X3V-/dr Hk G#[8_G.͇=YLJv)BR jԎTTAף~ȘG<217He"MQZߎUrJ `W&HmJ'zxK1'm5`}cm 4 -}O^2TQ~_M%H56* 2E=IA)@YRYy-z~B&-] S*^F"Hߌ닒nݛF&%hI-֐iۢ4ՂI܌}횂O!렎*FMvu`T\SI "dR7ٻ忁TM9PHIB -? Ls+*(@h,G:+wr, J"^"tvn 8'9OLĚUTñZbE/<7!5l4RvDG k*]@b,ph$HCCs祈25dӕx;{Sr'|s8w78NzJCs֙ s7mMc#1G Gp:z Աep[fY$qa"UIc5F.K^lMUu!MRK("b>Xѻ9Wk 98'Lc{qB:=Mcb>~Ƌ(l*h4gmoupF"?1DK(ƵB5Ipgh4V Ji.\0F\QZZފQL&`h!6)EHQ 2ijRA&.@§0R2)tkys@?~˜`Wy1(k,d! 3@07]W3HIsXG!Sb8ռU6?evA!MstPI[DUSXXh  эm@'j#$i+&CjXx_vYEm.\/Qt0$ymN7s/>X?\s_LÕP>DM8DߗH̴ޗY3 -Ox_?HIұ-:ZD $.=Vj5lˇ(׼n];wϣtq{M!Ls_,'\ٷIH'AˢR܄-rwξ=9;Sw=w3dCQ(LZE% pEWClq)nXw JեizCA:4QKA"x4RRk -{0,1kU>jD>An[[ -O*؀Cb JJ(&B- ] yp$4TT5WB!}r6"hҶc`˭jAl-ǡ)6HM -ֲZʀK32wi"=$E"N 'j0D~,ْ4)-M&P]ST!KV'#t7@cI3_ tH->Lp0f%@CE:'IaAb: XBm%;zX ǿU3wdB +h63}}L]ǜQSzJ#Ƌ 8!5 -[MjAOKPvNLԀ']Ia.Hm9!v# w te]#y<#s31` F2G0[:|!e'ZR5OH>l$$ji{TL4pӚ4LGO3@4ͱX]L1m*-$eAզ -aFE2%|lxC{>i!Jia[D˞CR=]%QV^d?zzsb(EY9Nb8T.:Jj/|M9Q$@"6Z̖# >YS}VH+[ =3Km)kSI1en"F(8gc&n"qV%F L0 -i;M2A-Q:OA|eojrDYn"i8 $EZv_aˍ2a͇5oqDd:dw!0JRrޮbwr.\RݞZiҗoҎԅV%ٕAdVD@#V hˁIqU/3D;'F_cVE"Oe6):UĎ~VyE& 8QxWuוҎ,w$r=Kנ]@=;R}X]΂RZcv${]') $l1`aVA]%P4›M⢯Rn$Uɀ% FҨ֮_,40&:zp.vI(D@gCgjhi?obqlg_FBbͧ04(ÚkXzmiN)Rq4c& 갫$rry X9g#!QҍW\K{O1O{tBJuz61 2( -=R#@P?qQgsf} -Gq7V"/aPPwIEIu7K`.,$)mudtv]vה/,>C(C~%@L"g^LꇵyVa|wCwJ9,8l8!+(c_Un8kEmc%EvsOgc>s3J{y8!!?9qKadH'eM/QNQtuxй4ݫ DJhoFpr=X^pܵXLfM@D\xʒPuiǕd3eqQ -`٢v&YNA 6=y.jXN&m׬$s~sF g䳁_S  )" -4n/)JKe`a4NjA)`j#z+f 'J59't+J&pcV@:L*VL -HAR&)\# -$$`ve5j*y.yU1}&$.W9SlPO"ae\I*^PZ(HR#o%F&Ѷ>xto9t '?>zOqrlWl2ʑdۅ/9ū+ } ]i%O4N$ac! s2@ULwJL T҄VHL%IcsoU]c촀@# aql@z欭RSm~l$$]SJNc-"Ɣ㙈 -Z*Ί]( ;5G6< lPl -,V/ j!439R o;'81z1n8fv|ŮGy;.&y孨 Pv<ִLsn -Goi8Ezl&ش[ aŋ@rumwa#F,;yS7Ա/"J47NZ\dͫ4 -w1iZ)Ԃf,ş5h$A;EX -Gd3B#^;y0<50sNY8_a4"dfr)]hMHZ*|ptb{Y^ok|}0b%W\9I$<T@a;Nä>X)Z7V޸ݝ 'xocfNA~?D7a?U1WRhD8HA`Me$Sw86Eiy0'9SUMHLHNog9@ro]&eָ{b -CCjQDKŝ$բF>H%`RD褤_!"VXiQ3K(;gWlǗK'qQܛ9Ï[~?ql+}@[`=hD,,ZmDimstd[;+;Txe47d0]8f;L^ YiV-O+7_۹aJw=wς{dO֭cA#Җ0[ X{L8b i@K@m%&Pj(a~bž8`%r[F:͛+Ӌ -n_kniBcIbЈZrJ'Z@v*=U)@> psD;ݮzʢS)zCo+}[mL 5i2\BcI*itmuo?7~(2;XGTD`cY h$m\)UFdxo ؖWOݤ"k@|\ŴC( yc7;hUCh-=#hq%Cn2GO//NxƇNsǐJ^o+Zc)ԋg*9aH%YEsW&> HD_R◞ºcaÁ8i@w0i|l[{a}8o*xG `(}vLy,/$ 4.ǡ?ڋ&ڲC2*3`}JB)M 9f%ɐ Ao XU7iyU44M[@ĺ&Oϑփqc," $ -%s^CI.Zv7 ˕KswgA -'Yj ZU&[,.ȼ?6{'[~v-yW$U7wBQrRB X5%I4umcu -c -|=8n- $[a2pv9m.΅fxĮtM*Zlo?uK1 <#g%ƴoto_wSRX9:9+ -u(sՒ*tgvKߴ?!-D/$LB{/^ࢂf@ϥIJ*ף  hJf1I#3UƵZ :b^ -C)lchK.jCR0z(( 4`5t. lz uvm(j# HüDl7\*=P Wh^qK@qSMa ڕ0/>BtXWd-z쒥p2£r0p9)SLBIk^(I-)L|I<ԝ5DPuaMٍG^C-Ҷ2j$~1yv?3" -9Ӱnj@iSviT#TkW;swv#;̕(P ]LI_D_Zym?lg\8zDOҗ{SnO8Xsœ=ۉ!Ec4%ɱU=NNzdb徶@R}+fpn]us1,{V+4yn)oo~ul=ZJg1- -'V[Lt>0?s);H4k 6BFP ܹشtǟd t g.qɟq_{c >|8`T-Ŷ\ymJG~$ռ?XhG( L)!ơ#8eHIgR[e]7I4u=NaI/8qc+wI=ȯ'ەC@+@zzHv.yY=XL+Yylč_vx9!9rNv&ݓM -V8oqJH+FOZڛaօBct`i/z- !Đa$vsi|[pP#tՎ%3+IڐJ{(z|>ib7Pp'6-kܛ5+,r$RmHFX)w&(ґ9 7~ @QBͿs(_ʰ6 8IhS-۲l;L#>ErWD,r_b q!v u]hʊdzYﹰNW{gÌ3fB/o^Du]j\5\9Nޠ] :{:EzٓN垈]=|9C72̾z1JҚA5*MsUuD_Ӥh hĻLj- zg[x!C} M9Tno`#4qȀTB#a ŚZ׽Ry?wEhUJJb dڨ)TֶQZ)^zEu侢s4%_?DE Diɢ ;I?m>.b^4GA-3DCxQ`hΌ)f$&+ ZUrawYܭp {dm;ɹ͹ҹP[nS<\rg4WI{&n5 AOu)MLY)|i)7&4Q'+Bu\i -k ȷe*/$ލ+CU̒I_s6;CԜʣX1)UIn͈$6L)}Ww5߱\a+cQ/SkKFt`>̩Qס6 1GaJ(`S,Y.jW'Pjy2$`bT, -f0IYю(6F$_”hdR C$dIBs:^jhsw4G3./N˥ъ#55HAcR8{ }f,I!X˖ݙmpǟUgRs2 QLyD:o^-Ko5˭tYb?Uw/8D1[HC#Iֱ| QOnN1hZ>82/a$5ZG;YNmoN)N~'UV|ze([/qKED:pٮ'sB|5;0H; =$YϱƙzIf~-VKо\5i=5S1&ҫ`wJxtV LZW U;bӖn10'g"jZjӕ>;|.%?2M)wTwW3sFuY6~}:PA[Ekq7.\ȗ3i?3>,(^{_V$zQK$T,Xry#!=gb/T}|9cRV `ܥ~"_&U{]S<9e{S9 nV%R8^0؉Jy߅?,߸M;LдTXCn5 -'6issЇu7T[>-$\Ƚ@PD)2gCxI: "~8:89>!s~^Cڳ^|IEIMdp8*iB+ خ2+3xW6s9,^Υv:{E;{&wvlS^c_0 eƈ5!h[܃@uSVZiS}C=/$f&̻Xŋ!k+EF==&ΝLEO.2,700V5{XJ{Oϻ@ᲇSCWBޙjKv{W~ wvd9Ig+oʟ5i[H/BEKyAKHػ5m&Y? I\RI,7Ьw -,hۑVQ-[i2Cw^":"cjfw-5{(htāgf?==ӽfU,c_tHk镽vvo;K *hR-AqĂ3oE|E?ܖϱ,((Jq䕌`1hT9 +^`|6:T6p00 n@a//XYPy:%$I=4. SMI)S]Ao9݁n5%P3NZb E/ѸBT%lP0Sl6I]Q}b͑+Aި?<ϢŠp{b -ʳcSeMҟQÑ1 \!l325?uLlV!e3$%s۪0S,"Q]/JAM߽L_y_E^`WiCf34Z˅`2iUρ6β+ `s9:*{yċ?;"WlAp8 ^å4Rfӌ~ȻШ&+ FWK_2+̞-lOՉ(eE;Ou~vj{CUfZA c>F-H3X˜M)hI HͲi#D[P $loŘMse8cg7-}}wp?[~*9NK)_Uٕe -A q0G֙Ұ (5)3p.vY;R -`wF(s/+)K +ic etű3fMA$Ib$i?vGe %h~!݀q$ .$( 'tAĮ.9tMJOy3nQ:GU}h"Chwآ:N mA$7rV[hk9A=\ 1=U΅\{ݢmۅy{d] ixTQEf3OHe+!~,oux$# n?zϡ duLm3ZSUB[43;[hMbͯBÈJ{}ΐgջFrZñ=x_Նu) -,n$I :4T,PJ(*,.cŋz@CXf#ԮKQz&}_ҁW c#i %65M>ŧ2u3Ib;K9Z=S@PVrO;Bb I+˦ڦfFR#]qm[sH%cV/2H,[+BdIKSc *%MW`ܒbk^b7xYt@uW0ǭW"TbVbv.Mb٭ue&q5\Ε\\E**îXܧ=H@zR }HZGKl._X$NaHSP؂CjQθeg,7R1sNt9IJ_?5wv¸T=Y#]'RAO+c"V-+9tN{GxfGreۛt'KwHԾ{7rv`uN4rz[ ro>v֠C~F 7߇MŰ3A ØTҡ4CգǪ.%n?{go3şBG™;-`]_ f&M$he]G{D7Hy)B&i95|F߬A'MAg@#(2P@Z@ JI?.#q巡d"GH9u7sUӅrX/2HUwI9Nz.j2 ks179д: -$hD wʁ=_s>` -N+c+hЧA - +y$)4@/4 Rc:` o7$}#/ӸW=.gJL] >F4MTԗ޽3qTnZ(HtVM[fU-B/;aRMW{p$%(N-oZ@q(0xN/!U|PN1cBXA e^,|ĴPӠ'%_L -ZIBc7P21; $rV5by<8V3\3LakXGDKЎl(-gW -l)p Asu?\pg^Y.?=<zA)beT\I6@ԋ`a -94$ޅ72]4\dU<|@IT>:;d?++_XA3G%GDɚ0û3-x%5liP :h_V C6r[4k(7o&o61uWytߝSw^:>L},mx/k|zϟ -G*u b) I;e1|IWӕRhOW9WJQ^%gӅ<6ۻsy.<97ǡB^ q,;è~Q?lU$:rbc'wfž-hnLlW5&yݘM +jü%*кu˚Va/^AnX?x۝ߵ?W}6TdmGhȇ֮8x]EL!+vߍA1hyM$9=UcvPCrtR1gUm|֮l N_X!laW*.(lơz*ю)(mcƢ7W}n"HȾ֬$V';81,|*&Q?LpYu4-bJ(rı^E)C0M'L7MghkiAkV5Gõx?$ Dҕ4h -8վ/׷oyjٮc'T -4vbʪCzW6|Xz71=sr9=7a]S1<,qŽ&RR&I u޴r4xIἣ ţ0!(C@ș7 {,>i>.;k VzH(~4Jݼlz)ySXV vr*i\Yj: b(jfjsPz$'hC:k9dϊep%15l8UJ5KK$i]tb* L`y!eqUF8:ma\mCs;im^})-jX_Q~sӠkEKVC,7,ɳly!.3+Y0*զ3I( *VKz- V5S) ZCW O +ǂhN,A&ԿrvYڋwo0z"'V&Fc3" -`b?ZuH݊v -}!܃esqZ1|+"_Vv܉aݛ'~X_ >?gX.z0KžKGݡvD\*K3Wf{Wy^/-/i _`1};4wɝr韸^?[]S7߳*nԮ ;&5F:ɅP:u!EP谇&bS?˗ |-Ͽt|?g3z=7<{b;<ķc<{ǻzw{C%^5>'jXK.a={\8xQųal~rGU"=k\B(NL`@j-QJW%Z(6jd-Gj&n P}p0ծYي%i[_`" -{~: -Ea_'37Sd>Vf>WH`G@W*3dM;@A#4u43XA[$`SSC -FçB_d6z }ʇTR{x J:.z:(r`Cei- RK ZԊvH]f^<"NCRgX $}X0þ/5hR)4AP5Ȏq,9֝}|Q!G؆|''V A- yf7Mf6̦` 4՚iͣ[(3Xա MD J/4t:M ãM$JJUKܙZ!pFhC!>Wa9u$X ޠR1`B 7:kk, nSl#ʮ⡞sx7j+V -.$[yBdxv]xh+ -|, -hp 4 ;&,1 -,&n/mOeȐv|)ʇ]ڕ܆I84| [ΥT)'j[cW)3Amxw?n)~(Eבи߻wOK?EX5#iԦ7)tmf:|JeNۯZ]fIak1m:tY!;*bmg`4]BtI/brV(~6{7_1Tqn/Z;sʽ"}("サXbH8X^CLŽd$pt'i?qσnM:gM\"Ն.;A(7JҴ.hn.ͳL 1@cY%ff1f^-.grS,1<ԫxX(LȍB RR8UyCЈ#Ƒ}N8Ծ=\|q8hSa Rzi T %9lwoaȶ Tdga -[v887@gPr`9d= -\pYh8yB40Ā`_c- |!v^뿑p'qI5ORғSeOVnW4Qv9I+jIsaC8|TL-.4LC}qtΝ>YL1I$<|62H4ߜ6}m#FDKsI7L7nȥw;aS< 0?u=kaGlRKH06&j_`/k -)6ni wgq{G4=WhLܙWD@ PSgw֞grw ,知 hsR<8bw)jgپ\['F^ gZ9Uո*)0ޠ|+kcRԯ{7- - F]T{Rpv-i }ٯL겇a?439'Kq3"dHSISewB&}Ik8Cz&/* -ѺM͐nM^vYj@ks %͐,g!Jrې]z 僪W‰Oyx|sGJ-ґ,;Dm5%?OI`<8a4 ͑< h_5em0dJCU^V}b1$HC"; XS$-gERPKxjȃײ뻫2i&QhiQ%/OoOYRq]XBdFV1dT{55*Fϫ d?039xH0ZEtyl9&Rf+~Yq_]0ɼmʫrsˣ<Σ<Σ<Σ~j 2Uu Չ5kD{/ }r?GܽvWnkv=MW0w󲞩8GCd>|}wJB lmbwؿoA=o wB]` jt K8ы=C[C0{ x/D0Y -hT,l_&Z\gUr1y'å~K*)0Z~&~A im rAn!]C <UM"ąׅ Κx..u#`7絺Ts}5HAW/w6ޏtq/rG%pAZeniEo295?gy9|Vg ;D| $qT%R-+T~R$eI -1wNJW*O]۫M1/&R@^lxSrdsǚԢpԸ"3IjjMfP$ 5YHC>NZ9TNV  6"IZB#e%$U3&L^06&Ҍ \Bv9~VH2:#xך@tx4ل]y>|{$*>}״SАKP~O1i{I u4 IJ -S`D0h>ǜ't7(r7K6Gy6{C45<"YB iHȚSӐI9쪵N/ yFCSq)9S=챗{vpu!K[Ĥ'ItO9?{/7&S֭it;wn޽{ru~%ME}s'Q@HSV86 zJ#Fw@cAM+rM]C\De jQSFRVo͂,ؗ5 -AAͪstq!إ4og]͗i.cZИ۪e{6?u! .URWғPTyaBzhGw6,,`_yh΋e IZ*-,sٻu  -lLnW P(P C -u@RbBŽf@/轨ݼy?=WSdJ)ԗx0-8 j@$'[&1] -nKit\~"J(st Dox_")%Bo=c/0eDU!ήrעYQ'3l+@qfX$7YKUՂ; -樧/PžsM މ 4ռ.hc#IEA@I9߻,?ב/z#syxMڒ:2ƚԝEbEX -rtP48lصĝ{bn8ܮf񗻛;Q_5$)wLZ15Vh0u?{e> Hu2i\nk=-*>4i\ iˠiF6;䟰:$/f -CM*w]ziz|% ׈(pdn@+k -1Ȉxf0&rb=_U0A># 9XBgc9lh.a"SLCݺ'Q M<X>GDd^NGOܧϜ"hٻ)4TBZ5uj5i\ j12rXUBsaXYO& b{`wbr&q'CCWbT\ -M'-d -=W$AtcX}޴țs_Sh"tf_iVU̟AHHk8ES৤;Qx}FH^߾?wŢM.2_FmkJвTZarHz'ob_}Y<[?ڂ9礖%o]lИ4b:䓤gz>|/?e;<WOΖREV!q5IZ2V[t7 ;o^}"ѽ؅H–IKj8'(,1JjP!1Ͻjwg!%Z]эN -P$xe 풧.(eٲ%9it$VMS,`yhM ykH{-Wcxfm<;?؁CRoN?2oLq[_oẅK=igh|WI+%}Uf u5WIv'Pów݇xb5_dd^ e;Goт -۫H /‡~Haxb>؎Pw:vޛeY\- 5ٕT scvd -{Sg5c^fhr' a Q!1+_wW{]vqyiiwyp_9/v!nTFѺiڦeB_eeec1Q)>a'dpNX> zd> 4݁s"&Q{L.d:o`Aۖ"稻J0hژ)k:XZuCJ N4F&}Jd9tkU& -"ر`=썝x嫂 %,lqGǑEzDS|> FfdJ:WfL)"1Z N̪kTBWue7X}r˷c&~sf4WXM*.:`u3 -o6I5Z~2<ݵ/gnKJ6@h2,b}ESdZ jU'oO2دx*d -IAXYoa{;2GERx[! >&8Uw.|$u ?7測yXA!ql۸/7:{-a~b1hYͳѕ Խ mR,T XnuN7XPJY0i7F݄+8VEzac֍ -̭SO-~FcUyFخ=jA)]V/#5@yn*cz>PC@wUH. %1ֻ}w쫇\Wsc ;49mqR;16;dUF̶i~6V*&e]J,jdfݺ%^? -g12$qE?0GfEd蘢n"ttK,}hr|SBS(z7{3{ݸg5aFeg> n}:KL611 6XUs`&[fZÇ$|lV j1!WeeY_pZ MƧVT办<֖c;jB~NʇwIv7ɨc49>~~n22l1s=հ神ҭ,}F&5鸧Vr6znj[wd=*;WskΣFkϊOe:MܸAn8hNkut.Ѝ'ftT Ѱ0}C Cv]*\AKZ*w{JJRfp^./_ݫ d, dT}{>9ߞ5^'ATI'og۸ z[?i5}cu y,p΀b8t&/<]U3<1s (jlsq;~yGd:O֮ND8$V}h@F&OEbyBS@\9N+ܛs<]}[,҃.ҬMyl|Wfp]5] -g6Ft,Fs(6lh7Yp,*+.__ǼvjźFH0P&$!ei~j5ɯ>9+l\% R+#p##-}(Htl꒗GIH8hU{gTFyq̆v=;n qSMn3R(cʽYcB=P_߬lPc#[ϠUvWuIp9_i5-'׏;:Mq-0i;)ޙh Q=hhY!ё'μ;i@)6p[9D29x_G) E84]}=ٌ8L3dU-A (/ud+77YO&{7g||ߙt{wekWk%Wc ->9^X餸/-suhĵ - ʬ$F 8Iԗih 0| nXͤ8x~wVO7nɝu2JOթ*y5Kc -ڹv}E/e$B YaȻB4WԩQ!?%ĐNS)%]cx)\ZB:+.NBQѓ(i\ZzIښtp7ii,* -DxDJαVɮ4ſ E4#BiT6:ٹ_]K?+eNɨHe!5r WpqY8ui.b/D:1F鴲AJs2ZQk- $ɒI0-6^bJ]gqW~'Ql&nisÊJ hSt#Ni"7.IM 7#Z -?!_pGje8P<,|93,8ul[!2E#[C~V6c k}ҳcD8u/!c@PT$4'%M 8乱ՕO򱖫l#%Qݘ^}t0Po1J978v`I]F]_-ZlɟpXe,XFsLJPNika*,vEiT$R?+,5y9G8ymq%U,UlQ@S[11%~FǷ:Q$6zLoM p毛NIqyZ8Za_ٻ͗IA3DԘu[7tPwuk˵DpSH7ɈT'5Xӫ+}ӏ1|}n%r,yKW1`|nkLEg~ -r%!/ֱgY).a>_s<9T<]NXF6c ;G9.zJ3KW3jyԥC4qה:_yNc9Hƍ Aㄼ.{fIQxW|c&O |H/qHSn\z P̙S 3)>!i I}l6 8cRU'8dxKA8GתVy\aKLaɍ%_V6u]5΋%/쟡s5$+++\~].ꏭlkX 4*AVx#M[@|,WXV< jNKݟ.ɞD:_@OnǥnipYdz}kX;qδvu0 Bnj*UB4) -ދ溶+W&9zcs;p,;{{~h Ff!NycNÓRsRJXxNJҊ4adTt_fvWՌ}485~ b z@ɩFNiz!VМXM[ճU K%UK1"#.:SHHJrTƦao;[qSѲ'tRmx iQ0AZlֺ>|=X׈}ג)YnƮ6ɧ`>4֝mҴ;K/gcZߜ2GiWݵM3B%vBK:̶iݸ<#'  G~VnaDC9=Ӓ'}i*#4;~a@Sx9hQd׆_,}6,w[Ux}3@`; ˤ͒n ,hٗ;|Wz[}͒Yn޺潁 ~zAJ%hqcΦR51fຩVD=TvC~)h&!+eq>ļ0 Qy#%wsDsw|x(k2E}'ytkC'U_c <9VbT tE nd;Ӥf7 $ĚhJ#tKh#FeGꖛcC+w << -h)-L!j6,ӊ (3hZ0.:+ SDmWjc$%LO?@dmtWuRШK^E,ŽIhDuҙvZw&_[)T)_c*0zh\2 -pRUB $x:gB HIbR,囙Ӽt_+zvgR-,$s'zWIuh\ NdՂV'Y!E=$ LQIAޔ&߬4Qgߐ%CLR ]_us&c̭Mȣ.@X]޾peܹVkN6V.oϜ5߼6C -Poƚsv9>__,Di t1-IZ{'"PȱN+i>s77Kק ,NR\X-si<Ë8Ni.04H -i}%؏c't+VNR)>'[^;H: !C;rZX(XqgR.*…]މM\ߙ=>]',ĝ{KQ \!/2g4IGW᱅J1NٵKLv1Wlh8;x2lRloS<8S\;֜K3H%M2Yǹu׽4wtzUb 7rNSXJ:g}>? Ҟ7^5; -kYp%AoyLD#܎ӯ]<'<N ߬;2ҿ?=gYRU# ]:-ޘƮNsK G66Tƀ'ZNbNK{ N L_䳤5l:aX B~&5L⛰ڶςՍ\C1>+% F+NH)Gzg8}@sEWKS9P -UE_:k[bp$B$saFpV $09J+쮕g))c'F9qm6\`K,| ʥhZ0qA#P* X r؃Ɲѫ4~U;4d^yGE'(udZ*L{Ihy $jHVtSlyGW2ўcy/ || нٳFkJ2+fNv=H]U9tyX)ߝ+^uEFx'JA ګZ~ B 9moj3/{Wn,M&942FS}s4?*1_D9J8L.裖B6<[ -*\c<^ -*GrmGn'5Z|sva͋򬟩&Rh5/H#FEff٬6ʥj8MKT‚RkhJNeHd6/^oZ:EP^Voň]x7 ^NopP-C -󆙶u)rs-J‹NK葐67ňRi - TH\y}ѺN ն/~Gf`s&nFn^FN15kvQ$yds>#ha;~k2,Vsf;לJ(!G`T?瑭gE|/H`(+ڒ-A9UzXbh!S0)!tNW^q'|7|Q4ڳ장Nls9Rּ-iZ<ðv.ny#7n-/@+qd ( -ZɛR`Ii8Zey腡>bb8ϡ3e@m昉Vʀz:q`1 3*WGmdԄڜ#huֲz:֭no'YIso͟5A Wi9 tW:7m.bSDL5lΑ^Uo@0 R*W$uַ3wi}_گgw־\~6dObygҴ_wz7VAG=C[T}p?v*ry7h?֧櫜%'Ds QSQ8{+~hQdE>4v;.*øsҰY6[,̋C÷"^FYrI;3@sQKqgq7BGV# -$h=uҎ6 -ٮ]󿛳_H.KNg|# G$izZ204xiЦ mt6|B]sM|P.s$pb[xFsֶ87mV^kʵ_M7ܾNޥ*<0-*^Vkϵ={ed'0CEPE @v5qbVyo{חorxXڲ:ȂB+P64fmʮRGt~m߳2+h{ͺ\yz\ 9m>eJc-)$d`JxVhΉr,@v <心ݫ05I5yz,v\xo%kiPVfʫ]/,WUhhqs7h嫝!RE7%FC$=cMcJL竼Vh"{kqL\,FۺzĴё =DޟcuS-Dq+Bh%Wbhi:[u~h!\= w+FH5)jMq -3O(E^0s?&g -0# -L+b >\!}n>O@{A!,41 uh3_9ʶrxN.WlI|ؚBr-_z`DoZC52YVtu}r$CC4Ҫ݂<kkvȿѫnrC#JX՜1q?bQ9W̐A]x^υЏ2"RoN9-s?'ObuKUAJS\%DGL^skQ -P -iItIE5sǦ&c$WJ_)}JJRR>@v3ξBz鶾-^׍[3Mb -^w(J?/iH*&m=S?WEu%q1r[$TacPՒ1Jfԉ0 OV90)Yɓ0 2KnjN˅j"i񫊎4JO UFïECXm.qFt/axeoy ?bV -˂X(ғ]/SkzWpT9U-:&*н;H(R?%C㢥MGBJSZCiA€? [x|8^mvh]Έ:BtC1XⵞuԩGqt=C*4p|. bՕyFvMv00煀ft6BIXfrx{k#IaϨu'}y e.%6EM|T6iu]3@EkC&Օi蟀\h/2/: K'%Nn*rе:C TIj3I.HH({&&N qy -ϑ6nR@/FM6Q8ilVm ~$zw#pDz'"I>{ Q~AӚƪ=5V1!ԬC]sZׅb_#C9րB@s- 7D֗tX4NKL{"KT!NIGTgu:f(W,C=*42l(lJ3g(pg8 SZ9L{L) g&ɕxh ]xna&|&IRCjDQ;tJ<`ri08sc(֑Fݶٞ@lW=x}nxdb$\V~WɕzȵqȶqhnG“c`|/{K#47.$SqgҸz 4+5UǕ8]?ue5qlݐM -Oqd_zVπ}#~9v73qr(#q&I -s/ht %Ֆ$c)d]cn~{̞Eldž8YҦN)ؔע# 8)^vS8 -гo|R4zR57M (%LJ_)wJGm,,ʖ=U%GKey O0n'(l'uEc-"+-ܒIKѳtЅ|S)L*V -*-g4l7ggB-Y൸ho)hөzsNqſk=݋,'̝sض,o2 bgr)] 1l?7R<œ@iGwhԻ"iT#=@\LN /AhB-/ ZZP~r^ssR:P ͠iu #Ba؍ooQN;! |ӂ$LȝΤ2&@rw)c2ds>@iV_4~Prʌqם6\8F%)ĴL)#xuRg>qDvuM7&N i"ωte'm%])%&jID?#YA OŚqkA+OfݞiU+m1 -f֊\^ 0İ ʕSkc|uUwĞ)5n4>pfRqjlsl%ndQK7.KB6p2q'` הղ_RM͝VpVz} -  '.i6.ǶgRم{\ƒ+4o732o{|wfBd:Oyvezwz=;gx tOGRHήhEDQy}w%:)`睨>̠ P!$?l\ozkiA: hR$Y}:έaVz<@ŀd5-WAi#t"MߥDcO<GEJ@֞\/~.Cb"螇áO"fWs+j\#23%RM%p, -?+ᐐ#c"p;C²KEm5=C^9qe?YgsAJ8*q[rmcS UWZytf۱/ֺV&>>-83gzXx6㢙iNR G Ny bʌM@3J!{>u,X#Pa3F#p~ ݾ+iL#^e:90K?eYg՝~). diBh _G\7ɩU}n@L<4!n,b (.+mf?s@^5ϭliؓ">vl~BY'< ~8cˌQJ!8_J -jCu?[ǵ۳VLf},V k.4kŞD2M[{6nf]_0"o ;`w=:Ǚxύjk&lj1+FɵmH/ݽ?u-%a 9V.=VlˊYY-+q'T57G!Mw9} -ZBid(w9 OmdςčςW_[:h1QbƹGSmTFD'g/]vlG^3If6Þh7?zs<;Xis2yx`1\SyxB@hP":'9ct\! 1F&A@rqCF. $F>G8:Cc5wH4k&K:-M%H0(R" -WlԜ21GV2~AnZ,PFCMvZuB' _kk+z1hZecQ&Yc-ĐƐ@kAHWx¢WQ=GYDW|vxoQ7XօܔFe??9Oa=bGJ2Oy_}Qhhkzn߶rjRc(Na7{69BUZ;4lR efF[`NZh?,״"u{7*b4IIq]##`y$m?Dqφ3ڻqztaS*Ø|ޱ4֧qpV˿U6ʷu2&<MzBO9wN!YJmt/uZAs" wwFe[ڣPލ&4hbtAh%r];*½-Hv;ZU`~)o=Uv̒WIv{ߒ;)v]knO PϞβ,CP=hQ^>jMbmǮ| &a&aF6G2F.%N!c-i? *MM7Ik5|.1# -Lh:Ka_QP$&av,vu<~yx%[ydzQawo,ZׇuQf>E=O -{-.q'!BApv=*V8ï)}nCu#C6=klΉ5W*htk6%8W-c8 x MlZ+o,G+Mw~r֟?ٍoy=  1aLYQ+ -Z~BRĥσUvĭ٠hL,mX<Y2e'RyꕂS6U7ba5T>M!W~=: -4Gմ0ӜGe6b%m0GAqNAΦωϕ"武$ m %siI:7tm}m6oGkQq+z>G٭hf+0XSF՜2#$WSSڝngASv@7m]Xw./f[h7nIxd}0I7Rf=XBb;P:dIMNsL8^ CiƴnQ6E'JN šX4bG[OYEv#'9Dz;y0fE" ݔOdͲڒmlk! -etҦҮXE _Ȓf.9Q9IaߤE'Ui }b|E$}s{YwAK#2֫ȝi(%%dstmߌ_L֋`\SȺhp,۸Oz0A#gO?*c^޸&h G=o3kA[ -N:͐NmsT5#i@HA*1: 7]@~v}Zۘ7mqr8匳:28ҽ!ni)HcdbEbP5w]x:U7X@)џcyZ<9AsQZ<ˤ(;1B Ed) 2 &ihٸW% p*EDBOJk^ ijrʭ'EQ#++Ow_ݗ_ݗ_Eܬ-X26ˢDZ=_hY>&e,Zs/h[[Sz~z>x8eݷWܝp^=+0x?\K :˖DUAm\k<jW7m8Ѳz-a&cN-fvƥhݝqsu!ïm18mW.{ZDpYo& -Lss7qt'#8Tʮ zU-yҭ-|'W*/7gTơ h]T~SΛײ % 8},OhJi&|>lC$SkۈH38Z,U"UsuZc2XVe<_y*\TV+#QB?5ʈCQUG\?X!gz}.klsQM,}R&V2ledVZl0Kn_~O&JP; SH L.r#+]_cOߡo -$wBO>nÆ\iΉ.jרC6a:Yecɘ%W7R*JɄ@OGĻ9.:=Nwq(}KrrQgyN [cI6 ˉ-mМT,NOjsBa -υQU$4aQEQHhyjVe1υs\Bm.`o$LWvy>C@Jć3Z7.C!,?h1'HKAb֤k3M<۾h](^\m -=K7Xp%Iӛ汶]ʳOn 'K 2m$lV*-{UfTzp rHROã^|74gϝ/& )2$"mݠ%͓a]! [v9I<9H!i>sm;*hʉI d|PHaQ"sӨMX{`ܾrBcdD>0fZ7wqFe{g!TYG(xQrM*m.e̡I#k޸_UqLzuoX@(چB qi";<6[p@cM-h׻?}vuZەᕣI7Χ&Ŋe4ɑq:܂$U_raa﹤b"uᔗ .~Q%y23MBU ҽ[>]qP^*^OL҅E Z!NEL09ݮ%l]֒z՜.](Zi)gxk&6^Uf]Lxn4C/gK6Yi{;ZdEQN0<TМЪMa./瞜8; -kR/pwUj6䚟 @@8 NI5U)j&\LjZũ7EFQ;g\XsLwU*߃P* !WK]ՊIhJ[ 9aBbJE|cܱ -6IIr-xQIϦzmP>Kzݽ.ԣ 6:{%>lc\>szr+)1ƿ} /b(v³^9_OϷsKI#Ksq8pJ I7IW7N̋FM 9Q`OÞ>*aRJ\#V -c(Ҫ 48̢8۝GUA׌%լ_EcU 8 SoKC 5UC]wJ,WscaYơeDZ38l-`Z0 Jg =h6JK@Ko$)K{DʘQ|g80vCU1>8*cZ^^+/XF /}9ZzynSS}+_g6I]$><&>45iǜA:Q - Y3n]: ]"X 2QȘ#e4-04n+ --<$Ub0+=(0h`Jұ<^q qw-wᝊd&d'=$tW<7'!ˢ 74tcBH7w'/rۮyS'7uu@ rK$DB]+f(pw H='464R;:PbYZ%DZ؇]\P? YY)˯ |p]FaI\#G4w]gWΗKTΌYQ>[n^kqSvc%ebU6!Am+k{[dyȾh -i,ڨ&,nGi++k9qRpʙY0E6}:ΉAoiolOi&[h+S.V;/ yVL_w?Iôe俒!L%ڍ;n%*PoPw1Jg>8iOҢ*!N9SU$hG R\oڲ-O_W?MR9"ymrdAZ%Ǫk'N?E[Q{cWڻ׺Ƃ.a"Y/ֵL(W [P؆= Acʡ7dؤ~ԃ>/a]sh>xE濽ZYxgdؘHQ9L 㖕(SIAV'.2JX!.WP -ffC^){ƦW%q\ئ{R,!g]I[+X H)2΀X@FiCelj#pvX52feVϮB)>b(k]lHi]0Iv&͙Ͳ.?|(_ȟs6[Ny  Q'[S⢏CFV NW$ƽe+RFHp2XeŽ$nX(:[GJ> -f;]_e: LCF _3q@5$%SsK]!vm+F=MA8hG&3ۣQK@p!VVߪ`ZGw_Yج7ʒek 5C 剝<72k _Msm=&`p]]Qx-\ $_w ^sm)Ž XhVhetƳ"M suR9't-y2Fl(#!]@qYq<'+)t$6?D닺M1A 46H%۱O݀S b:& F41aW&k1: q_ߕsc{QQ釓(%1RiQ)D!r)d.sZ[Qb{4Џ(23H<'C. -lټJeh$X./oΒl,P$i8c-R[Ǘŏ NH/(7?2hAKS][V>&<@eUiU`\7֚̚ڥkӵ&0fSXxھ$F̓t?լ[9i!Z" +hi)!9UaMEvbų֤E"L6-j>lM < ^3f(M;m# T\e"H}cNiF8/ǨF~7ɷYm do.ִ K`@m)@=hӏ9gnwVÛ:ݤ[,dMI.z^`Yku#AAb5r'Z^] -2t)DʂIԱMaGt8Ɠ[(ù#ʨc`ceNn`x&l,T$4tc!L+ -(<~?5 Ӫ -5G"SZ)b&)|û[eâuvXo켣|(*n 7=;3b)31~W>60[8/:YyL{ -N IA1ms^$t,[ -{1jQ1#\?0PbéxC?q {~u,N~y? h崔EeVeKzK%Z1@/a? -jػ-ODΆdZ &&(K Q 2I˵CNcO]'‰SըwU*kjT HDԈ:ɲSh46Vyr;F2-N05WKf4$wܟ] -mr[.{|[7*+|qQV1R4+!C`U& T"Qpg)-:Ѻ4dsq8+~ެl1Ƈi0}n&٩6R5vꓭfv)Er(U3 -4)UuK{\1GnݏgCyU%0xRܵ !K_I] 1 -Cp~eAk> :MeW2$X*LAc$ Nث+惗Ow+FK /坶,T0R|rj``gBݘ2n\P1BRq@+jgY<؉=}E ?7S }r|QpprUZi~:˾$,hZõ~҂@(CM8I&Z+勂$mf[)_fO~X2aCe5xxNnoβl"R>1IO?epn;Wgh4(/~ ג -ՂB.Y- Ox'-n"/aaI m^yr ,X`Me3 -z!s]Ӳc @BJA^u!(-ȷ׵\Iǩ5^U[*jԒو2֍mMlS-%ʒ=\p(Quq Zxg[ɞq[ig_ڇEz݅hI4iTtM.2qocwl?М`DL7q^}勋xrt9ssWuEWqfaX& 7!nvEJqGּ ȴDx=*Uic,MkSW%Ғ<:x`tSμ7=瓓s[Sg3uȁ|k#G9 ?8Zػ\PixpaB9L2+)3n, -zV^%Dݨ2cqTcH:jdbR%Ef̪2L_T)>t<߉+^+c|i]브T BSZSa zjlٻe!Zmgۜ<ŸU o@:ETzWÂ>L<8bm[PSzcM6XU=b!orX+kH0S0frAW>qߒ>%ys~c?w7L9Vҏ4'ͩFVBd%8͉PV”Xe%`YZS>bb*I3'Q kkհ׌E"HA+u}C -ZH\3V`^5Cs @H˩r8I@⾠Xmؙ Xip|'a@Y+P:׵[3_LayB5%=d9ߴ+okű#+nd+,;֘I$7"qVxnZdCk,ВZDq;6a&Bˁ2;GNM'! -_ -6iyFJ[ZN460 + 0<xxnGGuM}(·cxorCz"L E:hcMEQ;myNzr̾0nv65/k+F&EsUIa)& !(aLh^֊}- 7{#O w|˗qcGV\R ),N`Dގ(;AX 0ZKIM!ZJТNW5Sq Ki)1mF> -r2yM<^kdؔ!l w}y<-i< -[LX`N\嵁OVWX~y'7\;h/G<Ҩ l- ෂOZobgUlʹKvMhAcZ _edFұDzsDNK[krOŌ<$bj 4T@{7V^3DZy$1M%ęA2ύ.JJ# /{dՑΙ%EMF7<_ܨȾҍD(EXߚ;e/孊0ĵN3!iP~O&j -- LAQU -f4qZp**IT?=ҮVU8 K`e9v`9Ysy45}8Tf&G 8"9$5pR0)qoi۷Qn\tTh\Xk Vy(6"sC!=)7>w֯t_}%q:,[Br*z>0,6]SB,E}pHώz/ -3M{anPZJ!4 -gB,- *Lv(9x.ŋ5ݸ܋dXMqݻ`Qr-uskI =a<[jt"mP*Pj9 o5U>MiH-_s|w6J,1hꯠ" *kow{/^K..r3TEqG#ָp+;.C{?tҁy WӎTqZ}ݼK2cz+ hςpqi0e-Hڻ`ŬS}{qCЂ֍v -ު7ƎS -qj hZ; ,vHʾeVةs -b&a -&Ӻ]+X q*@1qJh HQAqvcG ][/AB[]IFzr+ha 5KU2:ي㠦\ƑLКN# fQdӨ64y_R S75cܶ7kWhm҂{Ӛ-<^#a< ¬E" o[j4ZEF0lsHlT@#G>wP:&G/ht5]NZtb୕y/+f- -{,H.%\<SDT -%XAbףEnvɟ'Ve:ǯc~k ; 讎zU`TerG$pH`~[,9r5/N<,UQи6jHhCxU0@քs|eBmR<#%Q랞Xoツ?)WtUV+xR V| M\!~0F&7NDJG!Uprlӄ+Xθ`tٷVޕzr,ʀb}H7hm뵲Ӯ+E͊RB>Tlepp^,<+,̪]aYҹ9((T ؊0r찌8 ^I%)]AA]6<.БQc?P&R - tO֪/;Wf Ļo~a̺c7_Ek钶9_/7߸[!Kz?gSi`N{b8.]ٽ=b7Yӕ+]Fa0RXq;3Ϫwma*gUg⌚]Hrs54-6FJטב}ξPt,tIilƤC"VqؠEԧm G"K5 B1ߞ9ؖ`ƖwB1Kt.C5~fgrWiv -3\m?QIE#[XKj4Bwdnǧi-a'I9Ri#z\~bUê"1XSX76U -M)C,yvMAINhZsϕ$݇tSJ -k)ܒq Q764=0g.}Xq=`7lNw om`41<‰ANI:h+S{|wv[/rre 077rKdAC1UHdԁ|b4쿙x߯v~1ѺFYK| yB6Fp&7& HM{{sP?:RsPOmK5zdyp57)UN&SitF*#wCK RцfZ<&>Pq@C&_|\<`m(*DS@䮲5^(Q F4cʼn?j;|anQ^U-FgF5IYro+J=NFiI [[tJ";D -| O+k @?ТXWs:@/8 ;LFX鬎 -/ϼ~̔Ʒ{,ʍVpRnY?t8KћẠɊ9n,~:[0a~]JԻ5lPML}xxl(YL:ƨKs$я#YZ1@E6.ӴV>m}-܀kAJ-PvLߏ,mCEiܢ+hdB,m rU)Ļ T<}e0ֻ̿2?>g`R%/B|%l7\'>s -ܫNCXc䏫Ou1)YFHމnhçy>Syp]Q_>w=4m l&N&ڔ:Ed'h(u#5\A.~GrE mesFNe"]8$u 9+f}\G>q% Nd65OcZش,1^uHwv]mW1yXGu$YG׌ôR~_|Ib-b]b!&33duշ,FY\qYO3UxԙxքXs9aPnNr͙woIm^NU~aG+HtZ0[)7֌aQ`&4#, N,vʸq.//ݽ8ݞ8•rirgYn/=6,w햳"ט-vtBlȺ#3k+AcLx eU:zݜSv>N>ٟFG9:缢p+nT{hWMxo=q6;p.rA1>eϖR?]_g^@ʬJ%1VV! NlΦ=>+ח>υZ3˹Z 5qS 7L]1R^i1i#jXV9'@aFSN,X)/gnLf6N&M\̀% hi[jIhd؁;5q82|T^7YdXJ[w(qq 4P;;0eC[uPJoqsV$40+'hK lf˶6mpÃ9iX\I}}S"Tee;Fऀ~z|b$7xa0aՐ#B6t&F P`(I WwOz49{#$fΌiEƖe;+t|,|Z }]|KHnik-|@_}?se)Jnr,+e޹&4 ptPzx% މ!keaُ$^4,2@pӗ㝼^klQYrKq+P't55` cJQwq"˻&KV̊}׵$9õ\I7CLd~iTd zxc }O3L`Z"4F/zT[dM Utxv)h^Ƌo4X?wORZ&[XZ/fFM"o(~XAr ')?"6yfN`kh& ti1h< px3^1knrg2ưY+zϥ#zM!Ղ1MCY;u0>n3ybGcPʌS:M 3@zxr߬zKu͓;ϘS7Uގ6yw3v&%εykz[,U@"p?s?=o\6sכrK#UJ\lF` dց?'И8Z7`"@Ipgu?~כË hFc'`A oJ j\hm,)iYßx@]h  A:Ñ9$~J%Z>SS=  5.@zsS4_ԑ7#dkb\_GM[1mBy*7!h]1RP5FAc,Z\ p֠1ոAl -1Rr֟?ݿ }'>هs7j)N(T[&xQ)Is'}iJ"4d7Jcx]' -/jz0aó ,ZS<9Tf1HD7+2?Qwk}ur7Kg;uv?9DgUVRx8<-MK9hIwp#Fۚ^9*f@<יTPg2 ( JօX), k{}@ṨwLz|<|h]eF% Ҧ5}*Zh,Za]YO1UٿVgZ+G9 xpX3#^3QCgV]qCDmԉq -O6zFv E2zZQ !uՔ4BB\+/ʒҪ6n-ȷ]+jjڣ:ZY;}*>z1nRl$4g݅:ܝfH ^fN]R`ȣ t}3ݵHmJ[V7fJ>/{$Ef 3wN%aƯ\vgyy?Vo92~=Gv.QIٻ Tĕ/aɋп;s`EEյLHNc:77Iu`s^jJs1Rn(o%EZe?Ey=Y;Z |-Ti }-몠N*ٚ%lniybt2pͅ>"mj YېF6cE4֤a蛔S"{ ژIz ^ݿCKx_a.>b#Ly NS<#@KBsbiյahiso38ț/R(T7=} ų3 샲(୍+v=\gKV/$9 _*V%|,19blyW/P3S{ʀY1':R:] %{n߹p73m -`Fަݩ! ӎݑhso2Q?UKE0@s>ʰJe9E4 0h97Q/H vIIkE e=(= > -XVŷ 9:<෎o&/=FejJ#wg=Ul䠸Hq6)` מ=K!Bf)ZoELl4ψS\WkkxKș;1Q#A ŀ K !zKubU^INk(W^[nB5dw+\.k勋-Ϻ%T(' 0̆i%HIsFR0 -{i{C<?Itrl1z7QiIfȚe ʝi,Y-hMa3n̾1K~Irq9XfpW0|0:Vg0sITNT^d%0K -LZ>k2ֽ;?+oVs𖹾xH/~W^qE1a%ЊX+RcEt,ޭʘ١<+6kpz{QտƑ~Bgqn7cMYO6><}k_υ9s| -EA'Yqqv6JsQbdV߿S'qx+w '0Aءn`1D&V3Ԃ@W[{Gx1^oMMxm&;;mE qy -k[8n-mu~}g[DyIGiyL d+ag- H+z·~n9M8^&e|{Ƌ2tz9verl?hg | 9 Z3cćZ jgg?g)F :(Ą~P& =1\hь!UhoΉf"1^9nۼS~+N*hsq -7 e9f6O,Y?VukǷJJ|d|XF8p9a[OK} -RQ@?Ҳ/7\)ZhF0L9`P>buqءiu1R 7|16oV־{ro/AخE -ey쭖\L}ag,7c"c$u]S - zd)zs,}Л,%];gY,STp|?7btJgѨ. -m&/4Hf1L&)m㎨[{[<ޗyMe) ?O lP4 ZK^tp+K/ -?ڧOc|kiÛ<\BcoL"V:1&;73s)Fb0v=%uGW긁n~D|G Qp.!mejޒ;>^z`(؋l+ӋF5ֹ<_»U. "ǎm~Nmajos?\s HH ɏN7v -M;jnZ.Ar3ܐ=NwlEpN ._~!!cRAOx_77H<xHa4; f!kZx}^w+I<(i1DϾ~:-s$V/鱚kg1NăoXNj:?:"hPתA+7ԛ\PL=NJ|9}%IO5nvs1ԃ| -a bJ79*#HB)R[wm{wޑ?O:iGj5+ZD('n{\Q& Bw/2`Eb,qs Wu8:GmF;珇'#]QƖ&vD7|gi\_|kʘg6\^z؆֎ȭ**UjTpąU!M/81ȅvrX˸.Nj vKF!xzLXۑ:mcpWzN;N0fQB`X~i?^{ƯR{ݓu}cV1]zvX75O}pl%j3J&Ae`G;Il,>A>MO:ozڋDNTxS]i`H] -,kYڏ*W)\j/Wq5 ck֘.ܺ;JpAٱxC,>3W?ׯ8h^֮3J&V[v^d.>n^Mww. -B.Z/!>|C+wwVrUbI5k]qq;Ϫ|uU? ר=.8}bECGT!kFY)TV\ۊWj9 -y-86zz;<ІG<v,՗q˵ʙ59S[(3#tXWre+΀G`ܫwj^_ymt5^oK{Xu STE9eL43&;cg݊iRE4hjLØvӌ6j؟ 3hʱw~~FW`ŏ)vښP)V-pШoH_];*ѮAR}EI缣}ncLJ E7.2Rs(h% #  -AJ=(,x@ANSY| 2-p ~8T[,|߸>kˬ#]XgpA쐮AJF(g@O 4ߥt$Z,:Y?@Ա&($u O7G$U^&֙l07q|wr:s|PjGZ֨4+0=G̓艅B%cfjqi9p&}۲&Yj 4EYAKMrVYi )4{aagv1YZ@?RĊ\~M*iݯb+YS2ċ~u%fzQAx2K㏦P#n΂;@X8V{O Ժس2ksq>1{/'yb˹{b$aPHXϡz؋s|y:lo]GT[:p]ם).*c.kTCFb[Bv}~62-G~K&cxqo̘̐ҁx%yfLyWcXE -L«.__玣 -S@Μq9ە.ibo6K?CM\I?!DsefZfź7,NU&6zڷNi7q-˜v3593㝅X29L';[>=`Fጒ2?W2ེoϜe^7Mfx/=QxӉJz;f]ȀFy&UF5LCBF]hc..ctjW˷OM Ir:(1%lJ+CkSM}+.TP{pہA *vvtbѠ'GNgVӉޘk0!J*\/r, k|}cWo`%Aʩ]PN-" -zQs99>fnF EU|W5/cYgqwA/loI"iS۱47<K3r:Īk=(Fwmy #n7'ΖhV4~3Ӕ9|^o, 1 +kzn' 'DI2DLTMBC9 :($idJRkL;m/~~fl9g(0Yꐼ -o j5uU?Q[Y^:nN<`0sRO^j>GY-ǦgI<2֨kݼOhVhv5d7Șl|B۬`|깅zzPX+K Zc-4N+ -/ᱚ+jz. *=jiw)ڮfuțG~(ҽ -Zd],MFP] -ҬCoK1u/ܙ",ԃ wl(EʒDp`JQ#~6]x _Tq  -h҆{ЪloDc/dFE-4igFCa-g:o!dy;7g\GU~:]qOAάC?z <+dG1 -hj|e< r7@E+{=xAG?H eRKcSb^RR H  >۰`0v1R -e 1cs"4`(jI:^cov9;7.ŏ3uYmI`l1s#ZAʅ_O7dPvdq-e5FiCC)dx7UX|ۘ:MBuMŅy79s*;g5 R -՘ -EJxM4mbZ2A̾ إV&;5%oՓ{UoCkv[= UJ1rU!ߍ9|;17GJ0S#N2pqJy/ڸXekpG ?l),s !&z~*!,) J,Eg۠PD  >HX2%@1Aj_ET.p@e_LG"*زڗq/4DeY,> +*ܹܶ,Ye7V[l'HNG6(B`}N![i8 ju NI4HC]1|J -mwy˭5dƺ#.hl(S%;t~i/{mxwkc3t:BPOV;w%66C)P0H7H@*B{z;UA3o86gRab7HyY_E%)A"'(>KA[9idxoxXڑ EDw:S9)o\޷>sC ԈVq endstream endobj 2860 0 obj <>stream -b\+j<bHP? L(2)\Fx[o %TRLq".AE1kH#{B RY~ ECy׸qsa΃;?s[k\"9 {b3GPWԖg;Z<:)edɉlBHiWv-۰/6FS~`@uh:NS;5E-M%0k V\:8OQx r27O"E$)o!ymAf\ʻVVrzÓbO:zǻ(sH/ --0J/2=7mH+njа G֍D \2Hhۂ־B-xOI;OH*5HTբ&㇄wES#EnMoa t2[g3;l0#jG<wLC@>GC$ - Æ4Q u;lX_Bc`GysmaĆAJB 6j: mXkEc%Jb47 / -{չ=ֈ/eSx!9"tK?HJ"eimIA25_$$U8|p=FL&Faly!)ݢB%f2^M%KxWRy3Z]$I2>_nϬ"8 J`,cH薆()c1b b DAޒ;g0#S(@ uu i^Pp،zwIЈem.Ο:gsfոrwF^$g9$;z۩ -摎{sgPJٷ1\_rO(""I+Ab~Z_Dit&Hdrv:_pϬ~rkMJ!M8;J܈/V.[mw.ҏS7뫼UFS*rM#k (g)vڀռLӼ6KRX0 U[db"c"i%) pt:P~ί߬BЙ<^vO-ԡ}fvHNZUOU-S!#'my)$?x4)~rSr#oӂVϽA3MV3({CI Ru{E/7٧V&I6=]Q4B4nUY/?U8;a w>0K lqrk,HT/\OLoW^a~xG@ ѫtR 6m` I+xr3ζBD &:YL%TIAe^zu#m#Q 8t}%3w,MMOzU1{5wkpfKk ;:b`3U, C?3g8:^ެ/$3 -9QJĢsfW6xۃGЮ'8X+rSǾInP{m?vRwkSy - } ժO5nlTh*,țg].`܏>K!I2i:c"=GAkm `\~L - jP4رkviBd| W7e2`@e$:7SUʵxQ& @S/l#OHd\ʁrL#SjY,o":jj9HzXeEU-{I.oЪyh}C\ǣ4!g&2aRjQ ѲWՃ?PCH-.28{Ѥ"463VGgV$Uy@KiVBp#[ӳX^GQQ]@F-p;Ȑ+ TO551bHP\.+ۓs<{ @m{-ز*>ڭ>7Zf0C4&YҤȷ'{b#\S{gnS<:aP.|b"iH8C! ZlAs蚧'@W)/fZ֣WOE-'7t+> Bm@wXכk\Cme_j7f ķvYwz½/mt=hIV4(T[c}s*^o)#-QjܨDMz&N9<]ʧ&;\~Z*46 k~A4 i:z -F%)\ޔYZuԡK\OFGvs~X⇵黺*ϊӍE2A22t4}?oK4הZ]VwO~`ě6qk36,oU-%rU6wJ=R$(GKZ7Y"-]!Ek!\"b<%ȅ\_bWzROFqkA*y{ƿ*9,*2Ppq$􇤺18X.@C0uHI&uhweQi ;C2oBt!C4c#!jD<ݱ$,`T¡ԥA*3_.WV5'||'4e}BuԂ@dfƑ2@^Vf\A6:h9$J*YALeuRs5ʲMLSO+30(]]pQ#1[GK0Gts. 豋N]2#y׭g~3(aZfmsga"k)2NHbmޱR\gʦ;E - v;M-9wDYo[~b;X ٳ ̤icwHXgN9L.),QLC*)uy-Mh?۳wI#C=K;I.E>tTdCi0|/#nԱh<G -TJrX%e0!ϕp]Ͽ70XDݕ"$Jk%FL8kLcW4))6LT˒,2w> e6YXNVLÊ}1#F\f^a{jfo[>qW;,b en0m*6%բ0CIMeUgg'qq&yS,8͸iC5]qϿGt>n'bxΝJ Yre/Y~􎬌C*,m1}2r؎ adV:?d<%7xhYPw>Ź֏-ɍ'҆,D8#Ӵ2~5o1φ&w=JPNԋmg?s2?v -qC#h "08a{'u faR9aH:ynC=\ -arU=jXRUcuDBFcRŠ`UH$ ǭQ /ਸ਼uNaRAP-zۅrwCo-mwXf(I71̦R}i)CbO]s{ 1\ң9E]M5XwU;ޟZG딿RE4:IA"NGzh4H9 --Qg$$eNޟxZDNӠQ">>G%Dk"?J{*cHhb1H=/'Q(#et{ʼng3n!"{@eou֭ndt8 (ȦϿD|)H(Ѳ VPD27#J7_S:tmJ4h0\вtЙg:Iqd02뎢 rUGk5ĭ-j]5o\qoKOWHbqڛTKs,Nc 2h>I3LAޮkޫaj*mqNZ]v7/g쳪Z%:w ,>[ -'sy#uonoNc/]CF+Iok=B=|(NSШ{4?i?f8rHXM@ 73dL-]~T>ehC/h]| Ov a'b٪K7vu;\м|9q,I'J мč&IVT 9xu`qytX<]V0ؽ>GgU*WFK"z̓oX'SF%IfO\v싺tzvZIhTIFfˎU7VeLZƿ?|x}o=OCz7 \^%pa 5[/XAI6C۲d8I*ms<$6AL27!lM"*<ᤑ'\ r7Q?c>̣ -MtN˲gZO'R4sB!Ó@)Y{y{wL¸tvHzCt5>-FCOZ \5 -9k;sENMr60)V+p;p?9k (4Jeg lPR$6*<[y"M/{NYYZ( ͌j硌*}wS-wY-5n<bB>c=~Q.d믆DARk}?*Q̙}RXi3 a_W7t QktbY[xfl$ּq&y'ؿWuIIAg_$&s[94\tl۫}%z,xgXV8Q -ES!_cR}˒K2W/qW.;Oe~/kǘuy 3#"oi\5Ux׽'V,}@o^X !r+6$eC+I]75ug -q<\*ĢLYD%9jm-f/cW7gQ~_D)+Car9pqAqC}ll2ЬV~9.~ZWh̙hu)y@t q޳B笂j^w}Xca -s?͹.\& -Ţ v'S9F\||aYH#fi&) n 2YX.kY-dT>|/7%r&c^y#F-l7JƪXVe-Vb}#M;˃=s)pl *Gj -_J%O B0 4{r+hj&"ؖ3beVL͊qs.t+HQz?p$5+?? !AlKTBPѲ&8J!0biv -کl:e1{I!Atθkc(N^ո?$6hl$9[A` -%m7v:~|vkVhr$:9HZ[;h7!A}Kq&:j"^z -Z:|5Ȥ'>?aoy4D2%",Ih,ݽGB[F(Ud^j様}[(_^ǥ.îXF#:YRuvļnX@f -VA-R,>rˑ.iH -I~R]r^VxW{nI ЂWkfέGˢmo|6AAImR`X) -V*= -48~"W -l̳l/ƺhZXۯ_ 7Y>ܛ6yX7W7XS;t%fnAb-yU4F"8-cFf*;>̾1qE:כ9s5 -u+;h,geN5`㮋VΤ @\Y ^Mtɷ!BR)FkUi[+0/"TFEƉZg77QR,Q=:djJ Ic|U9fh%$2NÓvXbW eaX ň) Hp^#sYz>+A7>wu4ui3W[hVU$ R>_x]`-egMaf&de8>%>NvpGf'nُDUqrC-*2@>yʻfC.z=[_/F)i:'G1%Ȓ\ZSknn`gÅ+3p:,x$CJK/ ys#hUq$uCX+fNmo>ezcޙVi,r?O>g_n -~)U4~@yQz [4To&=z zp4ՙ$2@`Fw~?kw7XZ`o{p6L󯹽;y9_#]*FW5oUB|V_],7b‹7hi:smoqsWkP,='c[SK\p4;&:r4J6A ; C\1h -D*Om̈-6 - iqʡ״yώ8~<Ҟ7 Ak`(.ʱ)}#I'N\/8"/bBn.y8N-h=K11`p7~71Z3n4R6$~@؈ZV+,Cŏ GLlN,)'-U8eCL_Ϳj ~IeU:d}:UŃIT Lc$9s9Z,o3Gwr0-s9׬}[z[2s[ߟzprI{I t:-l6±p=Qk48L[(|/9j3X~%GsNzO4+?B8}D rK`w4*s<|,Ax̌cXg>뫵O ɽ֫Nv/29'()%Ѯe; Ftʘ;z_nǪ1뀌zȮ>๨TҦ&W݅tAF$6SxJ4DtIwkUГSY fxI({xh3;`p*ҝv -OwmcEdY=vS7-,_׎X ӭv^GgU*z@j?N?e<"AkUo4۪p]Dz+@ʎH{ Q8kIJ&'Y30v)jngkeKL9&b8Aa;421?l[k{Y6۱~.)Hj k!/):E*"]g?\5JשTf|L0# s]^r5A!oJ٤ ׭YWZm<.ڼ%M{j؋UH~E{N14r#SLIM+OSM)Ȗ'թ? -;(Pp4Ӧ \0hLZ1Q7?YS&AgвrtZ(A:sr^KJ0}hР - k#e, -m>Gr&c Vq w>`'.C3ͥ #9#ߎMڑEGט0bzGÙdGÙ2iszdd+.4u}ӆ=%D; -ǯ06T@gh*ܭ"4r< 6Ī2:K.Y;_ߧP砅83yzoTuƷqRctS>+G -u6#KoqG\FI UE𪛹E[}.>>p"q7u?C|!oA+S pPz+ly\ Lę`(p>(ͅhmq_q\yboqI[ERP"ng/oB=}@9STDiFh$l>5:n&ESNJ%'o.\tQ m9~s܈45}$5"yu8fxXsmd5T>GΏeVȹm@]ٵ[vW%)J$t\'Cy-Ga; e6 \Gk^M[f_Zol*l(7=XZ:66f ->9'ع^!䷉+`G]:ַiLVD/">ͼ"~UDZڟ{Ny70G}8'#EMK+r zYɵZ:):N7>UXNos-(-Υvd+xиI 9j抵jiݟ($y_,w iXrǜTL1"wI5Mqˢ.@)XZ-4zJ$95oeec'G|DGm":*u/9Z@x~QӨrhFصZV#&AN"ux7}ls55SHj5^ۥyTAs)KnvuAcI"2pES-' ZgW_-glMk [:4 Iǒ8pf,s3srLQ]7kD%{RId/n~,cTpH_&-h@N6c+yx Oq -Si{W _蒄d~-C9_-S`0mh;vEU^8s 84WU8;Nة|dGV}dGV='5eoR8F=6 :'4apg檎gccP4;_a:8ϫ0) :HU`1,XRAI")yrijmcEDIlAlec4+:`t2B_o^$ - -Z#3 3 0dzP?{Ц 5]7;TN-P=uIڷW1KD吐sl@ -ͪf9̼񂦑@.nkZasG -RQd^GKiz/h< -FY D>+kj8я)<վG.Ȃp$ޗgi'< -^x1l^cgK݁Ր={X5iݡc%M4l|Dulȴd4O'U]4F-U@#($ ğ\%LS/;ww%@IA%?% L9 apzջ4vgLW-&] -VI(@cmoO3']m&1ʉ)LiIn}S?;ٝ,Xt;mOEUGEx(x76E@8 r2(Ճu=cC+֦h'ꎡ=9/(WN SoZR juG'lC`o2Z:J {mlKSZB՜}h ݑـ ^봪q,4;q*rz%F&fZW?v;RfgvW9Rz(Yb=N3zH*4s0tMAs]47.QIKBRxx^vF-s>?]_X˰׋82\r*mQ0OyKDsm}&|eޭ &B-ڠ%362{b,D >Qp6sn8UMMb!I㧜tku(waL"2* hi b&A#)VhT!ŚQ,ȀM[ر=1cJb'?{k{a""FV2S4L~DR8%Tq9,R'%7λ M9IPT^& {6D3|D0&:[AKI &߰ד(MgsA9'DKy "1 .JpC:{zU }WR,V,W;Y]@r)'Ae9V~˝HJc4qnFlϦIY}6>JZ/ 󝞋I&+x:[tp=h́RT!|A퍼nx`>h恴`YC(t>KR}?}\zҾsJ*{t'Hk)`Zf)j[r?(RtzN_gu<ɐռďEgm͠3Zh9Ua5stsĨUN#G.=4*ssw9Ϛ>N8ɤs~ - U[1-EiڷFT6@S)/Kqձl;WG^ߖ*dLj͝gO"!os¬4Wd2ksh^H`/Rch]@a}P!4y?svH_U<A'4dhT~RE+"zNp[\7u -$9f`|xnB#IZ0>4Y C$\ ¬\ӽY//3?y1s0`cQRZع1H^AEXap Q#ӧ(KBf Lӛ@""O@b!b<&vJP¿`Ԓ9JsSkl l( RVQq ip)bQB1?Hn2"`K{kZ>ᯕ u[>{#2T6^DJwIm ֳ1}G&'eϟWFR jBrudj HT,mP@h(PPL.<*DcGHRRcB/M@dL\Y9尬HN?Ѧnl0}/;:C8mE^١:E!jxv$Ÿ䧩EgI K1HI_N0sM+ -TE0 ӔeX+,oě- Ayȵ󺽗3`olެMwK4^7s(HUez(+z&kGt?H%8E<-٫OgL6}ytռ8m S^S\HKq9-!n:S}j -iM@ -{"1(ĤSBl-+&.dIC9kQ^&@>pBF2 28g 08 ';a҅Q0fY,1OqnHEns^g/9zȷf)o?޾~F6#$OYgK;_+5me$dp $ëTK6=/ J mxOֈN_y*aJ 촥@[`h۠EFl G}Vom vl \'sZQo QNE"t9v&~z;<`_UNPy=DMZDUK=:ZSY#(,#(IIk -wnK7AU7?{ۛ[Df".f/"vY]b֕CJ N=tcvhX.gAC?BNxYdzwΊI O &~H2H"A:1W%`#P%'Lc@dz-lah EZ"[%S$1J}<}3x>፿I_uڐ!{˺iQ؁kq:'Beu_1C^A+á8Dh50=VH=aݸ HR\GP4 e84iHS5(Am %OP7z$kqKX"c-;g/ -3cND)Mln9k&Ȓ/b.()qi2>| Ċ^dwݢ܏ͱq-a` @.qH䍟.ngoV(oiJi$!(BO^FFc-eg0=6nb7K跄sAbqLQvdY//f+ؖ"n)w~[ێ,l ,݈\JlK -8'h㕅p)8:+Ba)PW 3yJ/r2H3hzis~2->!o_NǽT0Ms -\͆!:m|b(-IynG/t\/!t7>pH}]DpVo9+RAο6ҙF黱7J!K{"8i#voi)hz^6`獋\! ywN%g/4Iq.vpc߰}˘bؓ\RSZKitL$iTχ%dǧV8$i7#̫g+)EPY.n IZ%}l)eI3Kw#&495O˼, +{,dcu.IKoٍt|No:Mh\ - #bc h}= -"O!ж>Io ->&"UʃT. ![Oz|:,!`,6!Q(O2M*[/^m 7rZ>DŽOe tce?s@0U9rArer6");ؠndނƎNJ#ri5w -ӒeAG{2:v@Rs;~=o"xH6$DlZ|}P켓>s?(t|#0} -AN;G$H}BL: _wVP:"0Y2,/h;Mhл N>s]*KQ[ԣk 1CY"OhiKJ8jyEEJ؝y;g\gN"JHF(X^ciai's.X/q#܌Qgn3 YNwWsf'֓+deevͷol łu_, NnzD(!=9qL6M~+wI&VRDt4 qJL$[ϲ/mYiZ//-] 2H܈Io_Y]&!SHIvJWYW -$3sC륈Iؤ%D*X]3uJy)"PUΥVKEV: oRVJsxԱ 9,M_t4a,.Ѷᎆ)#% #Pctxi b̫!ڔyS?(S hMקƊJ4[qh8ӆ=^>G,)C〔U)\O3S٥.DsbgWt{ˍb[,⽱<3W}߲ la3>0M!)S0J<]ǯs1[hemWvͺ]hoVkS[:$aTn-#=Ő8U -:9TX`\P4BtNMQzN;Cݔ&}qF(JN E4ABy~N>?BކjeƟe`(OQ 辝{/HSQ= XfѡZBϙ=rOmgϋHUyҟ4fRdLKJ8ef(ēR!eHЯ$VdMZ'u幱>7}:9cE7-vZ(^NBUȰS(GFĥLj^SXσȞ-w{Ef ӤA8u7y3o0hT4|} '޹ vwiP{:蝠RI緫90I2 IʎO PHAOtN9_>MbQr:K.I{hAU9qo߲"{rQ+x2XB SQC-sۡvη=u%`H291uwUE#N2$q&qAV"=N(;ba/dHT*n%3)u L45^Is8L⾇R-݄q;2 -x|Ȱ$0 -+3VqG|d/(hE)p 6IMT03} k'<\xΎ̚ԂtDz2<H4dFm6N8 V @kr:E -Ax N8ݾ -KܔSHH)ߵ{-V }-P {-m{`,²CK'p$apޔuSMu%vame>kZNћӶJZg|0*uY*07FF-(kZ+uvn:|hZ+yo]2j"&S:MyRgImEcDm]+lNJ{cV,y[5nkɫ-}7c>#?#?o]D[)l8_#3 ~i|^_wϘ3qV\^z-LiͰ@0z;n6Dѕ쨿 I?y1^6cX25}a'tJ$DqQ,nIP ̑!z R챐=OƁM nI6ޕ"@Pn -&xA쀯/% {P4boS^r=1J܉grlX"}e94Ewx3D/)Y3}@$<C+C)ߊ؄I(< 'K3]s@>? IJpz:Fœ aɨ[ehNBR1yiXNa5(u $Jj.=ce~ӎL20n LES'(~SZV2(AN? (ߤ;#|bNDXH@7ȅ }JR@Ԙad0֐L#[xKA*ЄKGyێHrȼW4˄ UiN쒚ž>L -+ OOfe(l ]H7ЁMOss?gsނy+eg8(\ch>菁 dA-HC B\%~iwi#HǶn# 7ʍs^|| x**530hdᑦS$KicU ZU:ș$nó.}/Yxb^OҴ8LI\ oi|Nu0iz:ϫݑ@>ȹS -C)@%15MM ӂ\A? dP@IR -t?R#E?R#E|)E #G6pgOΖ.7Ll l8iHI,@Q3ÙV㵙eZuߑyT"G|{VnA;ڜ#eG h+Q/6>˷V՘(H*frijG"h. ~{L4umߵk:?vkuŽwϵk4]:{X@N!kGաdbu<1XS>+V?oIϱ9韓9Irߛc󮉆lcma7Xh[۶rK{_|˺ZYm)J(ul`7O}TX^U]SWJ t@k6нrs;ꖫ ZMWqE>9E $?HD]TPA1-)}yA~NN9$qbE/;&OI: -kڙkeYcVٚfmV-wߣ 8A3u^ U+L#}]ȝRg=%wnOVmYC5VZhB%VeUYʵ2xAwizAƯs4:A1B;xb^M\wKǕFGsǻ9x*k(eOީ.eXRJ$Ha1|Z ż-r@w9t/S:+pj-:E/+{0ՉzY/MSկm֋g֐g5֕W7L*R ` -ˇ3N0"ǒ0 鱀B\AjqQ( \), ~r= gYHBc-{U׿^\jmfP'iL=Th״=0‚^ 3zH}g3L-z49_RwSժYwhڹX:jI5kWSr=Nkb2*?1ԢAd#^OJ8Rv *%R^)^rua,g!A S9yN'[ij W#@g)Jq Zn8EMgBOCJt~s(9Hl8il qTָ@44#XVMS}0Ņi #p^.2^ !YeS)5-V߈'G{3S[^ts - ˹I'Kɺz_gn&4W\{TrmQ$YQ"#zR^A\i5Ѯ5%Ʊh l׵M"KO7Ƀ( C#8N%:5J|(gs|"&W1y[QBn>YqFw82&˼4gź˨̗oWz0Sj-ĿnDʂBoNnY: _gGwtLG7-¶^U=g:x[6"wM$k.qU d[TD+SY7,jy#}UMr0KrM_ROhEq0A[*E(Vӻ=lym=y13S( *%5?;?3eo7޾7.BiV?ueV;d=YLB(xc.^Us/K \F=8¹,i*rrƅUtU-;y6g{6guўVIŹĂw C Ʊ1"pX=/%7<!(މv)!4foشέ.",SP; G;: z_"aۨ8.8mιNn{b:v:g4xV#;ElFg=^D}e Dhqv=H8Znp}#J N/-orFއ U6^˫uq ?$6K7Q^B-s$PU6Dy~\@PS&) q3 ]۝sϖlϖ2>zK/>>ͣGFԒOU0Z ?t8MU1uYZ|WL}z߇=`jbثMjZg&z+*Jlb-~5wOYXP_Y5leN ǐ@vc[`ۋ~o!-Ɯcpn m?7䄌~"ET- s30Q B~to_u;΢9^mvkƠ~/8 G0Bl;@TlLop@mLQ;:pS*q&(;2Z`'HRR}$<3 IW{ .@I; 7Z,yaQZyUe"yT^,J+M|G/D6Qg7JT5%B2G꿅lk6z\bRV0%=cڐpc&b#AYV?(haׅrHY="qS*;(xw$[=wN-V1NST;85NS_Vqg꟭꟭~MNsaQvsfσIX*)C(Ot`7Bfy0<Ő t 7<_%\@KbC!Spy]+ k:o[c!DyȈZO v _5*轢w?+krè:HI`Kc:D*'o?B6zD rcBX= Ѱ1J6WA4D)ߥ ~,DAPyULP{$'d_HS&v4XM"d&MV':LxJ)jK[*r޶BѾ9] ?$4j:Rݸ?Zh/+ #8e:ip kYcZ -+TcBh4Q0&^0d70|īӯg !9㻛+U?Rf z)njKY]Sc#)Drb7^mܫ!MeafVc :'bT-t[Y)IO2!ۢoq%P&ʤ 5ZG5 UoVA5猜0AgH6$D.L D$ѱ벞;."#2^DXB<|6gx6{8_~‹nxQKSDb jW -$"Q`a@^%0^QekDtj\ 8Sz;\2e qe -Y7@i齴5\[ }ߗ/Kon M\M-uA飧ILlc-]6yu'ˌyf$Ig>3E @clO@flIA[`O`'DRa"yk4>E gkuyk 1 6m[tA+ 5>c k~ϖ>Pk6lj<}S{TJ11E.̮=#8aj`0v9EF"BS$4 -τN!J$Z@rTE(!X)tvQS#4#˞PO:ϑWq|jڰZN.Md4ލ;7Gq٠pssd/˰1Y}|ZԐY=աu ?`MQX$U<G dG`7ϲ~#$HH2G&OK3N#1%3(,(m;"K^> -4Id2 ifB3dC# f=W̷Fk*q+x&. lq(^)kyXC[Pnb"- ^kCD " /ܪgA>h+kO&:9ޫx;ˉ{ZHl ƀc2c~lFcOR{jo7]q|'qaq9v6&Eݰm\'A0wfJG#]KDT Ĝ,vU;p.PfѝL%\mRy\kJROъxAA**wi})gU#kiu"YlxaX-1NE)'N)5qwK nDXlS?EݶP>W9;ێghBb35E.r8{N:H_`zԍxN<-U:9: -HE[$W_x=F/!>e(M:!k W۪tC))Ÿ^0 ! aeRf F'q]2;w"Vp!+`tea1t&ىb-.C!ol}U4K]9T_s?FgHz|X 2Z0EZ k4P{z' ܵY@5"t)9N?BLΫk#ǔ^xx"]~׸*WGyz5왆i+wQ%km*BQԊGtؐ@I;$ȓ`/Q:wkZOӵ,Z}Ǝ $x_4 y>^aᝯ`_fC"d]?gPU0U1t%t9aD* "_ _EڍbޣzQ>ÉN!_ȒRl);*(?. X{[sP2A~ϺyuYĢ/~bgx(."e\/4sqY Og8y/Z2,-fG>yS 0 "bsM{%8;tZ*IAMW Ӽ^#\)n$ي:5E@e2[[u\J(bY:a YI.,BE_t%zFeeUƀ,1bvqc@6"ڵS6&~2B\ -b2-u͘ItS`\T|Mn@$+F8s;HI"7k>h8&^Us,g> @ ?EJYPߐ! S#ˍXȬ3++ܫSR&^Lvt HiS)Vz{Xy%=(ivCŰc8.Zk`[2vھ6pFn`b Qs|ET5 SKӔ|ucRhؐIڛ64w$דpG}8D8v:Jb!BǪEJWB~vG4O 9ı -mRBA~l([ Z$]6CuC˥s ̣fp5K+QW{S3R<%X~EH]Yl]\lPD3:r$0ƽȚpkkX?,?$T+ >'1%aF)"oH -|L3 T &|ɌN5V)1T.lHkOS5Q)(C={!l8CEA}KZVJbU_E4 VՍymA8ۧ G9vh̋^ݹ=*D?IyD/DHz % ЯyJHVJ P47]p,D -``@D\#! (V4$Skl(rUӻ!~Uޛ|M+rԆ l@*.Ks}0]TB>J]84;Vc)Ad˓jAUӰ"g8Jz6SИ~HI$ ?0:t(zܻq>h:,-Z݁~:G{;f ÝO$T2m*Jۺ@eaqNU`\T+7Q$$R`ҿ'Icᛴ–|pRN"Iw8I7u]q0{Il H!EpM%ޝ[3Q[SaO=~F Gsӷ&Q+rcicʕ`rP˄+#~L lMi^q4,0!#9 VPi\eؒv0)Eo9^m#ْRI58$0N0%ƤXu7ڻ$ɗ6p9o`uwoG -eZ*zc.'$,.k)0R1 XF)ث=f Ws6rp6gOUO$9OQ  .ł(b#Y? "ǣj&JDP`tGT50D`fh]$UH^wS{"`N]p;]]Hxl盤Zڗ:ޛ04"em?7X(iy`LQRG .*baE]Cç8G:;qab(',r(1DݖQC#Ԓ@[9%OI%)ORbO,Iaδ'@m·9=d6K"RNYϚ|̙X]D4H8L}, -%9UQ4kr_voJB<\pm{g9ѫU52lrX@SxúDYC~ʬ(Nm~4O֬mP_-P(u6Jy444}'ᢛg8!1 Yѳ>#תV%O!HV{+phJ5WmMr9e]딞kR V?~Jh^UG$$CeYij!ڇí I,GIT1YfYlhqʏ#Uc6 A\7Aـ͘5A!3[&+~pm\khOk"e [؞1S)1@N@ǠivbGifϛdOT++M2!ge-/oE.XMHs#Dy4|[|a.Y[_&ܥPK4E:h,j%sϞ<ڹ{ѳu&#A/Uƿ-;Ȏ9u "c\%D-7xYĠ%IZ":I+ =F C9OpŶt1+ F@[uPI1Zr3(EŴbA#Qr ;dL ǀƚmEooygzgQnx/MY@f٫y<*ߢڒ+I$׿x=~~9N~zgs'nF4O,MRģH/Hc2@&DºWIcKWЄ羌+I2Xn*{&2ceaQ2&7w7QGyoUm>x{͟7ώ:%FDiyমZ?I<1/_\O @1F〝٨~KOC;YF< Aꄍ O y5"[D\8-~w=gO/Z%h}j<2qM)їr&$٦y0(R8AyKYNhˤ|LrG'ŲXte#w{X؏oȝНjO%SQ!axўZCzqL6Zp>q] w)sp!S'TlkiǭCV36Rf% -gr!ghj4IOd Hً95F~:-zWN*wF?m77Vf]Vf{ 7dSM3{ -ATHm}F %مeoQ9]pfh  -kEG,92( -ՐׅU#!SDo0dIdq"ON'x,>!m )}@mv>QMJ1Zk>ed -t(AV#B;hN8e~2{ *D :h#|^ 0 ۴ ^伐JGqr8Tͫ|;|J{VڳΕ1KVHrchKƔ"Y'H$efv">tx4"tI%pfAL ѮϰRDY) bp9Xx !mVlRxx"U)mޟ$zss$5wY~Bq㰆`Ea-o{ПCt^v|`$r7tNPvr삃trY93s'~+l"dܪ i>6~@Vc:E0q (y4Af|X@T4Idc-!4yש6+F,W)Ƃ9{++MGE}}Z{>l(I9bHB3jJY̐,m2I%7HeVSA^3Я4FykJp对VȲq!PL4^1,}``fXyd~O#񲈔+uץ6G 5XBG`]EfAJu 2LzP 5N_lHъJ!&c8Lp[l @x-=E(wW_U@L7т=[J"P(tdl nXg ݥL^q!mcGa{>w`ITtS|ԨlNɛWyv%yx&Yioqoo^Oo|pW+uOYꆺ{UR4gL4k%1E\ -#`ez@sMAvXjU!tN$:%W,i8'%Cg'2.(KԨnr,جMsM 5^%9lS2GшC"gW,R; Y$",P=k㛦ykrK4⽀+1̹8-{9%(ڻ1uXdhG-:8 D)2DX%S{^Vp4 Jko_ޢgcHݶmǽa+yp`\H'iMe}1 m‰ m# lD#$9In9?e0hjavA'>J%D{2H=)݀X\ - p\xjӊIcUBӠ1V]ҡaO +Y -gu d`Z薋u+\ҏJUgO@zXic^0eЙY?Du8WR2e"uY'0nA9S&O6SVGޱDdj4%A-? ,#O0IطvT兹C*(2~ieR巠s-XcjI?4d3ǞyWћ,k9| 4'`0~ RrqVU%x@R3e,0IA,j|HIk;D<.."C&غ,_/X=@VKm%& ^yk3B5 }-;ֲI T_ɘ"Ř] ~y{+[IVl޾l/.Ye[w$?Ya|;_v#1"Ƽ)XU *cZhj~'&bQQb^< =(!xkƲ"űZյ< S$ Af,Hxc -)9u]n*F^rg6׳Cvf`Qt҉{@MedAq0~cQVʴX0e2Lkt!b}S+VQ|UKZVd'<K?u8{]\OWs牗*WOְȣULY1*v8^sdlıLI;VCLHQ&vnvO]Z VC*}}^Ɣ>= -/i*TVy{5P~̀yM>QlSB*{0;ٞ|h ރO =# XwK9|Pc՜FzM8k g; -ZvYTP뺪,!9"E2P^ydi4+*Iz]0j,j73\o7=ѵ,=3T=3|]37} {àsb[Ft{ιξ^ax]y8U_2kЃ0LRRxm,A@C$叀i'hTNSqHyo>}l*Y1_½u0G5i[Sv0C3B󺒍'm n&E[[ns@L,CEU-Br̫qVw6k7Ht#ZL螼N$JY$rIo0^kgwn?~C;}}7cፙ?xS̨3M@BP=IdO @x7w/>ȄFVx.Ɔ90sw>G?ϫ(C!]_iŨH/u\ogGŐt&7Lo+%xeZZiQd4G:V -tOTx ?'H^ -aߘikq{rA}_iwwLcsF>A4Kd $$Oy#3 o)RYaQ\4 Hj6 |ʒ Y Zv4b |DК21Q eܶJSn{jOy=%I1o=jV`)"]+ORpNUQΞs╍Ko@8+ee5xii^)Ǖd%4QTsuBydȢ2;WLN( 1xrɤ^lA P0.Ryӗ?c#uuQ!~zHWN..F>  "t5ø=WQZ~vZԿs^hyg]ep/ֳ%,m}5%ri\@òS94RF-6V0)7U %x,8 ?-ox[rmNmߞml.By>w"noyRm?o_ǘUb .Ga[h=X\ S-uȺo%"H -mC~@(ICtVYҙ@{ZzIyiVuWңt/7~vG$=Xe(uWlb0$YVBqٜ > -n1eE[sAJZ6;-T6e4"̪alV.܄D.AX.30A]c9o_xQBaUoP0"cx̼LKڦ٭{5~Rzq/>1S%*EO(٣6^tgu{QߛC[-γJQ2ꢀnk -yJ_-g(x^feb_L22n40{A[uh'>_$U8\ּBc@4bG'™FbpHNfcxm,5CZY jAY*xRVnzځ}XG -za#j z *KI'AM$?o4eK٘4d:|A?4^J (YuAF8 [8DAbo1%Фbl~3f?VD>ӚlW -+ -E0WyvD$4D^}ohȒZGIx4[:ܹ[>(P=/D \$=Eq/,v:Ǣ'tKp*B7UTT^0p5 ܸtL -?F_>r?pɏ_(,f,>h_ }о$!^"5NpDE2v_x lF rlWTC^H:;5wU.;dC>`ō%,f l|$&dsjIꝵDp_]ѓPd'C&c#LA Md}B&PIRL` VC4>EBr --X߻!"hxz: v5=*Brqv{0p9*AR v{iMVtb]\6돀Uןk"C UvC -$|Pj)v*e *ip_ЋEE}T6E1e@-U˔ZF"Ή79^n1kI6(AЈK1i^BOX!9/(a_<{,a%'@Bb{ 9!8'PaVT+q6B=ų1" &ގ~K__gbܖӽi_Enj9 ̗jN"aD5XŌVrQ`adļ1,_&N\YUmR? Y "o3"Ym* -t_\$0_~! .sVU$\5:-;z>Yt0Dօ1-=qBQ^*iH;z3p>(jqQb>Y|JʣH oαa;7$L؞# -R@5!΄ft]3 Z5E3Rt߃r>6ƘMENkGcOY/;GsPv8Gs9~:G7.z 8;8͎k8. 4gAGKX)\:̌wEn1SC7K#hIxG<˱E:F@"iZ^P HBe҇PӵӘ{YƄd**"x/4oE|ƾ~uh\gb ,q%X_ -4lGSTJ;-)O;)}?U8%NWHfNRѠ2q$L䘧rG#il1~5G߃{ϔ~Qr~f$D콱r؏{w[I 8/ DNZgtfՋM{skXJƭqjFǩ} vh0r]ivry\= yxO8A 7b wpILƮ\Yq5}eey= )S# tIBPeʾ%zC{u+K׽2w+k!xQR m+GM&tѽi̟p_L2@51OyHy@w%%9~l 7\ۿE+GK"4bH /5"nԈ?`nQYE0l̙A$EW(W`dqzi"ՇH*,% v STIk$Bi"Uo M}͝[$`MM KDdT@T0u`ߐXQ&Eq#w?/>~CRC@eUWBLFiROgQ="62Qk6@~Oe3DHi!{ᬑ56pCcv$ebshh/~&cQ-"uۨZMrn/fTXbbKnCG .8њp:XBfYy&Rć &4k`=WQAӀ 6i)ǎ{5c5e -_W*#7djgPDq3[ ^Dګȧj4whIVg+z)9lÓ`di[ -4c15l iwQ|)_"g}z &`'EY%Ҥ4dS2:IRy71Y®2jy*Ytxdw!٥):GDҶ+BűȪ[YdY+3Ex4WX>5QMESt^LT/6J.~(q4bLN ;l$Fs1iZfMI -ت$:\] Dk@&夜tfOO{[A_ij𛭅bИ@&Q, un@ɈL J8K>.n͡ g{ 7l3MJ+2{J-y[4 0Al˕ӨE, 2a!0[SB $TȪlh -q -l 2$m%jI,tɓE hU7,coLȌmcl9F# -Sg%ubBJєhq́FST`~B6XxFzsDB\h$a;tiDi Ei璼 {a35ֱ -4lԑ됈XQL*dPQwo(Ç_ŀ!BX / q][Okx;k~.-_]qe\{/Oo_Ǥ4'CLP~eJ(Qȹh 3u) LCߨG1ʔ^bԇO@B b`O`+Xm1 `'IDw [KSeHWLzA&g RCum9۸k[s+&dh/'/5;b"(uA eiE>(N,Q=LW"yF/y\'}?IGe1,ЯH˸?-܊7@'H vnܷW-pW5Mdq9뀳 , -@a^e聅lX~aVuX8#:`㺠{cu H}1[)bTtDQd p; -wrbZ˪J ;Hb[c -a*#KD`L#zf)H#@b>H:wJņ+G(A{hV++ZzodDj2i 0^E2kWP*,Ȓ.[dڬleNɮX3dGV5ՎӋ:TЊYH=ז'?)C=VəTlH( :c3ςUep,miNʌ$W#uԟCUG]n]%\Ĭ^B u{!Όɳ=ڳ=߲}D9(_{sm+.6L*Z\2}uyT,KYwlQ.O"PeY Uc<$yW[w,}S`mo^iWB% N_Y6I\Bd{4EӒ* V1dzdx4Ѹ]>zl[|muaf-ayXE|t0,Y$Wy,Pw>{8-5YWTTV'V?_[ˎ0WkF0P.Tȩ2PM/Fǩ})sx+L6:^>u9v~ - R\P,, /AWe!.0ZlxY=.Co:[%ޞIuURZːMeZM:w>j15ɽ]AѣoMqua kĬ >EsWY++{`e2ul0ЍCLN2OLNd6mwg!ݶ/$Eb,"6*:OYj^37wXx {SO7͎6xJ)obVmmI鹛):x;zx>.nxDY2ahM3CV &+$^;̥bfqa~&2n-znn'$PPɇJD4ъ92$O6L8"KPl#F/xUZ4.J'jw^7dt\پ.fFmt,E$z7 6/Ӽ6zyjk yC{;ԾC{C e|XFbNF[8DI} kQX}Z(tX~T>Sʽ~Touko`nYKN 3 Xw |aJ쾠ܛXjxQGo|8 V} +! E#oD dZY%L/=?kcؤI͑>l搁e#;j%05JH],pwY}s=Wݡ=x^?݃3;±61J3rM!`r w3Hij[sxtj9dYlTwW;-gy<_%RtOe^P!P@I`婱1E"CNu -^ay4C&#TCQ̞ F@dP),8ә@ -D}#1~v Y?0?FȂtbArn:4؅6ePDt=rJ'H1=̝ds ]< ffVfWD8;$$ `'S&H s{h z Yyљ|3W_{_<+F5+8Qv A$e0w: Kzz{*xvx{j~ -zwzz?G=`Z[wop7]_kLk&ݨ+ +k#0̩]D7-Ljd0udb!KY!ZMW;6?5"hfʸdqhZZFn]*dbb=Tw}3:f@vio>V&6EXCf=#hwtXLVf_uKJH.J$ٛ,i Y[6{K?K!b(j"RJ!g)%M-_ -nu=݋0'j f[,WgDJ=. T(w$7I -1=suwo_o#or7otvKoWuw_ovsgOކXq`&-<|0l0Nv*pW_ȬR7XY z9zJGDU -Y2# I7-Me3eXZVb 늅j ^N's'/t[LKh[צ YUՃUS%x밥w½4`-!Pf-ԀIoqZ[5wUD)H5 |a>b|15cd`iaI~A= *BE 3!ao(aK5s=s=s/\Z%$}M١s3LĄ2 Xz;A/'+"xDqOY GjޫF6z5`A枣6O²Z#͇LG;ê|e A&2epe"9bpِM98xb3;E;}j2cG><4\ ѡ?E>`U#,?_"(1E͘: -!3HhKG eŽ#BẐD'u q %Gyjiz_ɤ]V:;dJJD   -zn{T`$#|*67nόM3&׷ە9{ `*%.[^-_&̀5KD p!|WM7U͐ 8}+G6>p9Ya~VEsT6 -:*_]VXU󡳊n! PXq0#u\gp fv4iDU8ho)N%Պb5~YMn<M}4x]Զn9PTjkBFe-ʫ2 L ,[f`_'e<=epQ.O UƖ.(T  YRICѓzp#'C3l:؏%xQp(/IdBNǠd5FΤ/}=O{W4w7m)rXrcj&gz&g -nX/;Og=KYrΒP$=(#a0ZyWhwuEojEc*ҹ ૦dgȒ,& (?ާ1A&NޔY;0:dUU܁FȆDƈ{l *P_T >k<<$MsV$C RYo=!#`=kY ZYp@3 -j\DCEɸ dK2.ʾ˒*dBOY R/͓wPX(,e)x.DK{`ă6 P -Ud rAN>wb>sw-,KDR8#iP -ƹ_du0d45QbYF:(_mi/Pn* - axj)-%Y u;q fDM^ץJ/#YY&&dCS~I %E&M>Rrxu#r_ǖQz0XٶzQ?/%'$ؓ"Nl(PD<730O>텴` N\VDjZ&S *h.{Q;g}<_?{: gƛAow4 s4qX-WXfv5%+E)qiǶʙ@rVj1+h^/cYȔ{9^Qqj)R4I=+[!-p"ٲBqebZZID{} 8BiFmK쫶aJt mlNZC-d`j]vOwYq\Pz8|m -<532(E<)d>P8([_6uTH-([ݸLTL3,g)FK3-sм"v–P%FBvQjb v]\F8?ey*`D>L2D7d%8+A8R&.^L[M_΄r "&V f):@5EtQe Y}" EB0?y2ҕ^84MQX]e4I1k!2V`TOjA'>)f+_R>O},nZ#--d VS7nۏ>{~K2_(݊SNGL¾ 9TCeϻswyI,'K”uG8rGWOJgH;S׊ Q2MX["2є͑fI+ K҄P2*(*{p6 K]S}v~[,my[R r)Ǚ I:cEKk'{@&B\s_QGyoVeMl&CFk˩D?rc}fZ8":uɾS^[pbawEDiKL[sD+uޤʡ К2уrM --u..ȹYX ۥ*kR$j?W@z N^ubLN!$e ꂶL`JE߮2 .yѮ%y_O?+'9N>uE'5>)v蟝멩λ{_Frt%nm)o ZWzյ yp\߹i>z'Շ͘D ^^"ƏLQȔˢʴw-e:q1: _] #B7H -Puof?,4<1c{w<=rw$djV̸BIoe2y0_9n\VK\| =MzeqI"$rW0Z/+:gz^cP2ZO{{7Gd[|&:h^64)9F"JO l t$zϪ';Ɨ9w|xK˼UW`eʽHUW$8vkm]DA["/U,~,hbZMB)ycj P-^ 1"ǓW2uP%JgiY(^~2s%p/e~rK䣓??YcWLCr$r'0"$ybZCgU"]P.2u}.`2~XAX/Wd먡T- 8dq }0I breT`bV8Ho{9_vJ^2?RK&Ktz'J5?KGQק -~ZIj`g>6Y+;ع.qJ/*9>Z-amO}(ڲINKM)8A4&V36\_! _ɌneJ%ՠWit)ּ3d.z 3,u=_6>wc)2-GWZӵ.E{h?k[_6쥝޲7y6ވ;8쇈wؠ!aCN 9tgy{x\1w4.K7ّ$-XH/?kYP;!95H'[[ow(sfik꺚7eZH+ "vKHtԈSp^KMw少sʂī7Yb@Y[.6=Q=YE~*jbSu ̫4!`1Gw4C4Zb -oElAza1JScXb&!G#mZ`saWU xDq I4iH2zti*#m-KݸN0z8wYe]YL o2im,.w弳YBNJuA)،#;rKe7bնtlhzbNEuIQchH _gOT*Qģ5.ݮY{kP -l'Јj^I(W -6s:i~Wj3bT:z2Br +8~pnaSTRBVRq~}v\^ձXqW#Zvkf3FA^yfw5I:,๶5Y %Pc1l|onuO]7z[1'!Ss%t -f%Kd*f!d$8^/=2Ȓ!a(4߂g/HӦvJ^"^{(dڋwaL*نX .+dm"4iwNব+{zoyH)O1"s*hs ?P3BFhJVhbs;]tggo̪ˊoc}LjL5*͜4ߑ>1tGQ| ]n7X]rHp)kPm-TII{{{|qQ";Z9M=!9`L4ώhe¹xDgRNM~6I%\q=1kC?{kA0ͶԟnyCkC;Y]jǚiۚVS=%]E>!7'UV.`t^-Fqj^%w:q\91mۦ@C@;e(( `GjʍV`F*j,10H=2U͛ziJH1z l!V`ڡ^%Pצj[+BE[5dXEt@`ߣg",}+mj,ۆk;Zm- }*2t6ibIb\5<ۙ\1=@7ШjB`ǒR46 b!6+ oʬP*P H*h5 - 4&D3N ²-} W$ͳ.bA; gǚj(*a֜ x[9{z0 ,0 -BZmpDxM1Mc*X896@p^R6q@ZaDIJav"Vq԰Ylv +N!_J۱"fii}K@Gv=#hO:*N -MH/Ɛ:rI*Аa`cV6A݉&\c@њ@(r/M uqZ2qs5|׫jpp]a &j*uаItZJR:- o!7X`ٔR4wj#HJ"rk2' Lhp T$ڭȀL\I%2819pq_|!c<ˤ`G;bрvXiuü"ljn5-XӖuz[鰱_$1 1*}{!xc*1,q>MnӪV{>s#֔KbWyHiGEX"SIZ-5n_aP&6D>O5 -Jy)(8rIXzKdԻ/ {(K1,zF1$.kh?ĩs;%O2@-oSp'=In{0},v@Ahh,W"ZE/Y\[+'nGXEW-dy1 = [S0'iUD dgajVP٬7^WMg ƃ J; ţC*kNY*׶mжm Ҷ|[G5+fmUv˼iP]MON޲.&HVL+b;S|/Fh>7G򎞱#CFͤQ2n̜]UܶUt?0[NVS*=x=F09|:G $6%JMML'ih25h$hἠcL(h5$;-aW2D7iBKВ0d i_D+7Ǫ$Z b).h -˹#ܙLB,o`Of@0߇1º:dCet.wLK:Iҧ%IH\)D02e@f&s9@+Qj2=h-!q@g| 4@B)cgxrΌРAw4 zb aU'~qgHB,/ f+7kbAhiŅ\i<{4$4^pz6z<;Og";u]mXi2׌;4\ Z'KHC2R1T+ !\N αHQ4OR4Uݻ\RYh10p{!x/yF $̞\V/c -0 (Xպy8G 3lkf)Z¸X%kZB{'}GHIW96eqadA;Y!-vƮhfU@T5 6óT'͓Y8¡v\>aW $*|oZ6@ȅ;Hi$GվIXOz`aifvά-7&Y(|*ἯpkkR-7HS -CՁ\rԫ+=gX* rZj;!2,A(tlyK2GV@cY0 P}EPRíOWEYIS4s,{)+ -}K 4fva3vAk .ӆb9kxQa5RhEI߲r9D0 )ʊ&A Fli.VVMpao3>'5G;uup l8Uւ9 4@\&ٸs,`Rpug *Cs=v1AL0Lθf 4sQjiK(B o(2>d#h9=ػ,c', x/Ґѽσ@s= -nmXX ƧQңnh㖚,N8K!9-awȓXby-HvE5HZ$]S40lCMNS}yͣMӘLwP+>Ydj/ʚĉ򝍜F|3wpArWCZ!#Lj %(8\b9VR`aş(v a Uҳ2:0 -OypJsq-\!$p0`" 4l`U0\h+qC]MHwE؈Rߺ:X9>>u0z4˞M_o_^[M,noj:FϛFuo-)Z? QWd,\D e^6c*=es$q{ߚ͕7oQ#.Qhc>Ε1oYOܧh]RL:8fbޛP -LXglas};6c0Ws#q{8Ӥ5H+뛧{o+ )O6\yf+(CAk٪*7nb+@fU*b-9NiC=H+뛵{oBh)k6a\yևl`&pR$+P?K1+mx!Fs$q{2km^tipw0G0#PL(&w; ׄK4nRgydQy(e tu|pzxޒ[[9ށ57(%0Z^/(B'$g#m}7my=Yc:Eˉ.PcAthi֌Rr/o-O~lnd -ݮ!8dcX0 ofrz&k:1|>}vzěfCƿ -2 ~i!/}CS^sd50fh=]Nu0u^Mq1efr3>Y&V7j69J -ۼy1dZ]-pS7hMÍv~\~}gdi߻$ty2]/V?{*i2 t>-6}ƶćuLg}F&-?-z06Ǵ,nfbhtԋv:zr=]~{3far5gaG>ʲ=op\M?߻>'Ѿd3ybtKod~ھ@qC-758{]|OLW~ -[d6ɫp\n&j׾p}sP# endstream endobj 16 0 obj <> endobj 109 0 obj <> endobj 201 0 obj <> endobj 296 0 obj <> endobj 391 0 obj <> endobj 485 0 obj <> endobj 553 0 obj <> endobj 621 0 obj <> endobj 689 0 obj <> endobj 757 0 obj <> endobj 825 0 obj <> endobj 893 0 obj <> endobj 961 0 obj <> endobj 1029 0 obj <> endobj 1097 0 obj <> endobj 1165 0 obj <> endobj 1233 0 obj <> endobj 1301 0 obj <> endobj 1369 0 obj <> endobj 1437 0 obj <> endobj 1505 0 obj <> endobj 1573 0 obj <> endobj 1641 0 obj <> endobj 1709 0 obj <> endobj 1775 0 obj <> endobj 1829 0 obj <> endobj 1884 0 obj <> endobj 1942 0 obj <> endobj 2000 0 obj <> endobj 2058 0 obj <> endobj 2116 0 obj <> endobj 2175 0 obj <> endobj 2244 0 obj <> endobj 2313 0 obj <> endobj 2382 0 obj <> endobj 2452 0 obj <> endobj 2522 0 obj <> endobj 2592 0 obj <> endobj 2662 0 obj <> endobj 2732 0 obj <> endobj 2751 0 obj [/View/Design] endobj 2752 0 obj <>>> endobj 2681 0 obj [/View/Design] endobj 2682 0 obj <>>> endobj 2611 0 obj [/View/Design] endobj 2612 0 obj <>>> endobj 2541 0 obj [/View/Design] endobj 2542 0 obj <>>> endobj 2471 0 obj [/View/Design] endobj 2472 0 obj <>>> endobj 2401 0 obj [/View/Design] endobj 2402 0 obj <>>> endobj 2331 0 obj [/View/Design] endobj 2332 0 obj <>>> endobj 2262 0 obj [/View/Design] endobj 2263 0 obj <>>> endobj 2193 0 obj [/View/Design] endobj 2194 0 obj <>>> endobj 2134 0 obj [/View/Design] endobj 2135 0 obj <>>> endobj 2076 0 obj [/View/Design] endobj 2077 0 obj <>>> endobj 2018 0 obj [/View/Design] endobj 2019 0 obj <>>> endobj 1960 0 obj [/View/Design] endobj 1961 0 obj <>>> endobj 1902 0 obj [/View/Design] endobj 1903 0 obj <>>> endobj 1847 0 obj [/View/Design] endobj 1848 0 obj <>>> endobj 1793 0 obj [/View/Design] endobj 1794 0 obj <>>> endobj 1727 0 obj [/View/Design] endobj 1728 0 obj <>>> endobj 1659 0 obj [/View/Design] endobj 1660 0 obj <>>> endobj 1591 0 obj [/View/Design] endobj 1592 0 obj <>>> endobj 1523 0 obj [/View/Design] endobj 1524 0 obj <>>> endobj 1455 0 obj [/View/Design] endobj 1456 0 obj <>>> endobj 1387 0 obj [/View/Design] endobj 1388 0 obj <>>> endobj 1319 0 obj [/View/Design] endobj 1320 0 obj <>>> endobj 1251 0 obj [/View/Design] endobj 1252 0 obj <>>> endobj 1183 0 obj [/View/Design] endobj 1184 0 obj <>>> endobj 1115 0 obj [/View/Design] endobj 1116 0 obj <>>> endobj 1047 0 obj [/View/Design] endobj 1048 0 obj <>>> endobj 979 0 obj [/View/Design] endobj 980 0 obj <>>> endobj 911 0 obj [/View/Design] endobj 912 0 obj <>>> endobj 843 0 obj [/View/Design] endobj 844 0 obj <>>> endobj 775 0 obj [/View/Design] endobj 776 0 obj <>>> endobj 707 0 obj [/View/Design] endobj 708 0 obj <>>> endobj 639 0 obj [/View/Design] endobj 640 0 obj <>>> endobj 571 0 obj [/View/Design] endobj 572 0 obj <>>> endobj 503 0 obj [/View/Design] endobj 504 0 obj <>>> endobj 426 0 obj [/View/Design] endobj 427 0 obj <>>> endobj 331 0 obj [/View/Design] endobj 332 0 obj <>>> endobj 236 0 obj [/View/Design] endobj 237 0 obj <>>> endobj 143 0 obj [/View/Design] endobj 144 0 obj <>>> endobj 51 0 obj [/View/Design] endobj 52 0 obj <>>> endobj 2803 0 obj [2802 0 R] endobj 2861 0 obj <> endobj xref 0 2862 0000000004 65535 f -0000000016 00000 n -0000000845 00000 n -0000032129 00000 n -0000000005 00000 f -0000000006 00000 f -0000000007 00000 f -0000000008 00000 f -0000000009 00000 f -0000000010 00000 f -0000000011 00000 f -0000000012 00000 f -0000000013 00000 f -0000000014 00000 f -0000000015 00000 f -0000000017 00000 f -0000725442 00000 n -0000000019 00000 f -0000032181 00000 n -0000000020 00000 f -0000000021 00000 f -0000000022 00000 f -0000000023 00000 f -0000000024 00000 f -0000000025 00000 f -0000000026 00000 f -0000000027 00000 f -0000000028 00000 f -0000000029 00000 f -0000000030 00000 f -0000000031 00000 f -0000000032 00000 f -0000000033 00000 f -0000000034 00000 f -0000000035 00000 f -0000000036 00000 f -0000000037 00000 f -0000000038 00000 f -0000000039 00000 f -0000000040 00000 f -0000000041 00000 f -0000000042 00000 f -0000000043 00000 f -0000000044 00000 f -0000000045 00000 f -0000000046 00000 f -0000000047 00000 f -0000000048 00000 f -0000000049 00000 f -0000000050 00000 f -0000000053 00000 f -0000733216 00000 n -0000733247 00000 n -0000000054 00000 f -0000000055 00000 f -0000000056 00000 f -0000000057 00000 f -0000000058 00000 f -0000000059 00000 f -0000000060 00000 f -0000000061 00000 f -0000000062 00000 f -0000000063 00000 f -0000000064 00000 f -0000000065 00000 f -0000000066 00000 f -0000000067 00000 f -0000000068 00000 f -0000000069 00000 f -0000000070 00000 f -0000000071 00000 f -0000000072 00000 f -0000000073 00000 f -0000000074 00000 f -0000000075 00000 f -0000000076 00000 f -0000000077 00000 f -0000000078 00000 f -0000000079 00000 f -0000000080 00000 f -0000000081 00000 f -0000000082 00000 f -0000000083 00000 f -0000000084 00000 f -0000000085 00000 f -0000000086 00000 f -0000000087 00000 f -0000000088 00000 f -0000000089 00000 f -0000000090 00000 f -0000000091 00000 f -0000000092 00000 f -0000000093 00000 f -0000000094 00000 f -0000000095 00000 f -0000000096 00000 f -0000000097 00000 f -0000000098 00000 f -0000000099 00000 f -0000000100 00000 f -0000000101 00000 f -0000000102 00000 f -0000000103 00000 f -0000000104 00000 f -0000000105 00000 f -0000000106 00000 f -0000000107 00000 f -0000000108 00000 f -0000000110 00000 f -0000725515 00000 n -0000000111 00000 f -0000000112 00000 f -0000000113 00000 f -0000000114 00000 f -0000000115 00000 f -0000000116 00000 f -0000000117 00000 f -0000000118 00000 f -0000000119 00000 f -0000000120 00000 f -0000000121 00000 f -0000000122 00000 f -0000000123 00000 f -0000000124 00000 f -0000000125 00000 f -0000000126 00000 f -0000000127 00000 f -0000000128 00000 f -0000000129 00000 f -0000000130 00000 f -0000000131 00000 f -0000000132 00000 f -0000000133 00000 f -0000000134 00000 f -0000000135 00000 f -0000000136 00000 f -0000000137 00000 f -0000000138 00000 f -0000000139 00000 f -0000000140 00000 f -0000000141 00000 f -0000000142 00000 f -0000000145 00000 f -0000733098 00000 n -0000733130 00000 n -0000000146 00000 f -0000000147 00000 f -0000000148 00000 f -0000000149 00000 f -0000000150 00000 f -0000000151 00000 f -0000000152 00000 f -0000000153 00000 f -0000000154 00000 f -0000000155 00000 f -0000000156 00000 f -0000000157 00000 f -0000000158 00000 f -0000000159 00000 f -0000000160 00000 f -0000000161 00000 f -0000000162 00000 f -0000000163 00000 f -0000000164 00000 f -0000000165 00000 f -0000000166 00000 f -0000000167 00000 f -0000000168 00000 f -0000000169 00000 f -0000000170 00000 f -0000000171 00000 f -0000000172 00000 f -0000000173 00000 f -0000000174 00000 f -0000000175 00000 f -0000000176 00000 f -0000000177 00000 f -0000000178 00000 f -0000000179 00000 f -0000000180 00000 f -0000000181 00000 f -0000000182 00000 f -0000000183 00000 f -0000000184 00000 f -0000000185 00000 f -0000000186 00000 f -0000000187 00000 f -0000000188 00000 f -0000000189 00000 f -0000000190 00000 f -0000000191 00000 f -0000000192 00000 f -0000000193 00000 f -0000000194 00000 f -0000000195 00000 f -0000000196 00000 f -0000000197 00000 f -0000000198 00000 f -0000000199 00000 f -0000000200 00000 f -0000000202 00000 f -0000725591 00000 n -0000000203 00000 f -0000000204 00000 f -0000000205 00000 f -0000000206 00000 f -0000000207 00000 f -0000000208 00000 f -0000000209 00000 f -0000000210 00000 f -0000000211 00000 f -0000000212 00000 f -0000000213 00000 f -0000000214 00000 f -0000000215 00000 f -0000000216 00000 f -0000000217 00000 f -0000000218 00000 f -0000000219 00000 f -0000000220 00000 f -0000000221 00000 f -0000000222 00000 f -0000000223 00000 f -0000000224 00000 f -0000000225 00000 f -0000000226 00000 f -0000000227 00000 f -0000000228 00000 f -0000000229 00000 f -0000000230 00000 f -0000000231 00000 f -0000000232 00000 f -0000000233 00000 f -0000000234 00000 f -0000000235 00000 f -0000000238 00000 f -0000732980 00000 n -0000733012 00000 n -0000000239 00000 f -0000000240 00000 f -0000000241 00000 f -0000000242 00000 f -0000000243 00000 f -0000000244 00000 f -0000000245 00000 f -0000000246 00000 f -0000000247 00000 f -0000000248 00000 f -0000000249 00000 f -0000000250 00000 f -0000000251 00000 f -0000000252 00000 f -0000000253 00000 f -0000000254 00000 f -0000000255 00000 f -0000000256 00000 f -0000000257 00000 f -0000000258 00000 f -0000000259 00000 f -0000000260 00000 f -0000000261 00000 f -0000000262 00000 f -0000000263 00000 f -0000000264 00000 f -0000000265 00000 f -0000000266 00000 f -0000000267 00000 f -0000000268 00000 f -0000000269 00000 f -0000000270 00000 f -0000000271 00000 f -0000000272 00000 f -0000000273 00000 f -0000000274 00000 f -0000000275 00000 f -0000000276 00000 f -0000000277 00000 f -0000000278 00000 f -0000000279 00000 f -0000000280 00000 f -0000000281 00000 f -0000000282 00000 f -0000000283 00000 f -0000000284 00000 f -0000000285 00000 f -0000000286 00000 f -0000000287 00000 f -0000000288 00000 f -0000000289 00000 f -0000000290 00000 f -0000000291 00000 f -0000000292 00000 f -0000000293 00000 f -0000000294 00000 f -0000000295 00000 f -0000000297 00000 f -0000725667 00000 n -0000000298 00000 f -0000000299 00000 f -0000000300 00000 f -0000000301 00000 f -0000000302 00000 f -0000000303 00000 f -0000000304 00000 f -0000000305 00000 f -0000000306 00000 f -0000000307 00000 f -0000000308 00000 f -0000000309 00000 f -0000000310 00000 f -0000000311 00000 f -0000000312 00000 f -0000000313 00000 f -0000000314 00000 f -0000000315 00000 f -0000000316 00000 f -0000000317 00000 f -0000000318 00000 f -0000000319 00000 f -0000000320 00000 f -0000000321 00000 f -0000000322 00000 f -0000000323 00000 f -0000000324 00000 f -0000000325 00000 f -0000000326 00000 f -0000000327 00000 f -0000000328 00000 f -0000000329 00000 f -0000000330 00000 f -0000000333 00000 f -0000732862 00000 n -0000732894 00000 n -0000000334 00000 f -0000000335 00000 f -0000000336 00000 f -0000000337 00000 f -0000000338 00000 f -0000000339 00000 f -0000000340 00000 f -0000000341 00000 f -0000000342 00000 f -0000000343 00000 f -0000000344 00000 f -0000000345 00000 f -0000000346 00000 f -0000000347 00000 f -0000000348 00000 f -0000000349 00000 f -0000000350 00000 f -0000000351 00000 f -0000000352 00000 f -0000000353 00000 f -0000000354 00000 f -0000000355 00000 f -0000000356 00000 f -0000000357 00000 f -0000000358 00000 f -0000000359 00000 f -0000000360 00000 f -0000000361 00000 f -0000000362 00000 f -0000000363 00000 f -0000000364 00000 f -0000000365 00000 f -0000000366 00000 f -0000000367 00000 f -0000000368 00000 f -0000000369 00000 f -0000000370 00000 f -0000000371 00000 f -0000000372 00000 f -0000000373 00000 f -0000000374 00000 f -0000000375 00000 f -0000000376 00000 f -0000000377 00000 f -0000000378 00000 f -0000000379 00000 f -0000000380 00000 f -0000000381 00000 f -0000000382 00000 f -0000000383 00000 f -0000000384 00000 f -0000000385 00000 f -0000000386 00000 f -0000000387 00000 f -0000000388 00000 f -0000000389 00000 f -0000000390 00000 f -0000000392 00000 f -0000725743 00000 n -0000000393 00000 f -0000000394 00000 f -0000000395 00000 f -0000000396 00000 f -0000000397 00000 f -0000000398 00000 f -0000000399 00000 f -0000000400 00000 f -0000000401 00000 f -0000000402 00000 f -0000000403 00000 f -0000000404 00000 f -0000000405 00000 f -0000000406 00000 f -0000000407 00000 f -0000000408 00000 f -0000000409 00000 f -0000000410 00000 f -0000000411 00000 f -0000000412 00000 f -0000000413 00000 f -0000000414 00000 f -0000000415 00000 f -0000000416 00000 f -0000000417 00000 f -0000000418 00000 f -0000000419 00000 f -0000000420 00000 f -0000000421 00000 f -0000000422 00000 f -0000000423 00000 f -0000000424 00000 f -0000000425 00000 f -0000000428 00000 f -0000732744 00000 n -0000732776 00000 n -0000000429 00000 f -0000000430 00000 f -0000000431 00000 f -0000000432 00000 f -0000000433 00000 f -0000000434 00000 f -0000000435 00000 f -0000000436 00000 f -0000000437 00000 f -0000000438 00000 f -0000000439 00000 f -0000000440 00000 f -0000000441 00000 f -0000000442 00000 f -0000000443 00000 f -0000000444 00000 f -0000000445 00000 f -0000000446 00000 f -0000000447 00000 f -0000000448 00000 f -0000000449 00000 f -0000000450 00000 f -0000000451 00000 f -0000000452 00000 f -0000000453 00000 f -0000000454 00000 f -0000000455 00000 f -0000000456 00000 f -0000000457 00000 f -0000000458 00000 f -0000000459 00000 f -0000000460 00000 f -0000000461 00000 f -0000000462 00000 f -0000000463 00000 f -0000000464 00000 f -0000000465 00000 f -0000000466 00000 f -0000000467 00000 f -0000000468 00000 f -0000000469 00000 f -0000000470 00000 f -0000000471 00000 f -0000000472 00000 f -0000000473 00000 f -0000000474 00000 f -0000000475 00000 f -0000000476 00000 f -0000000477 00000 f -0000000478 00000 f -0000000479 00000 f -0000000480 00000 f -0000000481 00000 f -0000000482 00000 f -0000000483 00000 f -0000000484 00000 f -0000000486 00000 f -0000725819 00000 n -0000000487 00000 f -0000000488 00000 f -0000000489 00000 f -0000000490 00000 f -0000000491 00000 f -0000000492 00000 f -0000000493 00000 f -0000000494 00000 f -0000000495 00000 f -0000000496 00000 f -0000000497 00000 f -0000000498 00000 f -0000000499 00000 f -0000000500 00000 f -0000000501 00000 f -0000000502 00000 f -0000000505 00000 f -0000732626 00000 n -0000732658 00000 n -0000000506 00000 f -0000000507 00000 f -0000000508 00000 f -0000000509 00000 f -0000000510 00000 f -0000000511 00000 f -0000000512 00000 f -0000000513 00000 f -0000000514 00000 f -0000000515 00000 f -0000000516 00000 f -0000000517 00000 f -0000000518 00000 f -0000000519 00000 f -0000000520 00000 f -0000000521 00000 f -0000000522 00000 f -0000000523 00000 f -0000000524 00000 f -0000000525 00000 f -0000000526 00000 f -0000000527 00000 f -0000000528 00000 f -0000000529 00000 f -0000000530 00000 f -0000000531 00000 f -0000000532 00000 f -0000000533 00000 f -0000000534 00000 f -0000000535 00000 f -0000000536 00000 f -0000000537 00000 f -0000000538 00000 f -0000000539 00000 f -0000000540 00000 f -0000000541 00000 f -0000000542 00000 f -0000000543 00000 f -0000000544 00000 f -0000000545 00000 f -0000000546 00000 f -0000000547 00000 f -0000000548 00000 f -0000000549 00000 f -0000000550 00000 f -0000000551 00000 f -0000000552 00000 f -0000000554 00000 f -0000725895 00000 n -0000000555 00000 f -0000000556 00000 f -0000000557 00000 f -0000000558 00000 f -0000000559 00000 f -0000000560 00000 f -0000000561 00000 f -0000000562 00000 f -0000000563 00000 f -0000000564 00000 f -0000000565 00000 f -0000000566 00000 f -0000000567 00000 f -0000000568 00000 f -0000000569 00000 f -0000000570 00000 f -0000000573 00000 f -0000732508 00000 n -0000732540 00000 n -0000000574 00000 f -0000000575 00000 f -0000000576 00000 f -0000000577 00000 f -0000000578 00000 f -0000000579 00000 f -0000000580 00000 f -0000000581 00000 f -0000000582 00000 f -0000000583 00000 f -0000000584 00000 f -0000000585 00000 f -0000000586 00000 f -0000000587 00000 f -0000000588 00000 f -0000000589 00000 f -0000000590 00000 f -0000000591 00000 f -0000000592 00000 f -0000000593 00000 f -0000000594 00000 f -0000000595 00000 f -0000000596 00000 f -0000000597 00000 f -0000000598 00000 f -0000000599 00000 f -0000000600 00000 f -0000000601 00000 f -0000000602 00000 f -0000000603 00000 f -0000000604 00000 f -0000000605 00000 f -0000000606 00000 f -0000000607 00000 f -0000000608 00000 f -0000000609 00000 f -0000000610 00000 f -0000000611 00000 f -0000000612 00000 f -0000000613 00000 f -0000000614 00000 f -0000000615 00000 f -0000000616 00000 f -0000000617 00000 f -0000000618 00000 f -0000000619 00000 f -0000000620 00000 f -0000000622 00000 f -0000725971 00000 n -0000000623 00000 f -0000000624 00000 f -0000000625 00000 f -0000000626 00000 f -0000000627 00000 f -0000000628 00000 f -0000000629 00000 f -0000000630 00000 f -0000000631 00000 f -0000000632 00000 f -0000000633 00000 f -0000000634 00000 f -0000000635 00000 f -0000000636 00000 f -0000000637 00000 f -0000000638 00000 f -0000000641 00000 f -0000732390 00000 n -0000732422 00000 n -0000000642 00000 f -0000000643 00000 f -0000000644 00000 f -0000000645 00000 f -0000000646 00000 f -0000000647 00000 f -0000000648 00000 f -0000000649 00000 f -0000000650 00000 f -0000000651 00000 f -0000000652 00000 f -0000000653 00000 f -0000000654 00000 f -0000000655 00000 f -0000000656 00000 f -0000000657 00000 f -0000000658 00000 f -0000000659 00000 f -0000000660 00000 f -0000000661 00000 f -0000000662 00000 f -0000000663 00000 f -0000000664 00000 f -0000000665 00000 f -0000000666 00000 f -0000000667 00000 f -0000000668 00000 f -0000000669 00000 f -0000000670 00000 f -0000000671 00000 f -0000000672 00000 f -0000000673 00000 f -0000000674 00000 f -0000000675 00000 f -0000000676 00000 f -0000000677 00000 f -0000000678 00000 f -0000000679 00000 f -0000000680 00000 f -0000000681 00000 f -0000000682 00000 f -0000000683 00000 f -0000000684 00000 f -0000000685 00000 f -0000000686 00000 f -0000000687 00000 f -0000000688 00000 f -0000000690 00000 f -0000726047 00000 n -0000000691 00000 f -0000000692 00000 f -0000000693 00000 f -0000000694 00000 f -0000000695 00000 f -0000000696 00000 f -0000000697 00000 f -0000000698 00000 f -0000000699 00000 f -0000000700 00000 f -0000000701 00000 f -0000000702 00000 f -0000000703 00000 f -0000000704 00000 f -0000000705 00000 f -0000000706 00000 f -0000000709 00000 f -0000732272 00000 n -0000732304 00000 n -0000000710 00000 f -0000000711 00000 f -0000000712 00000 f -0000000713 00000 f -0000000714 00000 f -0000000715 00000 f -0000000716 00000 f -0000000717 00000 f -0000000718 00000 f -0000000719 00000 f -0000000720 00000 f -0000000721 00000 f -0000000722 00000 f -0000000723 00000 f -0000000724 00000 f -0000000725 00000 f -0000000726 00000 f -0000000727 00000 f -0000000728 00000 f -0000000729 00000 f -0000000730 00000 f -0000000731 00000 f -0000000732 00000 f -0000000733 00000 f -0000000734 00000 f -0000000735 00000 f -0000000736 00000 f -0000000737 00000 f -0000000738 00000 f -0000000739 00000 f -0000000740 00000 f -0000000741 00000 f -0000000742 00000 f -0000000743 00000 f -0000000744 00000 f -0000000745 00000 f -0000000746 00000 f -0000000747 00000 f -0000000748 00000 f -0000000749 00000 f -0000000750 00000 f -0000000751 00000 f -0000000752 00000 f -0000000753 00000 f -0000000754 00000 f -0000000755 00000 f -0000000756 00000 f -0000000758 00000 f -0000726123 00000 n -0000000759 00000 f -0000000760 00000 f -0000000761 00000 f -0000000762 00000 f -0000000763 00000 f -0000000764 00000 f -0000000765 00000 f -0000000766 00000 f -0000000767 00000 f -0000000768 00000 f -0000000769 00000 f -0000000770 00000 f -0000000771 00000 f -0000000772 00000 f -0000000773 00000 f -0000000774 00000 f -0000000777 00000 f -0000732154 00000 n -0000732186 00000 n -0000000778 00000 f -0000000779 00000 f -0000000780 00000 f -0000000781 00000 f -0000000782 00000 f -0000000783 00000 f -0000000784 00000 f -0000000785 00000 f -0000000786 00000 f -0000000787 00000 f -0000000788 00000 f -0000000789 00000 f -0000000790 00000 f -0000000791 00000 f -0000000792 00000 f -0000000793 00000 f -0000000794 00000 f -0000000795 00000 f -0000000796 00000 f -0000000797 00000 f -0000000798 00000 f -0000000799 00000 f -0000000800 00000 f -0000000801 00000 f -0000000802 00000 f -0000000803 00000 f -0000000804 00000 f -0000000805 00000 f -0000000806 00000 f -0000000807 00000 f -0000000808 00000 f -0000000809 00000 f -0000000810 00000 f -0000000811 00000 f -0000000812 00000 f -0000000813 00000 f -0000000814 00000 f -0000000815 00000 f -0000000816 00000 f -0000000817 00000 f -0000000818 00000 f -0000000819 00000 f -0000000820 00000 f -0000000821 00000 f -0000000822 00000 f -0000000823 00000 f -0000000824 00000 f -0000000826 00000 f -0000726199 00000 n -0000000827 00000 f -0000000828 00000 f -0000000829 00000 f -0000000830 00000 f -0000000831 00000 f -0000000832 00000 f -0000000833 00000 f -0000000834 00000 f -0000000835 00000 f -0000000836 00000 f -0000000837 00000 f -0000000838 00000 f -0000000839 00000 f -0000000840 00000 f -0000000841 00000 f -0000000842 00000 f -0000000845 00000 f -0000732036 00000 n -0000732068 00000 n -0000000846 00000 f -0000000847 00000 f -0000000848 00000 f -0000000849 00000 f -0000000850 00000 f -0000000851 00000 f -0000000852 00000 f -0000000853 00000 f -0000000854 00000 f -0000000855 00000 f -0000000856 00000 f -0000000857 00000 f -0000000858 00000 f -0000000859 00000 f -0000000860 00000 f -0000000861 00000 f -0000000862 00000 f -0000000863 00000 f -0000000864 00000 f -0000000865 00000 f -0000000866 00000 f -0000000867 00000 f -0000000868 00000 f -0000000869 00000 f -0000000870 00000 f -0000000871 00000 f -0000000872 00000 f -0000000873 00000 f -0000000874 00000 f -0000000875 00000 f -0000000876 00000 f -0000000877 00000 f -0000000878 00000 f -0000000879 00000 f -0000000880 00000 f -0000000881 00000 f -0000000882 00000 f -0000000883 00000 f -0000000884 00000 f -0000000885 00000 f -0000000886 00000 f -0000000887 00000 f -0000000888 00000 f -0000000889 00000 f -0000000890 00000 f -0000000891 00000 f -0000000892 00000 f -0000000894 00000 f -0000726275 00000 n -0000000895 00000 f -0000000896 00000 f -0000000897 00000 f -0000000898 00000 f -0000000899 00000 f -0000000900 00000 f -0000000901 00000 f -0000000902 00000 f -0000000903 00000 f -0000000904 00000 f -0000000905 00000 f -0000000906 00000 f -0000000907 00000 f -0000000908 00000 f -0000000909 00000 f -0000000910 00000 f -0000000913 00000 f -0000731918 00000 n -0000731950 00000 n -0000000914 00000 f -0000000915 00000 f -0000000916 00000 f -0000000917 00000 f -0000000918 00000 f -0000000919 00000 f -0000000920 00000 f -0000000921 00000 f -0000000922 00000 f -0000000923 00000 f -0000000924 00000 f -0000000925 00000 f -0000000926 00000 f -0000000927 00000 f -0000000928 00000 f -0000000929 00000 f -0000000930 00000 f -0000000931 00000 f -0000000932 00000 f -0000000933 00000 f -0000000934 00000 f -0000000935 00000 f -0000000936 00000 f -0000000937 00000 f -0000000938 00000 f -0000000939 00000 f -0000000940 00000 f -0000000941 00000 f -0000000942 00000 f -0000000943 00000 f -0000000944 00000 f -0000000945 00000 f -0000000946 00000 f -0000000947 00000 f -0000000948 00000 f -0000000949 00000 f -0000000950 00000 f -0000000951 00000 f -0000000952 00000 f -0000000953 00000 f -0000000954 00000 f -0000000955 00000 f -0000000956 00000 f -0000000957 00000 f -0000000958 00000 f -0000000959 00000 f -0000000960 00000 f -0000000962 00000 f -0000726351 00000 n -0000000963 00000 f -0000000964 00000 f -0000000965 00000 f -0000000966 00000 f -0000000967 00000 f -0000000968 00000 f -0000000969 00000 f -0000000970 00000 f -0000000971 00000 f -0000000972 00000 f -0000000973 00000 f -0000000974 00000 f -0000000975 00000 f -0000000976 00000 f -0000000977 00000 f -0000000978 00000 f -0000000981 00000 f -0000731800 00000 n -0000731832 00000 n -0000000982 00000 f -0000000983 00000 f -0000000984 00000 f -0000000985 00000 f -0000000986 00000 f -0000000987 00000 f -0000000988 00000 f -0000000989 00000 f -0000000990 00000 f -0000000991 00000 f -0000000992 00000 f -0000000993 00000 f -0000000994 00000 f -0000000995 00000 f -0000000996 00000 f -0000000997 00000 f -0000000998 00000 f -0000000999 00000 f -0000001000 00000 f -0000001001 00000 f -0000001002 00000 f -0000001003 00000 f -0000001004 00000 f -0000001005 00000 f -0000001006 00000 f -0000001007 00000 f -0000001008 00000 f -0000001009 00000 f -0000001010 00000 f -0000001011 00000 f -0000001012 00000 f -0000001013 00000 f -0000001014 00000 f -0000001015 00000 f -0000001016 00000 f -0000001017 00000 f -0000001018 00000 f -0000001019 00000 f -0000001020 00000 f -0000001021 00000 f -0000001022 00000 f -0000001023 00000 f -0000001024 00000 f -0000001025 00000 f -0000001026 00000 f -0000001027 00000 f -0000001028 00000 f -0000001030 00000 f -0000726427 00000 n -0000001031 00000 f -0000001032 00000 f -0000001033 00000 f -0000001034 00000 f -0000001035 00000 f -0000001036 00000 f -0000001037 00000 f -0000001038 00000 f -0000001039 00000 f -0000001040 00000 f -0000001041 00000 f -0000001042 00000 f -0000001043 00000 f -0000001044 00000 f -0000001045 00000 f -0000001046 00000 f -0000001049 00000 f -0000731680 00000 n -0000731713 00000 n -0000001050 00000 f -0000001051 00000 f -0000001052 00000 f -0000001053 00000 f -0000001054 00000 f -0000001055 00000 f -0000001056 00000 f -0000001057 00000 f -0000001058 00000 f -0000001059 00000 f -0000001060 00000 f -0000001061 00000 f -0000001062 00000 f -0000001063 00000 f -0000001064 00000 f -0000001065 00000 f -0000001066 00000 f -0000001067 00000 f -0000001068 00000 f -0000001069 00000 f -0000001070 00000 f -0000001071 00000 f -0000001072 00000 f -0000001073 00000 f -0000001074 00000 f -0000001075 00000 f -0000001076 00000 f -0000001077 00000 f -0000001078 00000 f -0000001079 00000 f -0000001080 00000 f -0000001081 00000 f -0000001082 00000 f -0000001083 00000 f -0000001084 00000 f -0000001085 00000 f -0000001086 00000 f -0000001087 00000 f -0000001088 00000 f -0000001089 00000 f -0000001090 00000 f -0000001091 00000 f -0000001092 00000 f -0000001093 00000 f -0000001094 00000 f -0000001095 00000 f -0000001096 00000 f -0000001098 00000 f -0000726506 00000 n -0000001099 00000 f -0000001100 00000 f -0000001101 00000 f -0000001102 00000 f -0000001103 00000 f -0000001104 00000 f -0000001105 00000 f -0000001106 00000 f -0000001107 00000 f -0000001108 00000 f -0000001109 00000 f -0000001110 00000 f -0000001111 00000 f -0000001112 00000 f -0000001113 00000 f -0000001114 00000 f -0000001117 00000 f -0000731560 00000 n -0000731593 00000 n -0000001118 00000 f -0000001119 00000 f -0000001120 00000 f -0000001121 00000 f -0000001122 00000 f -0000001123 00000 f -0000001124 00000 f -0000001125 00000 f -0000001126 00000 f -0000001127 00000 f -0000001128 00000 f -0000001129 00000 f -0000001130 00000 f -0000001131 00000 f -0000001132 00000 f -0000001133 00000 f -0000001134 00000 f -0000001135 00000 f -0000001136 00000 f -0000001137 00000 f -0000001138 00000 f -0000001139 00000 f -0000001140 00000 f -0000001141 00000 f -0000001142 00000 f -0000001143 00000 f -0000001144 00000 f -0000001145 00000 f -0000001146 00000 f -0000001147 00000 f -0000001148 00000 f -0000001149 00000 f -0000001150 00000 f -0000001151 00000 f -0000001152 00000 f -0000001153 00000 f -0000001154 00000 f -0000001155 00000 f -0000001156 00000 f -0000001157 00000 f -0000001158 00000 f -0000001159 00000 f -0000001160 00000 f -0000001161 00000 f -0000001162 00000 f -0000001163 00000 f -0000001164 00000 f -0000001166 00000 f -0000726585 00000 n -0000001167 00000 f -0000001168 00000 f -0000001169 00000 f -0000001170 00000 f -0000001171 00000 f -0000001172 00000 f -0000001173 00000 f -0000001174 00000 f -0000001175 00000 f -0000001176 00000 f -0000001177 00000 f -0000001178 00000 f -0000001179 00000 f -0000001180 00000 f -0000001181 00000 f -0000001182 00000 f -0000001185 00000 f -0000731440 00000 n -0000731473 00000 n -0000001186 00000 f -0000001187 00000 f -0000001188 00000 f -0000001189 00000 f -0000001190 00000 f -0000001191 00000 f -0000001192 00000 f -0000001193 00000 f -0000001194 00000 f -0000001195 00000 f -0000001196 00000 f -0000001197 00000 f -0000001198 00000 f -0000001199 00000 f -0000001200 00000 f -0000001201 00000 f -0000001202 00000 f -0000001203 00000 f -0000001204 00000 f -0000001205 00000 f -0000001206 00000 f -0000001207 00000 f -0000001208 00000 f -0000001209 00000 f -0000001210 00000 f -0000001211 00000 f -0000001212 00000 f -0000001213 00000 f -0000001214 00000 f -0000001215 00000 f -0000001216 00000 f -0000001217 00000 f -0000001218 00000 f -0000001219 00000 f -0000001220 00000 f -0000001221 00000 f -0000001222 00000 f -0000001223 00000 f -0000001224 00000 f -0000001225 00000 f -0000001226 00000 f -0000001227 00000 f -0000001228 00000 f -0000001229 00000 f -0000001230 00000 f -0000001231 00000 f -0000001232 00000 f -0000001234 00000 f -0000726664 00000 n -0000001235 00000 f -0000001236 00000 f -0000001237 00000 f -0000001238 00000 f -0000001239 00000 f -0000001240 00000 f -0000001241 00000 f -0000001242 00000 f -0000001243 00000 f -0000001244 00000 f -0000001245 00000 f -0000001246 00000 f -0000001247 00000 f -0000001248 00000 f -0000001249 00000 f -0000001250 00000 f -0000001253 00000 f -0000731320 00000 n -0000731353 00000 n -0000001254 00000 f -0000001255 00000 f -0000001256 00000 f -0000001257 00000 f -0000001258 00000 f -0000001259 00000 f -0000001260 00000 f -0000001261 00000 f -0000001262 00000 f -0000001263 00000 f -0000001264 00000 f -0000001265 00000 f -0000001266 00000 f -0000001267 00000 f -0000001268 00000 f -0000001269 00000 f -0000001270 00000 f -0000001271 00000 f -0000001272 00000 f -0000001273 00000 f -0000001274 00000 f -0000001275 00000 f -0000001276 00000 f -0000001277 00000 f -0000001278 00000 f -0000001279 00000 f -0000001280 00000 f -0000001281 00000 f -0000001282 00000 f -0000001283 00000 f -0000001284 00000 f -0000001285 00000 f -0000001286 00000 f -0000001287 00000 f -0000001288 00000 f -0000001289 00000 f -0000001290 00000 f -0000001291 00000 f -0000001292 00000 f -0000001293 00000 f -0000001294 00000 f -0000001295 00000 f -0000001296 00000 f -0000001297 00000 f -0000001298 00000 f -0000001299 00000 f -0000001300 00000 f -0000001302 00000 f -0000726743 00000 n -0000001303 00000 f -0000001304 00000 f -0000001305 00000 f -0000001306 00000 f -0000001307 00000 f -0000001308 00000 f -0000001309 00000 f -0000001310 00000 f -0000001311 00000 f -0000001312 00000 f -0000001313 00000 f -0000001314 00000 f -0000001315 00000 f -0000001316 00000 f -0000001317 00000 f -0000001318 00000 f -0000001321 00000 f -0000731200 00000 n -0000731233 00000 n -0000001322 00000 f -0000001323 00000 f -0000001324 00000 f -0000001325 00000 f -0000001326 00000 f -0000001327 00000 f -0000001328 00000 f -0000001329 00000 f -0000001330 00000 f -0000001331 00000 f -0000001332 00000 f -0000001333 00000 f -0000001334 00000 f -0000001335 00000 f -0000001336 00000 f -0000001337 00000 f -0000001338 00000 f -0000001339 00000 f -0000001340 00000 f -0000001341 00000 f -0000001342 00000 f -0000001343 00000 f -0000001344 00000 f -0000001345 00000 f -0000001346 00000 f -0000001347 00000 f -0000001348 00000 f -0000001349 00000 f -0000001350 00000 f -0000001351 00000 f -0000001352 00000 f -0000001353 00000 f -0000001354 00000 f -0000001355 00000 f -0000001356 00000 f -0000001357 00000 f -0000001358 00000 f -0000001359 00000 f -0000001360 00000 f -0000001361 00000 f -0000001362 00000 f -0000001363 00000 f -0000001364 00000 f -0000001365 00000 f -0000001366 00000 f -0000001367 00000 f -0000001368 00000 f -0000001370 00000 f -0000726822 00000 n -0000001371 00000 f -0000001372 00000 f -0000001373 00000 f -0000001374 00000 f -0000001375 00000 f -0000001376 00000 f -0000001377 00000 f -0000001378 00000 f -0000001379 00000 f -0000001380 00000 f -0000001381 00000 f -0000001382 00000 f -0000001383 00000 f -0000001384 00000 f -0000001385 00000 f -0000001386 00000 f -0000001389 00000 f -0000731080 00000 n -0000731113 00000 n -0000001390 00000 f -0000001391 00000 f -0000001392 00000 f -0000001393 00000 f -0000001394 00000 f -0000001395 00000 f -0000001396 00000 f -0000001397 00000 f -0000001398 00000 f -0000001399 00000 f -0000001400 00000 f -0000001401 00000 f -0000001402 00000 f -0000001403 00000 f -0000001404 00000 f -0000001405 00000 f -0000001406 00000 f -0000001407 00000 f -0000001408 00000 f -0000001409 00000 f -0000001410 00000 f -0000001411 00000 f -0000001412 00000 f -0000001413 00000 f -0000001414 00000 f -0000001415 00000 f -0000001416 00000 f -0000001417 00000 f -0000001418 00000 f -0000001419 00000 f -0000001420 00000 f -0000001421 00000 f -0000001422 00000 f -0000001423 00000 f -0000001424 00000 f -0000001425 00000 f -0000001426 00000 f -0000001427 00000 f -0000001428 00000 f -0000001429 00000 f -0000001430 00000 f -0000001431 00000 f -0000001432 00000 f -0000001433 00000 f -0000001434 00000 f -0000001435 00000 f -0000001436 00000 f -0000001438 00000 f -0000726901 00000 n -0000001439 00000 f -0000001440 00000 f -0000001441 00000 f -0000001442 00000 f -0000001443 00000 f -0000001444 00000 f -0000001445 00000 f -0000001446 00000 f -0000001447 00000 f -0000001448 00000 f -0000001449 00000 f -0000001450 00000 f -0000001451 00000 f -0000001452 00000 f -0000001453 00000 f -0000001454 00000 f -0000001457 00000 f -0000730960 00000 n -0000730993 00000 n -0000001458 00000 f -0000001459 00000 f -0000001460 00000 f -0000001461 00000 f -0000001462 00000 f -0000001463 00000 f -0000001464 00000 f -0000001465 00000 f -0000001466 00000 f -0000001467 00000 f -0000001468 00000 f -0000001469 00000 f -0000001470 00000 f -0000001471 00000 f -0000001472 00000 f -0000001473 00000 f -0000001474 00000 f -0000001475 00000 f -0000001476 00000 f -0000001477 00000 f -0000001478 00000 f -0000001479 00000 f -0000001480 00000 f -0000001481 00000 f -0000001482 00000 f -0000001483 00000 f -0000001484 00000 f -0000001485 00000 f -0000001486 00000 f -0000001487 00000 f -0000001488 00000 f -0000001489 00000 f -0000001490 00000 f -0000001491 00000 f -0000001492 00000 f -0000001493 00000 f -0000001494 00000 f -0000001495 00000 f -0000001496 00000 f -0000001497 00000 f -0000001498 00000 f -0000001499 00000 f -0000001500 00000 f -0000001501 00000 f -0000001502 00000 f -0000001503 00000 f -0000001504 00000 f -0000001506 00000 f -0000726980 00000 n -0000001507 00000 f -0000001508 00000 f -0000001509 00000 f -0000001510 00000 f -0000001511 00000 f -0000001512 00000 f -0000001513 00000 f -0000001514 00000 f -0000001515 00000 f -0000001516 00000 f -0000001517 00000 f -0000001518 00000 f -0000001519 00000 f -0000001520 00000 f -0000001521 00000 f -0000001522 00000 f -0000001525 00000 f -0000730840 00000 n -0000730873 00000 n -0000001526 00000 f -0000001527 00000 f -0000001528 00000 f -0000001529 00000 f -0000001530 00000 f -0000001531 00000 f -0000001532 00000 f -0000001533 00000 f -0000001534 00000 f -0000001535 00000 f -0000001536 00000 f -0000001537 00000 f -0000001538 00000 f -0000001539 00000 f -0000001540 00000 f -0000001541 00000 f -0000001542 00000 f -0000001543 00000 f -0000001544 00000 f -0000001545 00000 f -0000001546 00000 f -0000001547 00000 f -0000001548 00000 f -0000001549 00000 f -0000001550 00000 f -0000001551 00000 f -0000001552 00000 f -0000001553 00000 f -0000001554 00000 f -0000001555 00000 f -0000001556 00000 f -0000001557 00000 f -0000001558 00000 f -0000001559 00000 f -0000001560 00000 f -0000001561 00000 f -0000001562 00000 f -0000001563 00000 f -0000001564 00000 f -0000001565 00000 f -0000001566 00000 f -0000001567 00000 f -0000001568 00000 f -0000001569 00000 f -0000001570 00000 f -0000001571 00000 f -0000001572 00000 f -0000001574 00000 f -0000727059 00000 n -0000001575 00000 f -0000001576 00000 f -0000001577 00000 f -0000001578 00000 f -0000001579 00000 f -0000001580 00000 f -0000001581 00000 f -0000001582 00000 f -0000001583 00000 f -0000001584 00000 f -0000001585 00000 f -0000001586 00000 f -0000001587 00000 f -0000001588 00000 f -0000001589 00000 f -0000001590 00000 f -0000001593 00000 f -0000730720 00000 n -0000730753 00000 n -0000001594 00000 f -0000001595 00000 f -0000001596 00000 f -0000001597 00000 f -0000001598 00000 f -0000001599 00000 f -0000001600 00000 f -0000001601 00000 f -0000001602 00000 f -0000001603 00000 f -0000001604 00000 f -0000001605 00000 f -0000001606 00000 f -0000001607 00000 f -0000001608 00000 f -0000001609 00000 f -0000001610 00000 f -0000001611 00000 f -0000001612 00000 f -0000001613 00000 f -0000001614 00000 f -0000001615 00000 f -0000001616 00000 f -0000001617 00000 f -0000001618 00000 f -0000001619 00000 f -0000001620 00000 f -0000001621 00000 f -0000001622 00000 f -0000001623 00000 f -0000001624 00000 f -0000001625 00000 f -0000001626 00000 f -0000001627 00000 f -0000001628 00000 f -0000001629 00000 f -0000001630 00000 f -0000001631 00000 f -0000001632 00000 f -0000001633 00000 f -0000001634 00000 f -0000001635 00000 f -0000001636 00000 f -0000001637 00000 f -0000001638 00000 f -0000001639 00000 f -0000001640 00000 f -0000001642 00000 f -0000727138 00000 n -0000001643 00000 f -0000001644 00000 f -0000001645 00000 f -0000001646 00000 f -0000001647 00000 f -0000001648 00000 f -0000001649 00000 f -0000001650 00000 f -0000001651 00000 f -0000001652 00000 f -0000001653 00000 f -0000001654 00000 f -0000001655 00000 f -0000001656 00000 f -0000001657 00000 f -0000001658 00000 f -0000001661 00000 f -0000730600 00000 n -0000730633 00000 n -0000001662 00000 f -0000001663 00000 f -0000001664 00000 f -0000001665 00000 f -0000001666 00000 f -0000001667 00000 f -0000001668 00000 f -0000001669 00000 f -0000001670 00000 f -0000001671 00000 f -0000001672 00000 f -0000001673 00000 f -0000001674 00000 f -0000001675 00000 f -0000001676 00000 f -0000001677 00000 f -0000001678 00000 f -0000001679 00000 f -0000001680 00000 f -0000001681 00000 f -0000001682 00000 f -0000001683 00000 f -0000001684 00000 f -0000001685 00000 f -0000001686 00000 f -0000001687 00000 f -0000001688 00000 f -0000001689 00000 f -0000001690 00000 f -0000001691 00000 f -0000001692 00000 f -0000001693 00000 f -0000001694 00000 f -0000001695 00000 f -0000001696 00000 f -0000001697 00000 f -0000001698 00000 f -0000001699 00000 f -0000001700 00000 f -0000001701 00000 f -0000001702 00000 f -0000001703 00000 f -0000001704 00000 f -0000001705 00000 f -0000001706 00000 f -0000001707 00000 f -0000001708 00000 f -0000001710 00000 f -0000727217 00000 n -0000001711 00000 f -0000001712 00000 f -0000001713 00000 f -0000001714 00000 f -0000001715 00000 f -0000001716 00000 f -0000001717 00000 f -0000001718 00000 f -0000001719 00000 f -0000001720 00000 f -0000001721 00000 f -0000001722 00000 f -0000001723 00000 f -0000001724 00000 f -0000001725 00000 f -0000001726 00000 f -0000001729 00000 f -0000730480 00000 n -0000730513 00000 n -0000001730 00000 f -0000001731 00000 f -0000001732 00000 f -0000001733 00000 f -0000001734 00000 f -0000001735 00000 f -0000001736 00000 f -0000001737 00000 f -0000001738 00000 f -0000001739 00000 f -0000001740 00000 f -0000001741 00000 f -0000001742 00000 f -0000001743 00000 f -0000001744 00000 f -0000001745 00000 f -0000001746 00000 f -0000001747 00000 f -0000001748 00000 f -0000001749 00000 f -0000001750 00000 f -0000001751 00000 f -0000001752 00000 f -0000001753 00000 f -0000001754 00000 f -0000001755 00000 f -0000001756 00000 f -0000001757 00000 f -0000001758 00000 f -0000001759 00000 f -0000001760 00000 f -0000001761 00000 f -0000001762 00000 f -0000001763 00000 f -0000001764 00000 f -0000001765 00000 f -0000001766 00000 f -0000001767 00000 f -0000001768 00000 f -0000001769 00000 f -0000001770 00000 f -0000001771 00000 f -0000001772 00000 f -0000001773 00000 f -0000001774 00000 f -0000001776 00000 f -0000727296 00000 n -0000001777 00000 f -0000001778 00000 f -0000001779 00000 f -0000001780 00000 f -0000001781 00000 f -0000001782 00000 f -0000001783 00000 f -0000001784 00000 f -0000001785 00000 f -0000001786 00000 f -0000001787 00000 f -0000001788 00000 f -0000001789 00000 f -0000001790 00000 f -0000001791 00000 f -0000001792 00000 f -0000001795 00000 f -0000730360 00000 n -0000730393 00000 n -0000001796 00000 f -0000001797 00000 f -0000001798 00000 f -0000001799 00000 f -0000001800 00000 f -0000001801 00000 f -0000001802 00000 f -0000001803 00000 f -0000001804 00000 f -0000001805 00000 f -0000001806 00000 f -0000001807 00000 f -0000001808 00000 f -0000001809 00000 f -0000001810 00000 f -0000001811 00000 f -0000001812 00000 f -0000001813 00000 f -0000001814 00000 f -0000001815 00000 f -0000001816 00000 f -0000001817 00000 f -0000001818 00000 f -0000001819 00000 f -0000001820 00000 f -0000001821 00000 f -0000001822 00000 f -0000001823 00000 f -0000001824 00000 f -0000001825 00000 f -0000001826 00000 f -0000001827 00000 f -0000001828 00000 f -0000001830 00000 f -0000727375 00000 n -0000001831 00000 f -0000001832 00000 f -0000001833 00000 f -0000001834 00000 f -0000001835 00000 f -0000001836 00000 f -0000001837 00000 f -0000001838 00000 f -0000001839 00000 f -0000001840 00000 f -0000001841 00000 f -0000001842 00000 f -0000001843 00000 f -0000001844 00000 f -0000001845 00000 f -0000001846 00000 f -0000001849 00000 f -0000730240 00000 n -0000730273 00000 n -0000001850 00000 f -0000001851 00000 f -0000001852 00000 f -0000001853 00000 f -0000001854 00000 f -0000001855 00000 f -0000001856 00000 f -0000001857 00000 f -0000001858 00000 f -0000001859 00000 f -0000001860 00000 f -0000001861 00000 f -0000001862 00000 f -0000001863 00000 f -0000001864 00000 f -0000001865 00000 f -0000001866 00000 f -0000001867 00000 f -0000001868 00000 f -0000001869 00000 f -0000001870 00000 f -0000001871 00000 f -0000001872 00000 f -0000001873 00000 f -0000001874 00000 f -0000001875 00000 f -0000001876 00000 f -0000001877 00000 f -0000001878 00000 f -0000001879 00000 f -0000001880 00000 f -0000001881 00000 f -0000001882 00000 f -0000001883 00000 f -0000001885 00000 f -0000727454 00000 n -0000001886 00000 f -0000001887 00000 f -0000001888 00000 f -0000001889 00000 f -0000001890 00000 f -0000001891 00000 f -0000001892 00000 f -0000001893 00000 f -0000001894 00000 f -0000001895 00000 f -0000001896 00000 f -0000001897 00000 f -0000001898 00000 f -0000001899 00000 f -0000001900 00000 f -0000001901 00000 f -0000001904 00000 f -0000730120 00000 n -0000730153 00000 n -0000001905 00000 f -0000001906 00000 f -0000001907 00000 f -0000001908 00000 f -0000001909 00000 f -0000001910 00000 f -0000001911 00000 f -0000001912 00000 f -0000001913 00000 f -0000001914 00000 f -0000001915 00000 f -0000001916 00000 f -0000001917 00000 f -0000001918 00000 f -0000001919 00000 f -0000001920 00000 f -0000001921 00000 f -0000001922 00000 f -0000001923 00000 f -0000001924 00000 f -0000001925 00000 f -0000001926 00000 f -0000001927 00000 f -0000001928 00000 f -0000001929 00000 f -0000001930 00000 f -0000001931 00000 f -0000001932 00000 f -0000001933 00000 f -0000001934 00000 f -0000001935 00000 f -0000001936 00000 f -0000001937 00000 f -0000001938 00000 f -0000001939 00000 f -0000001940 00000 f -0000001941 00000 f -0000001943 00000 f -0000727533 00000 n -0000001944 00000 f -0000001945 00000 f -0000001946 00000 f -0000001947 00000 f -0000001948 00000 f -0000001949 00000 f -0000001950 00000 f -0000001951 00000 f -0000001952 00000 f -0000001953 00000 f -0000001954 00000 f -0000001955 00000 f -0000001956 00000 f -0000001957 00000 f -0000001958 00000 f -0000001959 00000 f -0000001962 00000 f -0000730000 00000 n -0000730033 00000 n -0000001963 00000 f -0000001964 00000 f -0000001965 00000 f -0000001966 00000 f -0000001967 00000 f -0000001968 00000 f -0000001969 00000 f -0000001970 00000 f -0000001971 00000 f -0000001972 00000 f -0000001973 00000 f -0000001974 00000 f -0000001975 00000 f -0000001976 00000 f -0000001977 00000 f -0000001978 00000 f -0000001979 00000 f -0000001980 00000 f -0000001981 00000 f -0000001982 00000 f -0000001983 00000 f -0000001984 00000 f -0000001985 00000 f -0000001986 00000 f -0000001987 00000 f -0000001988 00000 f -0000001989 00000 f -0000001990 00000 f -0000001991 00000 f -0000001992 00000 f -0000001993 00000 f -0000001994 00000 f -0000001995 00000 f -0000001996 00000 f -0000001997 00000 f -0000001998 00000 f -0000001999 00000 f -0000002001 00000 f -0000727612 00000 n -0000002002 00000 f -0000002003 00000 f -0000002004 00000 f -0000002005 00000 f -0000002006 00000 f -0000002007 00000 f -0000002008 00000 f -0000002009 00000 f -0000002010 00000 f -0000002011 00000 f -0000002012 00000 f -0000002013 00000 f -0000002014 00000 f -0000002015 00000 f -0000002016 00000 f -0000002017 00000 f -0000002020 00000 f -0000729880 00000 n -0000729913 00000 n -0000002021 00000 f -0000002022 00000 f -0000002023 00000 f -0000002024 00000 f -0000002025 00000 f -0000002026 00000 f -0000002027 00000 f -0000002028 00000 f -0000002029 00000 f -0000002030 00000 f -0000002031 00000 f -0000002032 00000 f -0000002033 00000 f -0000002034 00000 f -0000002035 00000 f -0000002036 00000 f -0000002037 00000 f -0000002038 00000 f -0000002039 00000 f -0000002040 00000 f -0000002041 00000 f -0000002042 00000 f -0000002043 00000 f -0000002044 00000 f -0000002045 00000 f -0000002046 00000 f -0000002047 00000 f -0000002048 00000 f -0000002049 00000 f -0000002050 00000 f -0000002051 00000 f -0000002052 00000 f -0000002053 00000 f -0000002054 00000 f -0000002055 00000 f -0000002056 00000 f -0000002057 00000 f -0000002059 00000 f -0000727691 00000 n -0000002060 00000 f -0000002061 00000 f -0000002062 00000 f -0000002063 00000 f -0000002064 00000 f -0000002065 00000 f -0000002066 00000 f -0000002067 00000 f -0000002068 00000 f -0000002069 00000 f -0000002070 00000 f -0000002071 00000 f -0000002072 00000 f -0000002073 00000 f -0000002074 00000 f -0000002075 00000 f -0000002078 00000 f -0000729760 00000 n -0000729793 00000 n -0000002079 00000 f -0000002080 00000 f -0000002081 00000 f -0000002082 00000 f -0000002083 00000 f -0000002084 00000 f -0000002085 00000 f -0000002086 00000 f -0000002087 00000 f -0000002088 00000 f -0000002089 00000 f -0000002090 00000 f -0000002091 00000 f -0000002092 00000 f -0000002093 00000 f -0000002094 00000 f -0000002095 00000 f -0000002096 00000 f -0000002097 00000 f -0000002098 00000 f -0000002099 00000 f -0000002100 00000 f -0000002101 00000 f -0000002102 00000 f -0000002103 00000 f -0000002104 00000 f -0000002105 00000 f -0000002106 00000 f -0000002107 00000 f -0000002108 00000 f -0000002109 00000 f -0000002110 00000 f -0000002111 00000 f -0000002112 00000 f -0000002113 00000 f -0000002114 00000 f -0000002115 00000 f -0000002117 00000 f -0000727770 00000 n -0000002118 00000 f -0000002119 00000 f -0000002120 00000 f -0000002121 00000 f -0000002122 00000 f -0000002123 00000 f -0000002124 00000 f -0000002125 00000 f -0000002126 00000 f -0000002127 00000 f -0000002128 00000 f -0000002129 00000 f -0000002130 00000 f -0000002131 00000 f -0000002132 00000 f -0000002133 00000 f -0000002136 00000 f -0000729640 00000 n -0000729673 00000 n -0000002137 00000 f -0000002138 00000 f -0000002139 00000 f -0000002140 00000 f -0000002141 00000 f -0000002142 00000 f -0000002143 00000 f -0000002144 00000 f -0000002145 00000 f -0000002146 00000 f -0000002147 00000 f -0000002148 00000 f -0000002149 00000 f -0000002150 00000 f -0000002151 00000 f -0000002152 00000 f -0000002153 00000 f -0000002154 00000 f -0000002155 00000 f -0000002156 00000 f -0000002157 00000 f -0000002158 00000 f -0000002159 00000 f -0000002160 00000 f -0000002161 00000 f -0000002162 00000 f -0000002163 00000 f -0000002164 00000 f -0000002165 00000 f -0000002166 00000 f -0000002167 00000 f -0000002168 00000 f -0000002169 00000 f -0000002170 00000 f -0000002171 00000 f -0000002172 00000 f -0000002173 00000 f -0000002174 00000 f -0000002176 00000 f -0000727849 00000 n -0000002177 00000 f -0000002178 00000 f -0000002179 00000 f -0000002180 00000 f -0000002181 00000 f -0000002182 00000 f -0000002183 00000 f -0000002184 00000 f -0000002185 00000 f -0000002186 00000 f -0000002187 00000 f -0000002188 00000 f -0000002189 00000 f -0000002190 00000 f -0000002191 00000 f -0000002192 00000 f -0000002195 00000 f -0000729520 00000 n -0000729553 00000 n -0000002196 00000 f -0000002197 00000 f -0000002198 00000 f -0000002199 00000 f -0000002200 00000 f -0000002201 00000 f -0000002202 00000 f -0000002203 00000 f -0000002204 00000 f -0000002205 00000 f -0000002206 00000 f -0000002207 00000 f -0000002208 00000 f -0000002209 00000 f -0000002210 00000 f -0000002211 00000 f -0000002212 00000 f -0000002213 00000 f -0000002214 00000 f -0000002215 00000 f -0000002216 00000 f -0000002217 00000 f -0000002218 00000 f -0000002219 00000 f -0000002220 00000 f -0000002221 00000 f -0000002222 00000 f -0000002223 00000 f -0000002224 00000 f -0000002225 00000 f -0000002226 00000 f -0000002227 00000 f -0000002228 00000 f -0000002229 00000 f -0000002230 00000 f -0000002231 00000 f -0000002232 00000 f -0000002233 00000 f -0000002234 00000 f -0000002235 00000 f -0000002236 00000 f -0000002237 00000 f -0000002238 00000 f -0000002239 00000 f -0000002240 00000 f -0000002241 00000 f -0000002242 00000 f -0000002243 00000 f -0000002245 00000 f -0000727928 00000 n -0000002246 00000 f -0000002247 00000 f -0000002248 00000 f -0000002249 00000 f -0000002250 00000 f -0000002251 00000 f -0000002252 00000 f -0000002253 00000 f -0000002254 00000 f -0000002255 00000 f -0000002256 00000 f -0000002257 00000 f -0000002258 00000 f -0000002259 00000 f -0000002260 00000 f -0000002261 00000 f -0000002264 00000 f -0000729400 00000 n -0000729433 00000 n -0000002265 00000 f -0000002266 00000 f -0000002267 00000 f -0000002268 00000 f -0000002269 00000 f -0000002270 00000 f -0000002271 00000 f -0000002272 00000 f -0000002273 00000 f -0000002274 00000 f -0000002275 00000 f -0000002276 00000 f -0000002277 00000 f -0000002278 00000 f -0000002279 00000 f -0000002280 00000 f -0000002281 00000 f -0000002282 00000 f -0000002283 00000 f -0000002284 00000 f -0000002285 00000 f -0000002286 00000 f -0000002287 00000 f -0000002288 00000 f -0000002289 00000 f -0000002290 00000 f -0000002291 00000 f -0000002292 00000 f -0000002293 00000 f -0000002294 00000 f -0000002295 00000 f -0000002296 00000 f -0000002297 00000 f -0000002298 00000 f -0000002299 00000 f -0000002300 00000 f -0000002301 00000 f -0000002302 00000 f -0000002303 00000 f -0000002304 00000 f -0000002305 00000 f -0000002306 00000 f -0000002307 00000 f -0000002308 00000 f -0000002309 00000 f -0000002310 00000 f -0000002311 00000 f -0000002312 00000 f -0000002314 00000 f -0000728007 00000 n -0000002315 00000 f -0000002316 00000 f -0000002317 00000 f -0000002318 00000 f -0000002319 00000 f -0000002320 00000 f -0000002321 00000 f -0000002322 00000 f -0000002323 00000 f -0000002324 00000 f -0000002325 00000 f -0000002326 00000 f -0000002327 00000 f -0000002328 00000 f -0000002329 00000 f -0000002330 00000 f -0000002333 00000 f -0000729280 00000 n -0000729313 00000 n -0000002334 00000 f -0000002335 00000 f -0000002336 00000 f -0000002337 00000 f -0000002338 00000 f -0000002339 00000 f -0000002340 00000 f -0000002341 00000 f -0000002342 00000 f -0000002343 00000 f -0000002344 00000 f -0000002345 00000 f -0000002346 00000 f -0000002347 00000 f -0000002348 00000 f -0000002349 00000 f -0000002350 00000 f -0000002351 00000 f -0000002352 00000 f -0000002353 00000 f -0000002354 00000 f -0000002355 00000 f -0000002356 00000 f -0000002357 00000 f -0000002358 00000 f -0000002359 00000 f -0000002360 00000 f -0000002361 00000 f -0000002362 00000 f -0000002363 00000 f -0000002364 00000 f -0000002365 00000 f -0000002366 00000 f -0000002367 00000 f -0000002368 00000 f -0000002369 00000 f -0000002370 00000 f -0000002371 00000 f -0000002372 00000 f -0000002373 00000 f -0000002374 00000 f -0000002375 00000 f -0000002376 00000 f -0000002377 00000 f -0000002378 00000 f -0000002379 00000 f -0000002380 00000 f -0000002381 00000 f -0000002383 00000 f -0000728086 00000 n -0000002384 00000 f -0000002385 00000 f -0000002386 00000 f -0000002387 00000 f -0000002388 00000 f -0000002389 00000 f -0000002390 00000 f -0000002391 00000 f -0000002392 00000 f -0000002393 00000 f -0000002394 00000 f -0000002395 00000 f -0000002396 00000 f -0000002397 00000 f -0000002398 00000 f -0000002399 00000 f -0000002400 00000 f -0000002403 00000 f -0000729160 00000 n -0000729193 00000 n -0000002404 00000 f -0000002405 00000 f -0000002406 00000 f -0000002407 00000 f -0000002408 00000 f -0000002409 00000 f -0000002410 00000 f -0000002411 00000 f -0000002412 00000 f -0000002413 00000 f -0000002414 00000 f -0000002415 00000 f -0000002416 00000 f -0000002417 00000 f -0000002418 00000 f -0000002419 00000 f -0000002420 00000 f -0000002421 00000 f -0000002422 00000 f -0000002423 00000 f -0000002424 00000 f -0000002425 00000 f -0000002426 00000 f -0000002427 00000 f -0000002428 00000 f -0000002429 00000 f -0000002430 00000 f -0000002431 00000 f -0000002432 00000 f -0000002433 00000 f -0000002434 00000 f -0000002435 00000 f -0000002436 00000 f -0000002437 00000 f -0000002438 00000 f -0000002439 00000 f -0000002440 00000 f -0000002441 00000 f -0000002442 00000 f -0000002443 00000 f -0000002444 00000 f -0000002445 00000 f -0000002446 00000 f -0000002447 00000 f -0000002448 00000 f -0000002449 00000 f -0000002450 00000 f -0000002451 00000 f -0000002453 00000 f -0000728165 00000 n -0000002454 00000 f -0000002455 00000 f -0000002456 00000 f -0000002457 00000 f -0000002458 00000 f -0000002459 00000 f -0000002460 00000 f -0000002461 00000 f -0000002462 00000 f -0000002463 00000 f -0000002464 00000 f -0000002465 00000 f -0000002466 00000 f -0000002467 00000 f -0000002468 00000 f -0000002469 00000 f -0000002470 00000 f -0000002473 00000 f -0000729040 00000 n -0000729073 00000 n -0000002474 00000 f -0000002475 00000 f -0000002476 00000 f -0000002477 00000 f -0000002478 00000 f -0000002479 00000 f -0000002480 00000 f -0000002481 00000 f -0000002482 00000 f -0000002483 00000 f -0000002484 00000 f -0000002485 00000 f -0000002486 00000 f -0000002487 00000 f -0000002488 00000 f -0000002489 00000 f -0000002490 00000 f -0000002491 00000 f -0000002492 00000 f -0000002493 00000 f -0000002494 00000 f -0000002495 00000 f -0000002496 00000 f -0000002497 00000 f -0000002498 00000 f -0000002499 00000 f -0000002500 00000 f -0000002501 00000 f -0000002502 00000 f -0000002503 00000 f -0000002504 00000 f -0000002505 00000 f -0000002506 00000 f -0000002507 00000 f -0000002508 00000 f -0000002509 00000 f -0000002510 00000 f -0000002511 00000 f -0000002512 00000 f -0000002513 00000 f -0000002514 00000 f -0000002515 00000 f -0000002516 00000 f -0000002517 00000 f -0000002518 00000 f -0000002519 00000 f -0000002520 00000 f -0000002521 00000 f -0000002523 00000 f -0000728244 00000 n -0000002524 00000 f -0000002525 00000 f -0000002526 00000 f -0000002527 00000 f -0000002528 00000 f -0000002529 00000 f -0000002530 00000 f -0000002531 00000 f -0000002532 00000 f -0000002533 00000 f -0000002534 00000 f -0000002535 00000 f -0000002536 00000 f -0000002537 00000 f -0000002538 00000 f -0000002539 00000 f -0000002540 00000 f -0000002543 00000 f -0000728920 00000 n -0000728953 00000 n -0000002544 00000 f -0000002545 00000 f -0000002546 00000 f -0000002547 00000 f -0000002548 00000 f -0000002549 00000 f -0000002550 00000 f -0000002551 00000 f -0000002552 00000 f -0000002553 00000 f -0000002554 00000 f -0000002555 00000 f -0000002556 00000 f -0000002557 00000 f -0000002558 00000 f -0000002559 00000 f -0000002560 00000 f -0000002561 00000 f -0000002562 00000 f -0000002563 00000 f -0000002564 00000 f -0000002565 00000 f -0000002566 00000 f -0000002567 00000 f -0000002568 00000 f -0000002569 00000 f -0000002570 00000 f -0000002571 00000 f -0000002572 00000 f -0000002573 00000 f -0000002574 00000 f -0000002575 00000 f -0000002576 00000 f -0000002577 00000 f -0000002578 00000 f -0000002579 00000 f -0000002580 00000 f -0000002581 00000 f -0000002582 00000 f -0000002583 00000 f -0000002584 00000 f -0000002585 00000 f -0000002586 00000 f -0000002587 00000 f -0000002588 00000 f -0000002589 00000 f -0000002590 00000 f -0000002591 00000 f -0000002593 00000 f -0000728323 00000 n -0000002594 00000 f -0000002595 00000 f -0000002596 00000 f -0000002597 00000 f -0000002598 00000 f -0000002599 00000 f -0000002600 00000 f -0000002601 00000 f -0000002602 00000 f -0000002603 00000 f -0000002604 00000 f -0000002605 00000 f -0000002606 00000 f -0000002607 00000 f -0000002608 00000 f -0000002609 00000 f -0000002610 00000 f -0000002613 00000 f -0000728800 00000 n -0000728833 00000 n -0000002614 00000 f -0000002615 00000 f -0000002616 00000 f -0000002617 00000 f -0000002618 00000 f -0000002619 00000 f -0000002620 00000 f -0000002621 00000 f -0000002622 00000 f -0000002623 00000 f -0000002624 00000 f -0000002625 00000 f -0000002626 00000 f -0000002627 00000 f -0000002628 00000 f -0000002629 00000 f -0000002630 00000 f -0000002631 00000 f -0000002632 00000 f -0000002633 00000 f -0000002634 00000 f -0000002635 00000 f -0000002636 00000 f -0000002637 00000 f -0000002638 00000 f -0000002639 00000 f -0000002640 00000 f -0000002641 00000 f -0000002642 00000 f -0000002643 00000 f -0000002644 00000 f -0000002645 00000 f -0000002646 00000 f -0000002647 00000 f -0000002648 00000 f -0000002649 00000 f -0000002650 00000 f -0000002651 00000 f -0000002652 00000 f -0000002653 00000 f -0000002654 00000 f -0000002655 00000 f -0000002656 00000 f -0000002657 00000 f -0000002658 00000 f -0000002659 00000 f -0000002660 00000 f -0000002661 00000 f -0000002663 00000 f -0000728402 00000 n -0000002664 00000 f -0000002665 00000 f -0000002666 00000 f -0000002667 00000 f -0000002668 00000 f -0000002669 00000 f -0000002670 00000 f -0000002671 00000 f -0000002672 00000 f -0000002673 00000 f -0000002674 00000 f -0000002675 00000 f -0000002676 00000 f -0000002677 00000 f -0000002678 00000 f -0000002679 00000 f -0000002680 00000 f -0000002683 00000 f -0000728680 00000 n -0000728713 00000 n -0000002684 00000 f -0000002685 00000 f -0000002686 00000 f -0000002687 00000 f -0000002688 00000 f -0000002689 00000 f -0000002690 00000 f -0000002691 00000 f -0000002692 00000 f -0000002693 00000 f -0000002694 00000 f -0000002695 00000 f -0000002696 00000 f -0000002697 00000 f -0000002698 00000 f -0000002699 00000 f -0000002700 00000 f -0000002701 00000 f -0000002702 00000 f -0000002703 00000 f -0000002704 00000 f -0000002705 00000 f -0000002706 00000 f -0000002707 00000 f -0000002708 00000 f -0000002709 00000 f -0000002710 00000 f -0000002711 00000 f -0000002712 00000 f -0000002713 00000 f -0000002714 00000 f -0000002715 00000 f -0000002716 00000 f -0000002717 00000 f -0000002718 00000 f -0000002719 00000 f -0000002720 00000 f -0000002721 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000728481 00000 n -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000728560 00000 n -0000728593 00000 n -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000000000 00000 f -0000245324 00000 n -0000245720 00000 n -0000245889 00000 n -0000246965 00000 n -0000246532 00000 n -0000247324 00000 n -0000247812 00000 n -0000248407 00000 n -0000245034 00000 n -0000245171 00000 n -0000244835 00000 n -0000733332 00000 n -0000032799 00000 n -0000240709 00000 n -0000395329 00000 n -0000244590 00000 n -0000395079 00000 n -0000395204 00000 n -0000246358 00000 n -0000248238 00000 n -0000243100 00000 n -0000243580 00000 n -0000244057 00000 n -0000240776 00000 n -0000242533 00000 n -0000242585 00000 n -0000244770 00000 n -0000244705 00000 n -0000244525 00000 n -0000244914 00000 n -0000244947 00000 n -0000381256 00000 n -0000381285 00000 n -0000380476 00000 n -0000380566 00000 n -0000372898 00000 n -0000350532 00000 n -0000340631 00000 n -0000335611 00000 n -0000327180 00000 n -0000321513 00000 n -0000292043 00000 n -0000283886 00000 n -0000279042 00000 n -0000248838 00000 n -0000249095 00000 n -0000279312 00000 n -0000284170 00000 n -0000292293 00000 n -0000321795 00000 n -0000327461 00000 n -0000335884 00000 n -0000340908 00000 n -0000350796 00000 n -0000373169 00000 n -0000380840 00000 n -0000381723 00000 n -0000382045 00000 n -0000382116 00000 n -0000382388 00000 n -0000382485 00000 n -0000395407 00000 n -0000395685 00000 n -0000396687 00000 n -0000406306 00000 n -0000471896 00000 n -0000537486 00000 n -0000603076 00000 n -0000668666 00000 n -0000733361 00000 n -trailer <]>> startxref 733561 %%EOF \ No newline at end of file diff --git a/docs/articles/cheatsheet/eurostat_cheatsheet.pdf b/docs/articles/cheatsheet/eurostat_cheatsheet.pdf deleted file mode 100755 index 33cee586..00000000 Binary files a/docs/articles/cheatsheet/eurostat_cheatsheet.pdf and /dev/null differ diff --git a/docs/articles/cheatsheet/map.pdf b/docs/articles/cheatsheet/map.pdf deleted file mode 100755 index 1ee97a68..00000000 Binary files a/docs/articles/cheatsheet/map.pdf and /dev/null differ diff --git a/docs/articles/cheatsheet/road.pdf b/docs/articles/cheatsheet/road.pdf deleted file mode 100755 index cf1b441c..00000000 Binary files a/docs/articles/cheatsheet/road.pdf and /dev/null differ diff --git a/docs/articles/cheatsheet/road2.pdf b/docs/articles/cheatsheet/road2.pdf deleted file mode 100755 index e557f62b..00000000 Binary files a/docs/articles/cheatsheet/road2.pdf and /dev/null differ diff --git a/docs/articles/eurostat_tutorial.html b/docs/articles/eurostat_tutorial.html deleted file mode 100755 index a323e2b1..00000000 --- a/docs/articles/eurostat_tutorial.html +++ /dev/null @@ -1,1368 +0,0 @@ - - - - - - - -Tutorial (vignette) for the eurostat R package • eurostat - - - - - - - - - -