Contentious Politics and Civil Conflict Research
Overview
Constructs reproducible country-year panels for research on contentious politics and civil conflict, as described in Guseinov (2026) doi:10.2139/ssrn.7506799. Functions build state panels keyed by Correlates of War or Gleditsch-Ward country codes and join curated socioeconomic, leadership, democracy, conflict, protest, and revolutionary-episode data on that common key, with diagnostics and plots for comparing source coverage. Bundled sources include Gapminder; the Nonviolent and Violent Campaigns and Outcomes (NAVCO) 2.1 data, Chenoweth and Shay (2019) doi:10.7910/DVN/MHOXDV; the Social Conflict Analysis Database, Salehyan et al. (2012) doi:10.1080/03050629.2012.697426; the Uppsala Conflict Data Program and Peace Research Institute Oslo (UCDP/PRIO) Armed Conflict Dataset, Gleditsch et al. (2002) doi:10.1177/0022343302039005007; and the Major Episodes of Contention data, Chenoweth and Kang (2026) doi:10.1093/jopres/xjaf008. Varieties of Democracy (V-Dem) indicators require the optional 'vdemdata' package, which is not on CRAN and can be installed from https://github.com/vdeminstitute/vdemdata.
Changes made for CRAN
- The package title is now "Contentious Politics and Civil Conflict Research".
cn_cite()now returns its result visibly instead of printing it withcat(). The result is abibentryobject with the additional classcn_citation; typingcn_cite("archigos")at the console still shows the BibTeX, andprint()shows it explicitly.- The bundled data files are smaller (tarball 4.3 MB): they keep only the columns the package reads, and the MEC and NMC Stata files are stored as compressed
.rds. Loader output is unchanged. 'haven' is no longer used. citation("contentiousR")now lists the SSRN preprint describing the package, followed by the software citation.
Show all changes in 0.1.0Hide the rest of the changes in 0.1.0
Bug fixes
load_vdem_data(coding_system = "cow")no longer silently drops East Germany (COW 265, 1949-1990); it was previously excluded only in the"cow"branch, so V-Dem coverage for Germany differed depending on the chosen coding system with no indication why.add_spell_duration()now computes spells from the actual calendar-year difference instead of row position within a state. A gap in the input years (e.g. left bytidyr::drop_na(event), which the package's own examples recommend) previously understated the elapsed time.plot_coverage()now errors with a clear message instead of crashing whendrop_empty = TRUEremoves every state (e.g. the chosen event never occurs in the supplied panel/year range).cn_cite()matched keywords by substring, so a shortdatasetname (e.g."mm") could also match an unrelated entry whose keyword merely contained it as a substring ("mmad"). Keyword matching is now exact against the comma-separated keyword list.harmonize_conflict_data(): a factoryear_colwas coerced withas.integer(), which returns the factor's internal level codes rather than the printed year. It is now converted to character first. Adate_colthat fails to parse (e.g. a non-ISO format without a matchingdate_format) now raises a clear error instead of a generic base-R one.
Bring your own data
- Added
harmonize_conflict_data()to join externally supplied conflict/ event data (GDELT, ICEWS, ACLED, or anything else not bundled withcontentiousR) onto a state panel: it maps the caller's country column to COW/GW codes viacountrycode::countrycode(), extracts a year from either a pre-parsedyear_color adate_col/date_format, optionally aggregates event-level rows to country-year (<prefix>_onset,<prefix>_n_events), and joins the result in. Unlikeadd_conflict(), it never downloads or bundles data itself, socontentiousRgains no dependency ongdeltr2,icews, oracled.api.
Visualization
plot_coverage()gained ashow_labelsargument (defaultTRUE). Set it toFALSEto drop the per-row country/code labels, which otherwise overlap and become illegible once the panel covers more than a few dozen states.plot_regional_coverage()'s region labels are now horizontal and word-wrapped instead of angled, and its region field's canonical "Middle East" label is the shorter "Middle East & North Africa" form.plot_temporal_coverage()'s period labels are now vertical instead of angled. Both plots no longer set aggplot2title (redundant with a caption in a manuscript).- Added
plot_regional_coverage()andplot_temporal_coverage()to compare regional and temporal event coverage across any combination ofconflict_data()campaign/episode datasets, plus a "Comparing revolutionary-event datasets" article reproducing the descriptive exercise in Guseinov, Ustyuzhanin & Korotayev (2026). - Added
add_regions()to join one or morecountrycoderegion classifications (region,region23,un.region.name,un.regionsub.name) onto a state panel bycow/gwcode.
Data
- Added the Major Episodes of Contention (MEC) dataset: 2,734 globally covered reformist and maximalist episodes from 1955 through 2018. MEC is available through
conflict_data(dataset = "mec")andadd_conflict(dataset = "mec"). Episode-level rows are preserved unless the existingaggregate = TRUEpolicy is requested.
Correctness
fetch_campaign_events()(used byplot_regional_coverage()andplot_temporal_coverage()) now compares NAVCO 2.1 at the same campaign-onset level as the other datasets, usingconflict_data()'s ownnvc2.1_ONSETflag (keyed on the numeric campaign id) instead of re-deriving onsets from the campaign name, which is not unique and could silently merge distinct campaigns that happen to share a name.fetch_campaign_events()'sregionfield now stays at exactly 7 categories.countrycode::countrycode()'s"region"destination labels a few pre-1990 historical entities (Yemen Arab Republic, Yemen People's Republic, the United Arab Republic) with the World Bank's older "Middle East & North Africa" string while every other MENA country gets the newer "Middle East, North Africa, Afghanistan & Pakistan" string; since campaign data covering the 1950s-80s includes those historical codes, the region was silently splitting into two bars inplot_regional_coverage()/plot_temporal_coverage().gdp_growth(load_gdp_data(),dataset = "gapminder") is nowNAunless the preceding row is genuinely one year earlier for the same country, the same gap-safety checkadd_lag()uses.- Removed
add_pop(). It was an exact duplicate ofadd_population()(same body, same arguments, two visually identical Reference entries) and every otheradd_*()/load_*_data()pair in the package already shares one name (add_vdem()/load_vdem_data(),add_leader_data()/load_leader_data(), etc.) --add_population()is the one that matchesload_population_data(). Useadd_population()instead. - Renamed
add_spells()toadd_spell_duration()to stop it silently shadowing (or being shadowed by)peacesciencer::add_spells()when both packages are attached in the same session -- the two are similar in spirit but not interchangeable (contentiousR's version works on any binary_onset/_incidence/_ongoingcolumn, not a fixed set of bundled columns). conflict_data()now appliesstart_yearandend_yearconsistently to every bundled source.- UCDP/PRIO output now distinguishes conflict incidence from episode onset.
ucdp_prio_onsetis based onstart_date2; the newucdp_prio_incidencecolumn identifies all active conflict-years. - SCAD country-year totals now exclude UCDP placeholder records, deduplicate multi-location rows by event ID, and treat documented negative death-count codes as missing.
- All-missing groups now produce
NAinstead of-Inf,NaN, and associated warnings during conflict aggregation. - Mass Mobilization participant strings are retained in
mm_participants_reported;mm_participantssummarizes only exact numeric reports. add_conflict()no longer re-aggregates sources that are already unique by country-year, preventing character-valued source fields from being dropped.
API and robustness
- Added
as_peacesciencer_panel()to supply the state-year key aliases and metadata required bypeacesciencerwhile preserving contentiousR's API. - Added
add_from_peacesciencer()to apply a state-yearpeacesciencerfunction while keeping temporaryccode/gwcodekeys out of the result. build_states_cow_panel()is internal again (not exported). It's the actual COW-panel implementationbuild_states_panel(coding_system = "cow")dispatches to, but there's no public reason to call it directly instead ofbuild_states_panel()-- and its GW counterpart,build_states_gw_panel(), was never exported in the first place.- Added strict validation for years, logical flags, panel keys, and output-key uniqueness.
build_states_panel()now validatesstart_year/end_yearagainst the Correlates of War / Gleditsch-Ward state system's actual coverage:1816-2025.- Added
ucdp_vpp_incidence. The existingucdp_vpp_onsetcolumn remains as a compatibility alias and is now documented as incidence rather than onset. - Removed the
magrittrdependency in favor of R's native pipe.
Release infrastructure
- Added broader test coverage, two introductory vignettes, package-level documentation, data provenance and licensing notes, pkgdown configuration, and GitHub Actions for package checks and site deployment.
- Added a case study article assembling a panel and modeling revolutionary onset, and a "Comparing revolutionary-event datasets" article (see Visualization above).
- Added a package logo, shown in the README and the pkgdown site navbar.
- Added formal
Referencessections toload_gdp_data()/add_gdp(),load_population_data()/add_population(),load_military_expenditure_data()/add_military_expenditure(),load_vdem_data()/add_vdem(),conflict_data()/add_conflict(),load_leader_data()/add_leader_data(), andplot_regional_coverage()/plot_temporal_coverage(), citing the underlying data source(s) for each. - Corrected the SCAD citation's DOI (in
DESCRIPTIONand the bundled bibliography behindcn_cite()): the previous DOI did not resolve.
From NEWS.md in the release
Install
Health
- OK13 OKNow
- OK6 OK2026-10-16
Documentation
- Help pages
- 40 (16 internal)includes a package overview page
- Examples that run
- 100%22 run in a plain check (6 of them under a condition)
- Exported functions with examples
- 96%
- Documented parameters
- 96%
- Return-value docs
- 100%
- Help pages citing references
- 35%
Downloads
Repository
Stars over time
11 development-tooling and community-health practices detected across 6 families in the upstream repository
Checks run against github.com/rguseinov/contentiousr on 2026-10-21.
The R CMD check workflow runs on Linux, macOS and Windows, and on R-devel
GitHub Pages site last deployed 2026-10-15 · The repository has a site deploy workflow
pkgdown site last built 2026-10-15
Show all practicesHide 2 practices
Dependencies
Code & Tests
Datasets
People & History
- 0.1.0Latest2026-10-15 · current release ·
12 days in CRAN's queue
Listed in CRAN's incoming queue from 2026-10-03 21:57 to 2026-10-15 12:21 UTC, in 52 readings. - RR 4.6.0 released · 2026-04-24
Package metadata
- First published
- 2026-10-15
- Total releases
- 1 / 1 yrs
- License
- MIT + file LICENSE OSI
- Copyright
- See file COPYRIGHTS for the third-party data bundled in inst/extdata.
- Minimum R
- ≥ 4.1.0
- Bundled data
- 3.7 KB / 1 file
- Download size
- 4.3 MB
Cite
Cite this package
Run in R for the authors' entry:
citation("contentiousR")The package provides a citation file, so citation() returns the authors' own entry.
It points to 10.2139/ssrn.7506799.
Cite the R Observatory
For a number measured here: a download total, a coverage figure, an archival date.
From data release v2026-10-25, which the citation names so these numbers can be found later. More on citing and the projects behind them.