Getting Started with psreplicate

library(psreplicate)

psreplicate is an R client for the Political Science Replication Index: a searchable, tagged index of replication packages crawled monthly from 34 flagship political science journals’ Harvard Dataverse collections. This vignette walks through the package’s functions in the order you’d typically reach for them.

Don’t know where to start? list_functions()

list_functions()
#> # A tibble: 18 × 2
#>    function_name       description                                              
#>    <chr>               <chr>                                                    
#>  1 search_replications Search/filter by query, journal, method, data_type, and …
#>  2 search_by_title     Search by title text only.                               
#>  3 search_by_abstract  Search by abstract/description text only.                
#>  4 search_by_author    Search by author name only.                              
#>  5 search_by_journal   Get all records from one or more journals.               
#>  6 search_by_method    Get all records tagged with a given method.              
#>  7 search_by_data_type Get all records tagged with a given data type.           
#>  8 search_by_year      Get all records published in given year(s).              
#>  9 dataset_info        Look up a single record by its DOI.                      
#> 10 browse_dataset      Open a dataset's page in your web browser.               
#> 11 list_dataset_files  List a dataset's files before downloading (needs the dat…
#> 12 download_dataset    Download a dataset's files to disk (needs the dataverse …
#> 13 load_dataset_file   Load one file straight into R, no disk (needs the datave…
#> 14 list_journals       List journals covered, with record counts.               
#> 15 list_methods        List method tags in use, with record counts.             
#> 16 list_data_types     List data-type tags in use, with record counts.          
#> 17 list_functions      This list.                                               
#> 18 refresh_index       Force a re-download of the index (otherwise refreshes da…

That’s every exported function in the package, in one table. The rest of this vignette just walks through the same list with worked examples.

Searching everything at once

search_replications() is the broad, do-everything search: free text across title/abstract/authors, plus optional filters for journal, method, data type, and year, all combined with AND.

search_replications(query = "regression discontinuity", journal = "AJPS")
#> # A tibble: 7 × 9
#>   journal_short title          doi   url   authors  year description method_tags
#>   <chr>         <chr>          <chr> <chr> <chr>   <int> <chr>       <list>     
#> 1 AJPS          Replication D… doi:… http… Kosec,…  2022 Could perc… <chr [2]>  
#> 2 AJPS          Replication D… doi:… http… Marsha…  2022 Politician… <chr [1]>  
#> 3 AJPS          Replication D… doi:… http… Gulzar…  2020 Over 40% o… <chr [1]>  
#> 4 AJPS          Replication D… doi:… http… Kogan,…  2020 We employ … <chr [1]>  
#> 5 AJPS          Replication D… doi:… http… Grembi…  2017 In many co… <chr [1]>  
#> 6 AJPS          Replication D… doi:… http… Coppoc…  2015 Field expe… <chr [2]>  
#> 7 AJPS          Replication d… doi:… http… Eggers…  2015 The regres… <chr [1]>  
#> # ℹ 1 more variable: data_type_tags <list>
search_replications(method = "Survey Experiment", year = 2020:2024)
#> # A tibble: 456 × 9
#>    journal_short title         doi   url   authors  year description method_tags
#>    <chr>         <chr>         <chr> <chr> <chr>   <int> <chr>       <list>     
#>  1 APSR          "Replication… doi:… http… Daur, …  2024 "Mainstrea… <chr [1]>  
#>  2 APSR          "Replication… doi:… http… Eady, …  2024 "Politicia… <chr [1]>  
#>  3 APSR          "Replication… doi:… http… Goldbe…  2024 "Supplemen… <chr [1]>  
#>  4 APSR          "Replication… doi:… http… Wimmer…  2024 "Introduci… <chr [1]>  
#>  5 APSR          "Replication… doi:… http… Rathbu…  2024 "Why are d… <chr [2]>  
#>  6 APSR          "Replication… doi:… http… Alaria…  2024 "Expanding… <chr [1]>  
#>  7 APSR          "Replication… doi:… http… Schiff…  2024 "This is r… <chr [1]>  
#>  8 APSR          "Replication… doi:… http… Lee, S…  2023 "What inte… <chr [1]>  
#>  9 APSR          "Replication… doi:… http… Jimene…  2023 "Local gov… <chr [1]>  
#> 10 APSR          "Replication… doi:… http… Noh, Y…  2023 "Gender qu… <chr [1]>  
#> # ℹ 446 more rows
#> # ℹ 1 more variable: data_type_tags <list>

Searching one field at a time

If you already know which field you’re searching, the single-field functions skip the guesswork of what search_replications()’s query argument actually matches against:

search_by_title("regression discontinuity")   # title only
#> # A tibble: 17 × 9
#>    journal_short title         doi   url   authors  year description method_tags
#>    <chr>         <chr>         <chr> <chr> <chr>   <int> <chr>       <list>     
#>  1 AJPS          "Replication… doi:… http… Marsha…  2022 "Politicia… <chr [1]>  
#>  2 AJPS          "Replication… doi:… http… Grembi…  2017 "In many c… <chr [1]>  
#>  3 AJPS          "Replication… doi:… http… Eggers…  2015 "The regre… <chr [1]>  
#>  4 JOP           "Replication… doi:… http… Holbei…  2019 "This cont… <chr [1]>  
#>  5 JOP           "Replication… doi:… http… Cattan…  2016 "Replicati… <chr [1]>  
#>  6 BJPS          "Replication… doi:… http… White,…  2023 "This is t… <chr [1]>  
#>  7 BJPS          "Replication… doi:… http… Abou-C…  2018 "This arti… <chr [1]>  
#>  8 PSRM          "Replication… doi:… http… Turgeo…  2021 "We study … <chr [1]>  
#>  9 PSRM          "Replication… doi:… http… De Mag…  2019 "Regressio… <chr [1]>  
#> 10 CPS           "Replication… doi:… http… Singh,…  2021 "Replicati… <chr [2]>  
#> 11 LSQ           "Replication… doi:… http… Pereir…  2022 "Replicati… <chr [1]>  
#> 12 PAN           "Replication… doi:… http… De Mag…  2024 "Replicati… <chr [1]>  
#> 13 PAN           "Replication… doi:… http… Miller…  2020 "This lett… <chr [1]>  
#> 14 PAN           "Replication… doi:… http… Hartma…  2020 "Regressio… <chr [1]>  
#> 15 PAN           "Replication… doi:… http… Choi, …  2018 "In regres… <chr [1]>  
#> 16 RP            "Replication… doi:… http… Drew S…  2023 "Replicati… <chr [1]>  
#> 17 RP            "Replication… doi:… http… Song, …  2019 "This is t… <chr [1]>  
#> # ℹ 1 more variable: data_type_tags <list>
search_by_abstract("difference-in-differences") # abstract/description only
#> # A tibble: 13 × 9
#>    journal_short title         doi   url   authors  year description method_tags
#>    <chr>         <chr>         <chr> <chr> <chr>   <int> <chr>       <list>     
#>  1 APSR          "Replication… doi:… http… Hassel…  2024 Recent wor… <chr [1]>  
#>  2 APSR          "Replication… doi:… http… García…  2021 How do cit… <chr [1]>  
#>  3 AJPS          "Replication… doi:… http… Colner…  2024 Does the i… <chr [1]>  
#>  4 AJPS          "Replication… doi:… http… grier,…  2024 We use dou… <chr [1]>  
#>  5 AJPS          "Replication… doi:… http… Glynn,…  2017 We develop… <chr [1]>  
#>  6 JOP           "Replication… doi:… http… Pahont…  2024 How does e… <chr [1]>  
#>  7 BJPS          "Replication… doi:… http… Giani,…  2025 Globalisat… <chr [1]>  
#>  8 PSRM          "Replication… doi:… http… Yoder,…  2020 We use nat… <chr [1]>  
#>  9 PAN           "Replication… doi:… http… Egami,…  2022 While a di… <chr [2]>  
#> 10 PoP           "Replication… doi:… http… Lueder…  2025 What are t… <chr [2]>  
#> 11 JPP           "Environment… doi:… http… Xu, H.…  2024 Based on m… <chr [2]>  
#> 12 RP            "Replication… doi:… http… Lipkov…  2025 Voter iden… <chr [1]>  
#> 13 RP            "Replication… doi:… http… Garsid…  2022 Can first-… <chr [1]>  
#> # ℹ 1 more variable: data_type_tags <list>
search_by_author("Wantchekon")                  # author names only
#> # A tibble: 3 × 9
#>   journal_short title          doi   url   authors  year description method_tags
#>   <chr>         <chr>          <chr> <chr> <chr>   <int> <chr>       <list>     
#> 1 APSR          Replication D… doi:… http… Wantch…  2026 Data and c… <chr [0]>  
#> 2 AJPS          Replication D… doi:… http… Garcia…  2023 We show th… <chr [3]>  
#> 3 AJPS          Replication D… doi:… http… López-…  2020 In a rando… <chr [1]>  
#> # ℹ 1 more variable: data_type_tags <list>

And the same idea for the structured fields:

search_by_journal(c("AJPS", "APSR"))
#> # A tibble: 1,600 × 9
#>    journal_short title         doi   url   authors  year description method_tags
#>    <chr>         <chr>         <chr> <chr> <chr>   <int> <chr>       <list>     
#>  1 APSR          Replication … doi:… http… Wantch…  2026 "Data and … <chr [0]>  
#>  2 APSR          Replication … doi:… http… Clarke…  2026 "This prov… <chr [0]>  
#>  3 APSR          Preventing R… doi:… http… Blair,…  2026 "Replicati… <chr [1]>  
#>  4 APSR          Replication … doi:… http… Jiang,…  2026 "As the ep… <chr [1]>  
#>  5 APSR          Replication … doi:… http… Velez,…  2026 "A persist… <chr [0]>  
#>  6 APSR          Replication … doi:… http… Bollen…  2026 "The physi… <chr [0]>  
#>  7 APSR          Replication … doi:… http… Voeten…  2026 "This arch… <chr [0]>  
#>  8 APSR          Replication … doi:… http… Sarkar…  2026 "The exper… <chr [0]>  
#>  9 APSR          Replication … doi:… http… Bleck,…  2026 "xxx"       <chr [0]>  
#> 10 APSR          Replication … doi:… http… Jablon…  2026 "Replicati… <chr [0]>  
#> # ℹ 1,590 more rows
#> # ℹ 1 more variable: data_type_tags <list>
search_by_method("Field Experiment")
#> # A tibble: 224 × 9
#>    journal_short title         doi   url   authors  year description method_tags
#>    <chr>         <chr>         <chr> <chr> <chr>   <int> <chr>       <list>     
#>  1 APSR          Preventing R… doi:… http… Blair,…  2026 "Replicati… <chr [1]>  
#>  2 APSR          Replication … doi:… http… Ahuja,…  2026 "How do el… <chr [1]>  
#>  3 APSR          Replication … doi:… http… Kao, J…  2026 "Replicati… <chr [1]>  
#>  4 APSR          Replication … doi:… http… AMAR, …  2025 "Misinform… <chr [1]>  
#>  5 APSR          Replication … doi:… http… Kruks-…  2025 "This pack… <chr [1]>  
#>  6 APSR          Replication … doi:… http… Martin…  2025 "Understan… <chr [1]>  
#>  7 APSR          Replication … doi:… http… Larson…  2024 "Intervent… <chr [2]>  
#>  8 APSR          Replication … doi:… http… Master…  2023 "Without f… <chr [2]>  
#>  9 APSR          Replication … doi:… http… Bernha…  2023 "This data… <chr [1]>  
#> 10 APSR          Replication … doi:… http… Cheema…  2022 "This data… <chr [1]>  
#> # ℹ 214 more rows
#> # ℹ 1 more variable: data_type_tags <list>
search_by_data_type("Elections / Voting")
#> # A tibble: 2,301 × 9
#>    journal_short title         doi   url   authors  year description method_tags
#>    <chr>         <chr>         <chr> <chr> <chr>   <int> <chr>       <list>     
#>  1 APSR          Replication … doi:… http… Wantch…  2026 "Data and … <chr [0]>  
#>  2 APSR          Replication … doi:… http… Clinto…  2026 "This incl… <chr [0]>  
#>  3 APSR          Replication … doi:… http… Horiuc…  2026 "In a rece… <chr [0]>  
#>  4 APSR          Replication … doi:… http… Müller…  2026 "Ethnicity… <chr [0]>  
#>  5 APSR          Replication … doi:… http… Bowles…  2026 "How do ca… <chr [0]>  
#>  6 APSR          Replication … doi:… http… Ahuja,…  2026 "How do el… <chr [1]>  
#>  7 APSR          Replication … doi:… http… Spry, …  2026 "This pape… <chr [0]>  
#>  8 APSR          Replication … doi:… http… Tuñón,…  2026 "Social sc… <chr [0]>  
#>  9 APSR          Replication … doi:… http… Kao, J…  2026 "Replicati… <chr [1]>  
#> 10 APSR          Replication … doi:… http… Myers,…  2026 "Fundraisi… <chr [1]>  
#> # ℹ 2,291 more rows
#> # ℹ 1 more variable: data_type_tags <list>
search_by_year(2015:2020)
#> # A tibble: 3,888 × 9
#>    journal_short title         doi   url   authors  year description method_tags
#>    <chr>         <chr>         <chr> <chr> <chr>   <int> <chr>       <list>     
#>  1 APSR          "Replication… doi:… http… Fouirn…  2020 "Replicati… <chr [0]>  
#>  2 APSR          "Replication… doi:… http… Lo, Ad…  2020 "Replicati… <chr [1]>  
#>  3 APSR          "Replication… doi:… http… Suryan…  2020 "Replicati… <chr [0]>  
#>  4 APSR          "APSA Princi… doi:… http… APSA C…  2020 "On April … <chr [0]>  
#>  5 APSR          "Replication… doi:… http… Tertyt…  2020 "We post t… <chr [0]>  
#>  6 APSR          "Replication… doi:… http… Walter…  2020 "The repli… <chr [0]>  
#>  7 APSR          "Replication… doi:… http… Moskow…  2020 "Replicati… <chr [0]>  
#>  8 APSR          "Replication… doi:… http… Haas, …  2020 "Does poli… <chr [0]>  
#>  9 APSR          "Replication… doi:… http… Landwe…  2020 "Depressio… <chr [0]>  
#> 10 APSR          "Replication… doi:… http… Zubek,…  2020 "Identifyi… <chr [0]>  
#> # ℹ 3,878 more rows
#> # ℹ 1 more variable: data_type_tags <list>

Finding out what values are even valid

The catch with search_by_method(), search_by_data_type(), and search_by_journal() is that you have to already know a valid tag or journal code to pass in. These three functions list exactly what’s in the data right now, most common first:

list_journals()
#> # A tibble: 34 × 3
#>    journal_short journal_name                          n_records
#>    <chr>         <chr>                                     <int>
#>  1 AJPS          American Journal of Political Science       832
#>  2 APSR          American Political Science Review           768
#>  3 BJPS          British Journal of Political Science        762
#>  4 BPSR          Brazilian Political Science Review           78
#>  5 CPS           Comparative Political Studies               422
#>  6 DADOS         Revista DADOS                                88
#>  7 FPA           Foreign Policy Analysis                     270
#>  8 II            International Interactions                   25
#>  9 IO            International Organization                  193
#> 10 IPSR          Italian Political Science Review            142
#> # ℹ 24 more rows
list_methods()
#> # A tibble: 16 × 2
#>    method                          n_records
#>    <chr>                               <int>
#>  1 Survey Experiment                     881
#>  2 Field Experiment                      224
#>  3 Panel Data                            210
#>  4 Difference-in-Differences             145
#>  5 Bayesian Methods                      133
#>  6 Regression Discontinuity              115
#>  7 Network Analysis                      112
#>  8 Machine Learning                      109
#>  9 Text as Data / NLP                     99
#> 10 Case Study / Process Tracing           98
#> 11 Instrumental Variable                  85
#> 12 Formal Model / Game Theory             70
#> 13 Spatial Analysis                       51
#> 14 Survival / Duration Model              51
#> 15 Multilevel / Hierarchical Model        43
#> 16 Meta-Analysis                          36
list_data_types()
#> # A tibble: 8 × 2
#>   data_type                           n_records
#>   <chr>                                   <int>
#> 1 Elections / Voting                       2301
#> 2 Elite / Legislator Data                  1337
#> 3 Public Opinion                           1306
#> 4 Experimental Data                        1216
#> 5 Survey Data                               329
#> 6 Cross-National / Country-Level            253
#> 7 Text / Corpus                             145
#> 8 Administrative / Government Records        79

Looking up and opening a specific dataset

Once you have a doi from a search result, dataset_info() pulls just that one record, and browse_dataset() does the same but opens the dataset’s page directly in your browser instead of returning a tibble:

hit <- search_by_title("Rebel Victory and Authoritarian")
dataset_info(hit$doi[1])
#> # A tibble: 1 × 9
#>   journal_short title          doi   url   authors  year description method_tags
#>   <chr>         <chr>          <chr> <chr> <chr>   <int> <chr>       <list>     
#> 1 APSR          Replication D… doi:… http… Clarke…  2026 "This prov… <chr [0]>  
#> # ℹ 1 more variable: data_type_tags <list>
browse_dataset(hit$doi[1])

Downloading the actual data files

Everything so far is metadata - title, abstract, authors, tags, a link. list_dataset_files() and download_dataset() get the real files (the .dta/.csv/.R/etc. that make up the replication package), so you don’t have to leave R to go download them by hand. Both require the dataverse package (install.packages("dataverse")), which does the actual work of talking to Harvard Dataverse’s file API - these are thin convenience wrappers around it, scoped to this index’s DOIs.

list_dataset_files(hit$doi[1])
#> # A tibble: 64 × 3
#>    filename                                                filesize content_type
#>    <chr>                                                      <int> <chr>       
#>  1 alesina_frac.tab                                            7996 text/tab-se…
#>  2 allwars_covar.tab                                         105466 text/tab-se…
#>  3 area.do                                                      275 text/x-stat…
#>  4 area.tab                                                    4505 text/tab-se…
#>  5 btscs.ado                                                   6316 application…
#>  6 civilreg.do                                                 1294 text/x-stat…
#>  7 ClarkeMengPaine_Rebel Victory_Appendix A (Online Appen…   231647 application…
#>  8 ClarkeMengPaine_Rebel Victory_Appendix B (Codebook).pdf   620019 application…
#>  9 cmp_allauth.tab                                            60834 text/tab-se…
#> 10 cmp_allauth_tscs.tab                                     1093178 text/tab-se…
#> # ℹ 54 more rows
# downloads every file into a new temporary directory and returns the paths
paths <- download_dataset(hit$doi[1])

# or into a specific directory, and only specific files
download_dataset(hit$doi[1], dest = "replication_data", files = "README.rtf")

If you just want one file’s contents, load_dataset_file() skips the disk entirely: a tabular file (.tab/.dta/.csv/etc.) comes back as a tibble, an .rds file is deserialized with readRDS() as whatever R object it holds, a plain-text file (a script, a README) comes back as lines of text, and anything else (PDFs, images) comes back as raw bytes.

load_dataset_file(hit$doi[1], "area.tab")
#> Downloading ingested version of data with readr::read_tsv. To download the original version and remove this message, set original = TRUE.
#> Rows: 188 Columns: 3
#> ── Column specification ────────────────────────────────────────────────────────
#> Delimiter: "\t"
#> chr (1): country
#> dbl (2): ccode, area
#> 
#> ℹ Use `spec()` to retrieve the full column specification for this data.
#> ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
#> # A tibble: 188 × 3
#>    ccode country                area
#>    <dbl> <chr>                 <dbl>
#>  1     2 United States       9158960
#>  2    20 Canada              9093510
#>  3    31 Bahamas, The          10010
#>  4    40 Cuba                 107400
#>  5    41 Haiti                 27560
#>  6    42 Dominican Republic    48320
#>  7    51 Jamaica               10830
#>  8    52 Trinidad and Tobago    5130
#>  9    53 Barbados                430
#> 10    54 Dominica                750
#> # ℹ 178 more rows

Keeping the index fresh

The index is downloaded once and cached locally (see tools::R_user_dir("psreplicate", "cache")), then auto-refreshed once the cache is more than a day old. Force an update sooner with:

refresh_index(force = TRUE)

Caveats worth knowing