Bolivia CPV 2024: Population QuickStatements for Wikidata

NoteAI-generated text, click for process details

This page was first generated using the Posit AI plug-in running Claude Sonnet 4.6, operating in my repository wiki-graph, which already contained the functions referenced here. The prompt I used was:

For each of the following tasks, build functions and embed the process in a qmd that explains the needed steps.

Before we can deploy the quickstatements below, we need to clear out the small number of P1082 values. They only appear in these ID’s: “Q628665” “Q1516972” “Q1814603” “Q1814613” “Q1814898” “Q1814929” “Q1952982”

We’re going to build a new table building off of pop_muni, with qid values added, using muni_id_lookup_table to connect them through id_muni.

Each row will drive a series of columns with quickstatements produced by add_quick_statement_column, one for each of the three total population columns. These quickstatements will add a value for P1082 (population) for the corresponding year of the census. All will be sourced to Q139668018.

The page reflects extensive manual and automated revisions to the code following a debugging process. Several sections below were added by hand.

Overview

This document adds P1082 (population) statements to Wikidata items for Bolivia’s 339 municipalities and for Bolivia’s 9 departments and 112 provinces using census counts from three surveys: 2001, 2012, and 2024 (CPV 2024).

Each statement is sourced to Q139668018 (the Wikidata item for the CPV 2024 publication) and carries a P585 (point in time) qualifier for the relevant census year.

Before adding new statements, a small number of pre-existing P1082 claims on seven municipality items must be removed. Those items were tagged during a prior data-cleaning pass; their existing values are undated or unreferenced and would otherwise create duplicates.

Setup

library(tidyverse)
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.2.0     ✔ readr     2.1.5
✔ forcats   1.0.1     ✔ stringr   1.6.0
✔ ggplot2   4.0.2     ✔ tibble    3.3.1
✔ lubridate 1.9.5     ✔ tidyr     1.3.2
✔ purrr     1.2.1     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(readr)
library(httr)
library(jsonlite)

Attaching package: 'jsonlite'

The following object is masked from 'package:purrr':

    flatten
source("create_quick_statement.R")
source("get_wikidata_instances.R")
muni_id_lookup_table <- readRDS("../ultimate-consequences/data/muni_id_lookup_table.rds")
pop_muni             <- readRDS("data/cpv2024/poblacion_municipio.rds")
pop_prov             <- readRDS("data/cpv2024/poblacion_provincia.rds")
pop_dept             <- readRDS("data/cpv2024/poblacion_departamento.rds")
# CPV 2024 publication item used as "stated in" (P248)
SOURCE_QID <- "Q139668018"

p585_for_year <- function(year) sprintf("+%d-01-01T00:00:00Z/9", year)

# Wikidata instance-of classes
BOLIVIA_QID            <- "Q750"
DEPARTMENT_CLASS_QID   <- "Q250050"  # department of Bolivia
PROVINCE_CLASS_QID     <- "Q1062593" # province of Bolivia
MUNICIPALITY_CLASS_QID <- "Q1062710" # municipality of Bolivia

Step 1: Fetch current Wikidata municipality data

A single get_wikidata_instances() call retrieves every Bolivian municipality item, collecting both the INE code (P14142) used for QID mapping and any existing P1082 (population) claims needed to generate the removal statements in the next step.

municipalities_wd <- get_wikidata_instances(
  MUNICIPALITY_CLASS_QID,
  property                    = "P14142",
  property_names              = "ine_code",
  numeric_list_properties     = "P1082",
  numeric_list_property_names = "population",
  country                     = BOLIVIA_QID
)
Found 340 instances. Retrieving details in batches of 50...
  Batch 1/7 (50 items)...
  Batch 2/7 (50 items)...
  Batch 3/7 (50 items)...
  Batch 4/7 (50 items)...
  Batch 5/7 (50 items)...
  Batch 6/7 (50 items)...
  Batch 7/7 (40 items)...
Successfully retrieved 340 items
cat("Municipality items retrieved:", nrow(municipalities_wd), "\n")
Municipality items retrieved: 340 
cat("Items with INE code:         ", sum(!is.na(municipalities_wd$ine_code)), "\n")
Items with INE code:          339 
cat("Items with P1082:            ", sum(municipalities_wd$population_n > 0, na.rm = TRUE), "\n")
Items with P1082:             339 

Step 2: Remove pre-existing P1082 claims (municipalities only)

Seven items carry one or more P1082 statements that were added before this structured import. They must be deleted first, or QuickStatements will create duplicate claims.

make_p1082_removals() extracts the current claim values from the already-fetched municipalities_wd tibble (no second API call needed) and emits one removal line per claim in QuickStatements batch syntax (-QID | P1082 | value).

#' Generate QuickStatements removal lines for all P1082 claims on a set of items.
#'
#' @param municipalities_wd Tibble returned by get_wikidata_instances(), which must
#'   include population_n, population_1 … population_N columns (numeric list
#'   property columns produced when numeric_list_properties = "P1082").
#' @param target_qids Character vector of QIDs whose P1082 claims should be removed.
#'
#' @return A tibble with columns `qid`, `label_es`, `claim_slot`, `value`, and
#'   `removal_statement` (the QuickStatements deletion line).
make_p1082_removals <- function(municipalities_wd, target_qids) {
  df <- municipalities_wd |>
    filter(qid %in% target_qids)

  if (nrow(df) == 0) stop("None of target_qids found in municipalities_wd.")

  # Identify the per-claim value columns: population_1, population_2, ...
  # (exclude population, population_n, population_*_year, population_*_ref)
  value_cols <- names(df) |>
    str_subset("^population_\\d+$")

  df |>
    select(qid, label_es, all_of(value_cols)) |>
    pivot_longer(
      cols      = all_of(value_cols),
      names_to  = "claim_slot",
      values_to = "value"
    ) |>
    filter(!is.na(value)) |>
    mutate(
      value_str         = as.character(as.integer(value)),
      removal_statement = str_c("-", qid, " | P1082 | ", value_str)
    ) |>
    select(qid, label_es, claim_slot, value, removal_statement)
}
qids_to_clear <- c(
  "Q628665",  # Porco
  "Q1516972", # Pojo
  "Q1814603", # Loreto
  "Q1814613", # Exaltación
  "Q1814898", # San Buenaventura
  "Q1814929", # Corocoro
  "Q1952982"  # (label missing in WD)
)

removals <- make_p1082_removals(municipalities_wd, qids_to_clear)
removals
# A tibble: 23 × 5
   qid      label_es         claim_slot   value removal_statement       
   <chr>    <chr>            <chr>        <dbl> <chr>                   
 1 Q1814603 Loreto           population_1  3859 -Q1814603 | P1082 | 3859
 2 Q1814603 Loreto           population_2  3828 -Q1814603 | P1082 | 3828
 3 Q1814603 Loreto           population_3  4269 -Q1814603 | P1082 | 4269
 4 Q1814613 Exaltación       population_1  6618 -Q1814613 | P1082 | 6618
 5 Q1814613 Exaltación       population_2  6362 -Q1814613 | P1082 | 6362
 6 Q1814613 Exaltación       population_3  8012 -Q1814613 | P1082 | 8012
 7 Q1814898 San Buenaventura population_1  7166 -Q1814898 | P1082 | 7166
 8 Q1814898 San Buenaventura population_2  4608 -Q1814898 | P1082 | 4608
 9 Q1814898 San Buenaventura population_3  6203 -Q1814898 | P1082 | 6203
10 Q1814898 San Buenaventura population_4  8711 -Q1814898 | P1082 | 8711
# ℹ 13 more rows

Copy the lines below into QuickStatements batch mode and run them before proceeding to Step 4.

writeLines(removals$removal_statement)
-Q1814603 | P1082 | 3859
-Q1814603 | P1082 | 3828
-Q1814603 | P1082 | 4269
-Q1814613 | P1082 | 6618
-Q1814613 | P1082 | 6362
-Q1814613 | P1082 | 8012
-Q1814898 | P1082 | 7166
-Q1814898 | P1082 | 4608
-Q1814898 | P1082 | 6203
-Q1814898 | P1082 | 8711
-Q1814898 | P1082 | 10105
-Q1814929 | P1082 | 11813
-Q1814929 | P1082 | 10647
-Q1814929 | P1082 | 13551
-Q1952982 | P1082 | 8290
-Q1952982 | P1082 | 7948
-Q1952982 | P1082 | 8679
-Q1516972 | P1082 | 11515
-Q1516972 | P1082 | 10156
-Q1516972 | P1082 | 11865
-Q628665 | P1082 | 5959
-Q628665 | P1082 | 10866
-Q628665 | P1082 | 14654

Step 3: Build municipality–QID population table

The join chain:

  1. pop_muni → muni_id_lookup_table on municipio == muni_cpv2024 and departamento == department. The department key is required because many municipality names (e.g. “San Pedro”, “Santa Rosa”) are shared across departments; omitting it inflates the row count from 340 to 369.
  2. muni_id_lookup_table → Wikidata on id_muni == ine_code using the municipalities_wd tibble already in hand.

TIOC rows in pop_muni (e.g. “TIOC-Raqaypampa”, “TIOC-Territorio Indígena Multiétnico”) have no matching muni_cpv2024 in the lookup table and will produce NA after the join; they are dropped and reported to the console.

#' Join pop_muni to Wikidata QIDs through muni_id_lookup_table.
#'
#' @param pop_muni    Tibble of municipality-level population rows from CPV 2024.
#' @param lookup      muni_id_lookup_table with columns id_muni, muni_cpv2024,
#'   and department.
#' @param ine_qid_map Tibble with columns id_muni (INE 6-digit code) and qid.
#'   Must have NA rows filtered out before calling (to avoid spurious TIOC matches).
#'
#' @return A tibble of matched rows, one per municipality, with all pop_muni
#'   columns plus id_muni and qid. Unmatched rows are dropped and messaged.
build_population_qs_table <- function(pop_muni, lookup, ine_qid_map) {
  ine_qid_map <- ine_qid_map |> filter(!is.na(id_muni))

  joined <- pop_muni |>
    left_join(
      lookup |> select(id_muni, muni_cpv2024, department),
      by = c("municipio" = "muni_cpv2024", "departamento" = "department")
    ) |>
    left_join(ine_qid_map, by = "id_muni")

  unmatched <- joined |> filter(is.na(qid))
  if (nrow(unmatched) > 0) {
    message(nrow(unmatched), " pop_muni row(s) had no QID match and will be dropped:")
    walk(unmatched$municipio, ~ message("  - ", .x))
  }

  joined |> filter(!is.na(qid))
}
ine_qid_map <- municipalities_wd |>
  select(qid, id_muni = ine_code)

pop_qs <- build_population_qs_table(pop_muni, muni_id_lookup_table, ine_qid_map)
4 pop_muni row(s) had no QID match and will be dropped:
  - TIOC-Raqaypampa
  - TIOC-Jatun Ayllu Yura
  - Villazón
  - TIOC-Territorio Indígena Multiétnico
cat("Rows in pop_qs:", nrow(pop_qs), "\n")
Rows in pop_qs: 339 
cat("Distinct QIDs: ", n_distinct(pop_qs$qid), "\n")
Distinct QIDs:  339 
pop_qs |>
  select(departamento, municipio, id_muni, qid,
         pob_2001_total, pob_2012_total, pob_2024_total) |>
  head(10)
# A tibble: 10 × 7
   departamento municipio id_muni qid      pob_2001_total pob_2012_total
   <chr>        <chr>     <chr>   <chr>             <dbl>          <dbl>
 1 Chuquisaca   Sucre     010101  Q1304750         214913         261622
 2 Chuquisaca   Yotala    010102  Q1142025           9497           9461
 3 Chuquisaca   Poroma    010103  Q182203           16966          16532
 4 Chuquisaca   Azurduy   010201  Q1585034          11349          10652
 5 Chuquisaca   Tarvita   010202  Q1142233          16230          14261
 6 Chuquisaca   Zudáñez   010301  Q1142243           7423          11362
 7 Chuquisaca   Presto    010302  Q1585103           8892          12385
 8 Chuquisaca   Mojocoya  010303  Q1142257           7926           8068
 9 Chuquisaca   Icla      010304  Q1142203           8177           7774
10 Chuquisaca   Padilla   010401  Q1142006          12453          10383
# ℹ 1 more variable: pob_2024_total <dbl>

Step 4: Fetch Wikidata departments and provinces (with INE codes)

Unlike municipalities, we can map provinces and departments directly via the INE code (P14142), which is now present on Wikidata for these items.

  • Departments: 2-digit INE code, matching cod.dep from the INE community classification file.
  • Provinces: 4-digit INE code (DEP + PRO), matching cod.prov.
# departments_wd <- get_wikidata_instances(
#   DEPARTMENT_CLASS_QID,
#   property       = "P14142",
#   property_names = "ine_code",
#   country        = BOLIVIA_QID,
#   numeric_list_properties      = "P1082",
#   numeric_list_property_names  = "population"
# )

departments_wd <- readRDS("data/wikiadata-bo-departments.RDS")

department_ine_lookup <- departments_wd |> 
                           filter(!is.na(ine_code)) |> 
                           mutate(department=str_replace(label_en, " Department", ""),
                                  dep_qid = qid) |>
                           select(ine_code, department, dep_qid) |> 
                           arrange(ine_code)



# provinces_wd <- get_wikidata_instances(
#   PROVINCE_CLASS_QID,
#   property = c("P131", "P17", "P14142"),
#   property_names = c("located_in", "country", "ine_code"),
#   numeric_list_properties      = "P1082",
#   numeric_list_property_names  = "population"
# )
# 
# provinces_wd <- provinces_wd |> 
#   mutate(dep_ine = str_sub(ine_code, 1, 2)) |>
#   left_join(department_ine_lookup, by=join_by(dep_ine == ine_code))

provinces_wd <- readRDS("data/wikiadata-bo-provinces.RDS")

cat("Department items retrieved:", nrow(departments_wd), "\n")
Department items retrieved: 9 
cat("Departments with INE code: ", sum(!is.na(departments_wd$ine_code)), "\n")
Departments with INE code:  9 
cat("Province items retrieved:  ", nrow(provinces_wd), "\n")
Province items retrieved:   112 
cat("Provinces with INE code:   ", sum(!is.na(provinces_wd$ine_code)), "\n")
Provinces with INE code:    112 

Wikidata already has some values for population. Let’s examine them. All nine departments have two values for population. Most provinces have no population data.

departments_wd <- departments_wd |> filter(!is.na(ine_code)) # filter out Litoral
     # One Bolivian department has not been controlled by Bolivia since the 19th century
     # It has no INE code.

departments_wd |> count(population_n) 
# A tibble: 1 × 2
  population_n     n
         <int> <int>
1            2     9
provinces_wd |> count(population_n)
# A tibble: 3 × 2
  population_n     n
         <int> <int>
1            0   107
2            1     4
3            2     1
departments_wd |> 
  select(qid, label_en, ine_code, population_1, population_1_year, population_1_ref,
         population_2, population_2_year, population_2_ref)
# A tibble: 9 × 9
  qid      label_en     ine_code population_1 population_1_year population_1_ref
  <chr>    <chr>        <chr>           <dbl>             <int> <chr>           
1 Q233169  Beni Depart… 08             477441              2024 https://censo.i…
2 Q233917  Cochabamba … 03            2005373              2024 https://censo.i…
3 Q233933  Tarija Depa… 06             534348              2024 https://censo.i…
4 Q235106  Santa Cruz … 07            3115386              2024 https://censo.i…
5 Q235110  Chuquisaca … 01             600132              2024 https://censo.i…
6 Q235362  Pando Depar… 09             130761              2024 https://censo.i…
7 Q238079  Potosí Depa… 05             856419              2024 https://censo.i…
8 Q272784  La Paz Depa… 02            3022566              2024 https://censo.i…
9 Q1061368 Oruro Depar… 04             570194              2024 https://censo.i…
# ℹ 3 more variables: population_2 <dbl>, population_2_year <int>,
#   population_2_ref <chr>
provinces_wd |> filter(population_n > 0) |> 
  select(qid, label_en, ine_code, population_1, population_1_year, 
                                  population_2, population_2_year)
# A tibble: 5 × 7
  qid      label_en         ine_code population_1 population_1_year population_2
  <chr>    <chr>            <chr>           <dbl>             <int>        <dbl>
1 Q389311  Nor Yungas Prov… 0214            36983                NA           NA
2 Q638697  Belisario Boeto… 0108            12277                NA        11161
3 Q1355903 Franz Tamayo Pr… 0207            26997                NA           NA
4 Q1366004 Capinota Provin… 0307            26725                NA           NA
5 Q1420274 Poopó Province   0406            14984                NA           NA
# ℹ 1 more variable: population_2_year <int>
province_pop_qids <- provinces_wd |> filter(population_n > 0) |> pull(qid)

Looking at the results we see our task: We will have to double-check departmental population values against our new sources and add infromation for 2001. We can clear the five undated data points for province populations.

qids_to_clear <- province_pop_qids
removals_prov <- make_p1082_removals(provinces_wd, qids_to_clear)

Copy the lines below into QuickStatements batch mode and run them before proceeding to Step 4.

writeLines(removals_prov$removal_statement)
-Q389311 | P1082 | 36983
-Q638697 | P1082 | 12277
-Q638697 | P1082 | 11161
-Q1355903 | P1082 | 26997
-Q1366004 | P1082 | 26725
-Q1420274 | P1082 | 14984

Step 5: Build province/department population tables via INE codes

The CPV 2024 population extracts already include department/province names. We add INE codes as follows:

  • Departments: take the first two digits of row_num-independent codes by grouping on departamento and joining to Wikidata via department INE code. (In practice pop_dept already has one row per department.)

  • Provinces: take the first four digits of the 6-digit municipality code. Because pop_prov does not contain a province code, we compute it from the department/province order using the INE code on Wikidata: we join on (departamento, provincia) after extracting a clean province label from WD.

Note: Wikidata province labels are not perfectly standardized (e.g. multiple “Cercado” provinces). We therefore match primarily by INE code (P14142). Where that is missing, we fall back to a conservative name+department join and report unmatched rows.

# pop_dept has one row per department; create dept INE code = 2 digits.
# We derive it from the province/municipality-style codes when available, but
# for CPV 2024 tables we only need the mapping through Wikidata.
# Here we join by department Spanish label as a fallback if needed.

# Prefer matching by INE code if pop_dept already has it (it currently doesn't),
# otherwise match by department name against WD Spanish label without prefix.

wd_dept_name <- departments_wd |>
  transmute(
    qid,
    ine_code,
    dept_name = label_es |>
      str_remove("^Departamento de(l )?\\s*") |>
      str_replace("Potosí", "Potosi")
  )

# pop_dept_qs <- pop_dept |>
#   left_join(wd_dept_name, join_by(id_dep==ine_code)) |> 
#   relocate(id_dep, departamento, qid)

pop_dept_qs <- pop_dept |>
  left_join(departments_wd, join_by(id_dep==ine_code)) |> 
  relocate(id_dep, departamento, qid)

unmatched <- pop_dept_qs |> filter(is.na(qid))
if (nrow(unmatched) > 0) {
  message(nrow(unmatched), " department row(s) had no QID match:")
  walk(unmatched$departamento, ~ message("  - ", .x))
}

pop_dept_qs <- pop_dept_qs |> filter(!is.na(qid))
# Province mapping strategy:
# 1) If Wikidata has INE code (P14142) for a province item, use it.
# 2) Compute province code by joining pop_prov to a lookup built from WD labels.

wd_prov_lookup <- provinces_wd |>
  transmute(
    qid,
    ine_code,
    department = label_es |>
      str_extract("\\(([^)]+)\\)$") |>
      str_remove_all("[()]") |>
      str_replace("Potosí", "Potosi"),
    province = label_es |>
      str_remove("\\s*\\([^)]+\\)$") |>
      str_remove("^Provincia de\\s+") |>
      str_remove("^Cercado$")
  )

# Some province items may not have "(Department)" disambiguation.
# Fall back to located-in labels when present would be better, but this QMD
# keeps it simple: we primarily rely on INE codes being present.

pop_prov_qs <- pop_prov |>
  mutate(
    department = departamento |> str_trim() |> str_replace("Potosí", "Potosi"),
    province   = provincia    |> str_trim()
  ) |>
  # join on (province, department) to recover province QID
  left_join(wd_prov_lookup |> select(qid, province, department, ine_code),
            by = c("province" = "province", "department" = "department"))

pop_prov_qs <- pop_prov |>
  left_join(provinces_wd, join_by(ine_code)) |> 
  relocate(ine_code, provincia, qid)

unmatched_prov <- pop_prov_qs |> filter(is.na(qid))
if (nrow(unmatched_prov) > 0) {
  message(nrow(unmatched_prov), " province row(s) had no QID match and will be dropped (inspect manually):")
  walk(head(unmatched_prov$provincia, 50), ~ message("  - ", .x))
}

pop_prov_qs <- pop_prov_qs |> filter(!is.na(qid))

Step 6: Compare existing and new population data in departments

Looking at the existing population data on Wikidata for departments, we see the most recent year is 2024 (the census year) for all nine. The one older year is 2012 for seven departments. These are the values that might match up.

pop_dept_qs |> 
  count(population_1_year)
# A tibble: 1 × 2
  population_1_year     n
              <int> <int>
1              2024     9
pop_dept_qs |> 
  count(population_2_year)
# A tibble: 3 × 2
  population_2_year     n
              <int> <int>
1              2012     7
2              2016     1
3              2020     1
pop_dept_qs |> 
  filter(population_1_year == 2024) |>
  select(1:3, pob_2024_total, population_1, population_1_year, population_1_ref) |>
  mutate(match = pob_2024_total == population_1)  |> 
  relocate(match, .after = qid)
# A tibble: 9 × 8
  id_dep departamento qid    match pob_2024_total population_1 population_1_year
  <chr>  <chr>        <chr>  <lgl>          <dbl>        <dbl>             <int>
1 01     Chuquisaca   Q2351… FALSE         606027       600132              2024
2 02     La Paz       Q2727… FALSE        3030917      3022566              2024
3 03     Cochabamba   Q2339… FALSE        2016357      2005373              2024
4 04     Oruro        Q1061… FALSE         571471       570194              2024
5 05     Potosí       Q2380… FALSE         861292       856419              2024
6 06     Tarija       Q2339… FALSE         534210       534348              2024
7 07     Santa Cruz   Q2351… FALSE        3122605      3115386              2024
8 08     Beni         Q2331… FALSE         488260       477441              2024
9 09     Pando        Q2353… FALSE         134194       130761              2024
# ℹ 1 more variable: population_1_ref <chr>
pop_dept_qs |> 
  filter(population_2_year == 2012) |>
  select(1:3, pob_2012_total, population_2, population_2_year, population_2_ref) |> 
  mutate(match = pob_2012_total == population_2) |> 
  relocate(match, .after = qid)
# A tibble: 7 × 8
  id_dep departamento qid    match pob_2012_total population_2 population_2_year
  <chr>  <chr>        <chr>  <lgl>          <dbl>        <dbl>             <int>
1 01     Chuquisaca   Q2351… FALSE         580923       581347              2012
2 02     La Paz       Q2727… TRUE         2719344      2719344              2012
3 04     Oruro        Q1061… TRUE          494587       494587              2012
4 05     Potosí       Q2380… FALSE         828517       823517              2012
5 06     Tarija       Q2339… FALSE         483518       482196              2012
6 07     Santa Cruz   Q2351… FALSE        2657762      2655084              2012
7 08     Beni         Q2331… FALSE         422008       421196              2012
# ℹ 1 more variable: population_2_ref <chr>
pop_dept_qs |> 
  filter(population_2_year != 2012) |>
  select(1:3,  population_2, population_2_year, population_2_ref) 
# A tibble: 2 × 6
  id_dep departamento qid     population_2 population_2_year population_2_ref
  <chr>  <chr>        <chr>          <dbl>             <int> <chr>           
1 03     Cochabamba   Q233917      1930143              2016 <NA>            
2 09     Pando        Q235362       110436              2020 <NA>            

The 2024 data are close, but unequal in all values. These values were initial releases by the Census and we will delete them to update them.

The 2012 data match in two cases, but none of theme are cited. We’ll delete all of these as well and replace them all with new, cited information.

Finally, we have two data points, without source, for 2016 and 2020. Since we are adding authoritative numbers for 2012 and 2024, we will delete these as well to avoid confusion.

Copy the lines below into QuickStatements batch mode and run them before proceeding to Step 7.

qids_to_clear <- departments_wd$qid
removals_dep <- make_p1082_removals(departments_wd, qids_to_clear)
writeLines(removals_dep$removal_statement)
-Q233169 | P1082 | 477441
-Q233169 | P1082 | 421196
-Q233917 | P1082 | 2005373
-Q233917 | P1082 | 1930143
-Q233933 | P1082 | 534348
-Q233933 | P1082 | 482196
-Q235106 | P1082 | 3115386
-Q235106 | P1082 | 2655084
-Q235110 | P1082 | 600132
-Q235110 | P1082 | 581347
-Q235362 | P1082 | 130761
-Q235362 | P1082 | 110436
-Q238079 | P1082 | 856419
-Q238079 | P1082 | 823517
-Q272784 | P1082 | 3022566
-Q272784 | P1082 | 2719344
-Q1061368 | P1082 | 570194
-Q1061368 | P1082 | 494587

Step 7: Generate P1082 QuickStatements (municipalities, provinces, departments)

One QuickStatements column per census year is produced using add_quick_statement_column_q().

Each statement carries:

  • a P585 (point in time) qualifier at year-level precision (/9);
  • S248 sourcing to Q139668018 (CPV 2024).
add_quick_statement_column_q <- function(dataframe, qid_col, property, value_col, ...){
  dataframe %>%
    rowwise() %>%
    mutate(quick_statement = create_quick_statement({{ qid_col }}, property, {{ value_col }}, ...)) %>%
    ungroup()
}
pop_qs_with_statements_muni <- pop_qs |>
  add_quick_statement_column_q(
    qid, "P1082", pob_2001_total,
    qualifiers    = list(P585 = p585_for_year(2001)),
    type          = "quantity",
    reference_qid = SOURCE_QID
  ) |>
  rename(qs_2001 = quick_statement) |>
  add_quick_statement_column_q(
    qid, "P1082", pob_2012_total,
    qualifiers    = list(P585 = p585_for_year(2012)),
    type          = "quantity",
    reference_qid = SOURCE_QID
  ) |>
  rename(qs_2012 = quick_statement) |>
  add_quick_statement_column_q(
    qid, "P1082", pob_2024_total,
    qualifiers    = list(P585 = p585_for_year(2024)),
    type          = "quantity",
    reference_qid = SOURCE_QID
  ) |>
  rename(qs_2024 = quick_statement)
pop_qs_with_statements_dept <- pop_dept_qs |>
  add_quick_statement_column_q(
    qid, "P1082", pob_2001_total,
    qualifiers    = list(P585 = p585_for_year(2001)),
    type          = "quantity",
    reference_qid = SOURCE_QID
  ) |>
  rename(qs_2001 = quick_statement) |>
  add_quick_statement_column_q(
    qid, "P1082", pob_2012_total,
    qualifiers    = list(P585 = p585_for_year(2012)),
    type          = "quantity",
    reference_qid = SOURCE_QID
  ) |>
  rename(qs_2012 = quick_statement) |>
  add_quick_statement_column_q(
    qid, "P1082", pob_2024_total,
    qualifiers    = list(P585 = p585_for_year(2024)),
    type          = "quantity",
    reference_qid = SOURCE_QID
  ) |>
  rename(qs_2024 = quick_statement)
pop_qs_with_statements_prov <- pop_prov_qs |>
  add_quick_statement_column_q(
    qid, "P1082", pob_2001_total,
    qualifiers    = list(P585 = p585_for_year(2001)),
    type          = "quantity",
    reference_qid = SOURCE_QID
  ) |>
  rename(qs_2001 = quick_statement) |>
  add_quick_statement_column_q(
    qid, "P1082", pob_2012_total,
    qualifiers    = list(P585 = p585_for_year(2012)),
    type          = "quantity",
    reference_qid = SOURCE_QID
  ) |>
  rename(qs_2012 = quick_statement) |>
  add_quick_statement_column_q(
    qid, "P1082", pob_2024_total,
    qualifiers    = list(P585 = p585_for_year(2024)),
    type          = "quantity",
    reference_qid = SOURCE_QID
  ) |>
  rename(qs_2024 = quick_statement)
muni_statements <- 
  pop_qs_with_statements_muni |> select(qid, qs_2001, qs_2012, qs_2024) |>
  distinct() |>
  arrange(qid) |>
  pivot_longer(cols = starts_with("qs_"), values_to = "statement") |>
  pull(statement)

other_statements <- bind_rows(
  pop_qs_with_statements_prov |> select(qid, qs_2001, qs_2012, qs_2024),
  pop_qs_with_statements_dept |> select(qid, qs_2001, qs_2012, qs_2024)
) |>
  distinct() |>
  arrange(qid) |>
  pivot_longer(cols = starts_with("qs_"), values_to = "statement") |>
  pull(statement)

cat("Total QuickStatements lines:", length(muni_statements)+length(other_statements), "\n")
Total QuickStatements lines: 1380 

Step 7: Review and export

Preview the first 15 lines to sanity-check the format before upload.

writeLines(head(other_statements, 15))
Q1061368 | P1082 | 392451 | P585 | +2001-01-01T00:00:00Z/9 | S248 | Q139668018 | S813 | +2026-05-10T00:00:00Z/11
Q1061368 | P1082 | 494587 | P585 | +2012-01-01T00:00:00Z/9 | S248 | Q139668018 | S813 | +2026-05-10T00:00:00Z/11
Q1061368 | P1082 | 571471 | P585 | +2024-01-01T00:00:00Z/9 | S248 | Q139668018 | S813 | +2026-05-10T00:00:00Z/11
Q1147271 | P1082 | 60359 | P585 | +2001-01-01T00:00:00Z/9 | S248 | Q139668018 | S813 | +2026-05-10T00:00:00Z/11
Q1147271 | P1082 | 82429 | P585 | +2012-01-01T00:00:00Z/9 | S248 | Q139668018 | S813 | +2026-05-10T00:00:00Z/11
Q1147271 | P1082 | 114232 | P585 | +2024-01-01T00:00:00Z/9 | S248 | Q139668018 | S813 | +2026-05-10T00:00:00Z/11
Q1166108 | P1082 | 11374 | P585 | +2001-01-01T00:00:00Z/9 | S248 | Q139668018 | S813 | +2026-05-10T00:00:00Z/11
Q1166108 | P1082 | 16308 | P585 | +2012-01-01T00:00:00Z/9 | S248 | Q139668018 | S813 | +2026-05-10T00:00:00Z/11
Q1166108 | P1082 | 22374 | P585 | +2024-01-01T00:00:00Z/9 | S248 | Q139668018 | S813 | +2026-05-10T00:00:00Z/11
Q120514 | P1082 | 36266 | P585 | +2001-01-01T00:00:00Z/9 | S248 | Q139668018 | S813 | +2026-05-10T00:00:00Z/11
Q120514 | P1082 | 44906 | P585 | +2012-01-01T00:00:00Z/9 | S248 | Q139668018 | S813 | +2026-05-10T00:00:00Z/11
Q120514 | P1082 | 49340 | P585 | +2024-01-01T00:00:00Z/9 | S248 | Q139668018 | S813 | +2026-05-10T00:00:00Z/11
Q1215506 | P1082 | 56979 | P585 | +2001-01-01T00:00:00Z/9 | S248 | Q139668018 | S813 | +2026-05-10T00:00:00Z/11
Q1215506 | P1082 | 108888 | P585 | +2012-01-01T00:00:00Z/9 | S248 | Q139668018 | S813 | +2026-05-10T00:00:00Z/11
Q1215506 | P1082 | 161913 | P585 | +2024-01-01T00:00:00Z/9 | S248 | Q139668018 | S813 | +2026-05-10T00:00:00Z/11

Export to a plain-text file for pasting into the QuickStatements batch interface at https://qs-dev.toolforge.org/.

# writeLines(all_statements, "data/cpv2024_population_quickstatements.txt")
writeLines(muni_statements, "data/cpv2024_population_quickstatements_municipalities.txt")
writeLines(other_statements, "data/cpv2024_population_quickstatements_dept_prov.txt")

# cat("Written to data/cpv2024_population_quickstatements.txt\n")
cat("Written municipality statements to data/cpv2024_population_quickstatements_municipalities.txt\n")
cat("Written department/province statements to data/cpv2024_population_quickstatements_dept_prov.txt\n")

The expected format of each line is:

QID | P1082 | <count> | P585 | +YYYY-01-01T00:00:00Z/9 | S248 | Q139668018 | S813 | +YYYY-MM-DDT00:00:00Z/11

Run the removal batch (Step 2) first, then submit the export file.