Reproducible research with UCDP data
Source:vignettes/reproducible-research.Rmd
reproducible-research.RmdA reproducible UCDP workflow records the exact release, inspects the
imported structure, checks analytical assumptions, and retains the
corresponding documentation. ucdpR keeps these tasks
separate so that each decision remains visible.
library(ucdpR)
conflicts <- data.frame(
conflict_id = c(1, 2, 3),
year = c(2020, 2021, 2021),
location = c("A", "B", "C"),
low = c(0, 2, 1),
best = c(1, 3, 2),
high = c(2, 4, 3),
latitude = c(10, 20, 30),
longitude = c(40, 50, 60)
)Describe the object and its coverage
ucdp_metadata() gives a compact record of dimensions and
available temporal or coordinate coverage. Imported UCDP objects
additionally report their source record, checksum, retrieval time, and
package version.
ucdp_metadata(conflicts, dataset = "Synthetic conflict data")
#> # A tibble: 1 × 20
#> dataset version variant format file_name source_url catalog_source
#> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
#> 1 Synthetic conflict… NA NA NA NA NA NA
#> # ℹ 13 more variables: retrieved_at <chr>, md5 <chr>, ucdpR_version <chr>,
#> # n_rows <int>, n_columns <int>, year_min <int>, year_max <int>,
#> # date_min <chr>, date_max <chr>, latitude_min <dbl>, latitude_max <dbl>,
#> # longitude_min <dbl>, longitude_max <dbl>ucdp_schema() works at the variable level and is useful
before joins, transformations, or model preparation.
schema <- ucdp_schema(conflicts)
schema[c("variable", "class", "n_missing", "n_unique", "minimum", "maximum")]
#> # A tibble: 8 × 6
#> variable class n_missing n_unique minimum maximum
#> <chr> <chr> <int> <int> <chr> <chr>
#> 1 conflict_id numeric 0 3 1 3
#> 2 year numeric 0 2 2020 2021
#> 3 location character 0 3 NA NA
#> 4 low numeric 0 3 0 2
#> 5 best numeric 0 3 1 3
#> 6 high numeric 0 3 2 4
#> 7 latitude numeric 0 3 10 30
#> 8 longitude numeric 0 3 40 60Validate assumptions without altering data
Validation checks are applied only when their required variables are present. The result separates a compact summary from record-level issues.
validation <- ucdp_validate(conflicts, key = "conflict_id")
validation$valid
#> [1] TRUE
validation$summary
#> # A tibble: 5 × 3
#> check status n_issues
#> <chr> <chr> <int>
#> 1 keys pass 0
#> 2 dates skipped 0
#> 3 fatalities pass 0
#> 4 coordinates pass 0
#> 5 codes skipped 0
validation$issues
#> # A tibble: 0 × 6
#> # ℹ 6 variables: check <chr>, severity <chr>, row <int>, column <chr>,
#> # value <chr>, message <chr>Warnings identify observations for inspection; they do not establish
that UCDP made a coding error. With strict = TRUE, warnings
also make the overall validation result invalid, which can be useful in
automated pipelines.
Aggregate events and retain fatality uncertainty
Fatality estimates should be aggregated as a low, best, and high triplet rather than reducing every observation to its best estimate alone.
ucdp_fatalities(conflicts, by = "year")
#> # A tibble: 2 × 7
#> year n_observations n_complete n_missing fatalities_low fatalities_best
#> <dbl> <int> <int> <int> <dbl> <dbl>
#> 1 2020 1 1 0 0 1
#> 2 2021 2 2 0 3 5
#> # ℹ 1 more variable: fatalities_high <dbl>
conflict_year <- ucdp_aggregate(
conflicts,
unit = "conflict-year"
)
conflict_year
#> # A tibble: 3 × 8
#> conflict_id year n_events n_fatality_complete n_fatality_missing
#> <dbl> <int> <int> <int> <int>
#> 1 1 2020 1 1 0
#> 2 2 2021 1 1 0
#> 3 3 2021 1 1 0
#> # ℹ 3 more variables: fatalities_low <dbl>, fatalities_best <dbl>,
#> # fatalities_high <dbl>ucdp_aggregate() also supports country, PRIO-GRID, and
dyad units with yearly or monthly periods. Common entity and fatality
columns are detected, while id, date,
low, best, and high provide
explicit overrides.
Construct complete panels transparently
panel_events <- data.frame(
conflict_id = c(1, 1, 2),
year = c(2020, 2022, 2021),
low = c(0, 1, 2), best = c(1, 2, 3), high = c(2, 3, 4)
)
panel <- ucdp_panel(
panel_events,
unit = "conflict-year",
start = 2020,
end = 2022,
fill = "zero"
)
panel[c("conflict_id", "year", "n_events", ".ucdp_observed", ".ucdp_fill")]
#> # A tibble: 6 × 5
#> conflict_id year n_events .ucdp_observed .ucdp_fill
#> <dbl> <int> <int> <lgl> <chr>
#> 1 1 2020 1 TRUE observed
#> 2 1 2021 0 FALSE zero_filled
#> 3 1 2022 1 TRUE observed
#> 4 2 2020 0 FALSE zero_filled
#> 5 2 2021 1 TRUE observed
#> 6 2 2022 0 FALSE zero_filledRows introduced to complete the panel remain identifiable. A
zero-filled row does not prove that UCDP observed a true zero; it
records the analyst’s chosen completion rule. Use
fill = "missing" when unobserved combinations should remain
missing, and supply universe when the panel must include
entities that never appear in the event data.
Retain provenance with live data
prio <- ucdp_get("prio", version = "25.1", format = "csv")
ucdp_metadata(prio)
ucdp_schema(prio)
ucdp_validate(prio)If the original source file should remain alongside the analysis, use
ucdp_download() and store it in a project directory rather
than relying on a temporary import.
Keep documentation with the release
Codebooks explain variables and coding rules; version histories explain changes between releases; citation guidance records the attribution requested by UCDP.
ucdp_codebook(
"prio", version = "25.1", dest_dir = "documentation"
)
ucdp_version_history(
"prio", version = "25.1", dest_dir = "documentation"
)
ucdp_cite("prio")Exact historical documentation is returned only when UCDP explicitly lists a matching artifact. The package does not silently substitute a current codebook for an older release.
Use publication-specific replication files
UCDP’s replication archive is distinct from its ordinary dataset catalog. It contains frozen files associated with particular publications.
replication <- ucdp_replication_catalog(
query = "Georeferenced", year = 2025, type = "data"
)
paths <- ucdp_replication_download(
"ged", version = "25.1", year = 2025,
dest_dir = "replication"
)
attr(paths, "ucdp_records")
attr(paths, "md5")A practical project record
For each empirical analysis, retain at least:
- the dataset name, exact version, and variant;
- the original file or its source URL and checksum;
- the retrieval date and
ucdpRversion; - the matching codebook and version history;
- validation output and explicit filtering decisions; and
- UCDP’s requested citation.
These records do not eliminate all sources of uncertainty, but they make the analytical input reconstructable and revisions auditable.