| Title: | Access and Analyze Data from the Item Response Warehouse |
|---|---|
| Description: | Find, download, and analyze datasets from the Item Response Warehouse, a harmonized collection of item response data from educational and psychological measurement described in Nadela et al. (2026) <doi:10.59863/cijg4549>. Functions search tables by metadata, fetch them in a common long format, reshape between long and wide layouts, simulate item response data, and compare the predictive accuracy of fitted models with the InterModel Vigorish. |
| Authors: | Hansol Lee [aut, cph], Michael Hardy [aut, cph], Ben Domingue [aut, cre, cph] |
| Maintainer: | Ben Domingue <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 1.3.1.9001 |
| Built: | 2026-10-20 15:25:31 UTC |
| Source: | https://github.com/itemresponsewarehouse/rpkg |
A dataset of item difficulty estimates and associated standard errors compiled from a curated subset of IRW datasets.
Used internally by irw_simu_diff() to generate empirically grounded item parameters for simulation.
diff_longdiff_long
A data frame with N rows and 4 variables:
Dataset identifier (character). Indicates the source dataset in IRW.
Item identifier (character). A label for each item.
Estimated item difficulty (numeric).
Standard error of the difficulty estimate (numeric).
This pool includes binary-response items from IRW datasets that passed basic quality checks—
specifically, datasets with less than 50% missing data and without repeated or duplicate responses.
It is accessible to users and is used as the default source in irw_simu_diff().
Curated and compiled by the IRW package authors from selected datasets in the IRW repository.
irw_fetch() and irw_itemtext() keep each table they download in this
folder, so later sessions do not export it again – every export counts
against the Redivis 30-day export cap.
irw_cache_dir()irw_cache_dir()
The folder is the IRW_CACHE_DIR environment variable if set, otherwise
tools::R_user_dir("irw", "cache") (e.g. ~/.cache/R/irw on Linux). The
Python package reads and writes the same files, but its default folder is
~/.cache/irw; to share one cache between the two languages, set
IRW_CACHE_DIR to the same folder for both.
Switch the cache off with options(irw.cache = FALSE) for a session, or
IRW_CACHE=0 for all of them.
Path to the cache folder (it may not exist yet).
irw_cache_info(), irw_clear_cache()
irw_fetch() and irw_itemtext() keep each table they download so that
later sessions do not export it again. A copy is used for as long as the
table is unchanged on Redivis, and replaced when it changes. See
irw_cache_dir() for where the files are and how to switch this off.
irw_cache_info()irw_cache_info()
A tibble with one row per cached file: kind ("tables" or
"itemtext"), table, hash (Redivis' content hash, which decides
whether the copy is current), version (the dataset release it was
fetched from), reference, size_mb, fetched_at and path.
info <- irw_cache_info() sum(info$size_mb)info <- irw_cache_info() sum(info$size_mb)
Summarize basic response diagnostics in IRW data, including items with a single observed response category and sparse categories in polytomous items.
irw_check_resp(x, min_count = 5L, min_prop = 0.01, resp_col = "resp")irw_check_resp(x, min_count = 5L, min_prop = 0.01, resp_col = "resp")
x |
A data frame in long format with columns |
min_count |
Minimum count for a category before it is considered
sparse (only used when |
min_prop |
Minimum within-item proportion for a category before it
is considered sparse (only used when |
resp_col |
Character string giving the response column to inspect when
|
When x is long-format (with columns id, item, resp),
diagnostics are recomputed using min_count and min_prop. When
x is the wide-format result of irw_long2resp(), any attached
diagnostics from check_resp = TRUE are returned directly.
A response category is treated as "sparse" if it has fewer than
min_count observed responses OR a within-item proportion smaller than
min_prop.
A list with two elements:
single_category_items (character vector of item IDs) and
sparse_category_items (named list of data frames with columns
resp, count, prop).
Delete cached tables
irw_clear_cache(table = NULL)irw_clear_cache(table = NULL)
table |
Character vector of table names to remove, matched
case-insensitively; a table's item text goes with it. |
Invisibly, the number of bytes freed.
irw_cache_info(), irw_cache_dir()
Returns the names of every IRW table in one collection, so they can be passed
straight to irw_fetch(), irw_save_bibtex() or any other vectorised
accessor.
irw_collection(name, quiet = FALSE)irw_collection(name, quiet = FALSE)
name |
Character. A single collection name, e.g. |
quiet |
Logical. Suppress the definition/coverage message. |
Prints the collection's definition and, when the collection does not cover
the whole warehouse, says so — see the Coverage section of
irw_collections(). Suppress with quiet = TRUE.
A sorted character vector of table names.
irw_collections(), irw_filter()
tabs <- irw_collection("depression") irw_save_bibtex(head(tabs, 3), output_file = file.path(tempdir(), "depression.bib")) # Compose with the numeric filters irw_filter(collection = "depression", n_participants = c(500, Inf)) # Cross-collection: math assessments administered in booklets intersect(irw_collection("math"), irw_collection("multistage"))tabs <- irw_collection("depression") irw_save_bibtex(head(tabs, 3), output_file = file.path(tempdir(), "depression.bib")) # Compose with the numeric filters irw_filter(collection = "depression", n_participants = c(500, Inf)) # Cross-collection: math assessments administered in booklets intersect(irw_collection("math"), irw_collection("multistage"))
The long membership table: one row per (table, collection) pair, with the
basis on which that membership was decided — a rule expression, or a
curator. Use this to ask the inverse question: what collections is a given
table in?
irw_collection_members(tables = NULL, collection = NULL)irw_collection_members(tables = NULL, collection = NULL)
tables |
Optional character vector. Restrict to these table names. |
collection |
Optional character vector. Restrict to these collections. |
A tibble with columns table, collection, basis.
In the exact-instrument collections (phq9, gad7, rses, cesd,
dass21, panas, tipi, pcl5, gse, erq, mspss, sd3), basis
starts with how the table was identified as that instrument:
wordingThe study's own item text matches the instrument. Identity is observed.
suppliedIRW identified the instrument and supplied its canonical wording, so a wording match only confirms that identification. Identity is asserted.
nameThere is no usable English item text; only the table's metadata names the instrument.
A note may follow after "; ": "supplied; subscale: anxiety (7/21)" for a
table holding one whole subscale, "name; partial: 18/20 items" for one
holding most of the scale. For the strictly verified set, keep rows whose
basis starts with "wording", not rows equal to it.
irw_collections(), irw_collection()
irw_collection_members(tables = "frac20") irw_collection_members(collection = "q_matrix") # PHQ-9 tables whose own item text was checked against the instrument m <- irw_collection_members(collection = "phq9") m[startsWith(m$basis, "wording"), ]irw_collection_members(tables = "frac20") irw_collection_members(collection = "q_matrix") # PHQ-9 tables whose own item text was checked against the instrument m <- irw_collection_members(collection = "phq9") m[startsWith(m$basis, "wording"), ]
Returns the collection registry: one row per collection, with its kind, definition, the rule that produced it, and how complete its coverage is.
irw_collections(kind = NULL)irw_collections(kind = NULL)
kind |
Optional character vector. Filter to |
Collections are labelled groupings of IRW tables — study designs (rct,
clustered, q_matrix), instrument families (big_five, promis), exact
instruments (phq9, gad7, rses, ...) and constructs (depression,
math). A table can belong to any number of them.
A tibble, one row per collection.
coverage says how much of the warehouse the collection's rule actually
searched, and it matters when you need "all" of something:
metadata-completeThe rule read irw_metadata(), so it saw every
documented table. Note this is not the same as the whole warehouse —
irw_metadata() itself has gaps.
tagged-subset-onlyThe rule read the construct name tag, which
is filled for only about half of documented tables, and far fewer in the
newer warehouses. The definition states the exact count searched. These collections are biased toward older tables and should
not be described as exhaustive.
curated-onlyEvery member was chosen by hand. The exact-instrument
collections are of this kind; see irw_collection_members() for how each
of their members was identified.
irw_collection(), irw_collection_members(), irw_filter()
irw_collections() irw_collections(kind = "instrument")irw_collections() irw_collections(kind = "instrument")
Conjoint tables (source = "conj") have one row per respondent, task
and profile: id, task, profile, the outcomes
(choice, rating, and any choice_<name> or
rating_<name>), the profile's attribute levels in attr_*
columns, and respondent covariates in cov_*. There is no item
or resp, because every profile is a new random bundle of attributes.
irw_conj_long(df, outcomes = NULL)irw_conj_long(df, outcomes = NULL)
df |
A conjoint table, as returned by
|
outcomes |
Optional character vector of outcome columns to keep. Default: all of them. |
This function stacks the outcomes into the core layout so that tools built
for id/item/resp can be used: item is the name of
the outcome question ("choice", "rating", ...), resp its
value, and task, profile and the attributes become
trial_ columns. Rows with a missing outcome are dropped.
A data frame with columns id, item, resp,
trial_task, trial_profile, trial_attr_*, and the
remaining columns of df.
## Not run: d <- irw_fetch("kreps_2020_covid_vaccine", source = "conj") long <- irw_conj_long(d) table(long$item) ## End(Not run)## Not run: d <- irw_fetch("kreps_2020_covid_vaccine", source = "conj") long <- irw_conj_long(d) table(long$item) ## End(Not run)
Many covariates ship as bare codes – cov_gender in {1, 2} – whose
meaning was recorded in the source file (an SPSS or Stata value label) but
is not in the IRW table, and the meaning differs from table to table:
cucchi_2018_rfq codes 1 = female, rowe_2016_cfs_strain
1 = male. This returns the source's own labels, one row per code, from
irw_meta's covariate_labels table. It does not touch the response
data, and irw_fetch() output is unchanged.
irw_covariate_labels(table)irw_covariate_labels(table)
table |
Character vector of IRW table names (case-insensitive). |
A tibble with character columns table, covariate,
code, label, one row per code, sorted by table, covariate
and code. code is the shipped value written as text (a shipped
1.0 is "1"). label is the source's wording, verbatim
and not harmonised across tables, or the literal
"[institution name withheld]" where the codes name institutions.
Only codes that occur in the shipped column are listed, and a covariate
may be partly covered. Zero rows, with a message, when IRW has no labels
for the table.
If the irw_meta version in use has no covariate_labels table (an
older or pinned version), this is an error of class
irw_covariate_labels_unavailable, not an empty result, so it cannot
be mistaken for "no labelled covariates".
irw_covariates, whose labels = TRUE applies
these labels.
irw_covariate_labels("cucchi_2018_rfq")irw_covariate_labels("cucchi_2018_rfq")
Reduces IRW long-format data to one row per id, keeping the columns
that describe the person rather than the response. Optionally aligns those
rows to the row order of a wide response matrix, which is what most
psychometric packages need when a grouping variable is passed alongside a
response matrix.
irw_covariates(df, cols = NULL, align = NULL, labels = FALSE, table = NULL)irw_covariates(df, cols = NULL, align = NULL, labels = FALSE, table = NULL)
df |
A data frame in IRW long format, containing an |
cols |
Character vector of person-level columns to extract. Defaults to
|
align |
Optional. A data frame with an |
labels |
Opt in to source value labels (ben-domingue/irw#1775).
|
table |
The IRW table |
irw_long2resp() keeps only id, item, and the response
column, so person-level covariates are dropped and the row order of its
result is not sorted. Aligning a covariate to that result by hand requires a
match() on id, and getting it wrong silently misassigns people
to groups. Passing the wide result as align does that match for you.
When cols is NULL, the person-level columns are detected
automatically: every column other than id and the response-level
columns (item, resp, rater, rt, text,
date, source_table) that takes exactly one value within every
id. A column with a value for some of a person's rows and NA
for others counts as varying and is not selected. Note that wave is
treated as person-level only when each person appears in a single wave.
A data frame with one row per id and columns id
followed by the person-level covariates. When align is supplied,
rows follow that order and ids not present in df yield NA
rows.
irw_long2resp, irw_covariate_labels
df <- data.frame( id = c(1, 1, 2, 2), item = c("i1", "i2", "i1", "i2"), resp = c(1, 0, 1, 1), cov_group = c("A", "A", "B", "B"), stringsAsFactors = FALSE ) irw_covariates(df) # Aligned to the row order of a wide response matrix wide <- irw_long2resp(df, id_density_threshold = NULL) irw_covariates(df, align = wide) # With the source's value labels (cov_gender 1/2 -> female/male) if (irw_has_credentials()) { df <- irw_fetch("cucchi_2018_rfq") irw_covariates(df, labels = TRUE, table = "cucchi_2018_rfq") }df <- data.frame( id = c(1, 1, 2, 2), item = c("i1", "i2", "i1", "i2"), resp = c(1, 0, 1, 1), cov_group = c("A", "A", "B", "B"), stringsAsFactors = FALSE ) irw_covariates(df) # Aligned to the row order of a wide response matrix wide <- irw_long2resp(df, id_density_threshold = NULL) irw_covariates(df, align = wide) # With the source's value labels (cov_gender 1/2 -> female/male) if (irw_has_credentials()) { df <- irw_fetch("cucchi_2018_rfq") irw_covariates(df, labels = TRUE, table = "cucchi_2018_rfq") }
Inverse of irw_recode(): maps codes such as I0001 back to the
original identifier values using the recode key.
irw_decode(x, key = NULL, cols = NULL)irw_decode(x, key = NULL, cols = NULL)
x |
A data frame returned by |
key |
A recode key as returned by |
cols |
Character vector of columns to decode. Defaults to all columns
present in both |
Works on long-format data (columns named in the key are decoded in place) and
on the wide output of irw_long2resp(), where item codes appear as
column names. irw_long2resp() prefixes item columns with
item_; that prefix is handled and preserved. Values or column names
that are not found in the key are left untouched.
x with codes replaced by the original values and the
"irw_recode_key" attribute removed.
Downloads a specified dataset table from the IRW datasource.
irw_download( table_name, path, overwrite = FALSE, source = "core", sim = FALSE, comp = FALSE, nom = FALSE )irw_download( table_name, path, overwrite = FALSE, source = "core", sim = FALSE, comp = FALSE, nom = FALSE )
table_name |
A character string specifying the name of the Redivis table to download. |
path |
A string giving the file path the data are saved to. There is
no default: name the file yourself, e.g. |
overwrite |
Logical. Whether to overwrite an existing file. |
source |
Character. The data family: |
sim |
Deprecated. Use |
comp |
Deprecated. Use |
nom |
Deprecated. Use |
A message confirming the file download location.
Retrieves one or more tables from IRW and returns them as tibbles.
This downloads every row of each table and counts against the Redivis export
quota; if you only need the item or response value sets, or per-item counts
and ranges, use irw_table_sets(), which answers with a server-side query.
If the table includes a character resp column, the function attempts to
coerce it into numeric. Strings like "NA", "", and NA are treated as missing values.
A warning is issued only if other non-numeric values are encountered.
irw_fetch( name, source = "core", dedup = FALSE, sim = FALSE, comp = FALSE, nom = FALSE, resp = FALSE )irw_fetch( name, source = "core", dedup = FALSE, sim = FALSE, comp = FALSE, nom = FALSE, resp = FALSE )
name |
Character vector of one or more table names (IRW table IDs). |
source |
Character. The data family: |
dedup |
Logical, optional. If TRUE, deduplicates responses based on timing variables. Defaults to FALSE.
If a |
sim |
Deprecated. Use |
comp |
Deprecated. Use |
nom |
Deprecated. Use |
resp |
Logical, optional. If TRUE, returns response matrix via |
Each table downloaded is also kept on disk (see irw_cache_dir()) and reused
by later fetches, in this session or another, for as long as the table is
unchanged on Redivis; the Python package shares the same copies. Switch this
off with options(irw.cache = FALSE) or IRW_CACHE=0.
A table the IRW found through another collection, such as openESM, prints
that collection's note and citation once per session per collection.
Silence it with options(irw.source_note = FALSE) or IRW_SOURCE_NOTE=0.
If a single name is provided, returns a tibble. If multiple, returns a named list of tibbles (or error messages, if retrieval failed).
irw_table_sets() for value sets and summaries without a download;
irw_cache_info() for the tables kept on disk.
# Main IRW data irw_fetch("environment_ltm") # Deduplicated irw_fetch("pks_probability", dedup = TRUE) # Simulation data irw_fetch("gilbert_meta_3", source = "sim") # Competition data irw_fetch("collegefb_2021and2022", source = "comp")# Main IRW data irw_fetch("environment_ltm") # Deduplicated irw_fetch("pks_probability", dedup = TRUE) # Simulation data irw_fetch("gilbert_meta_3", source = "sim") # Competition data irw_fetch("collegefb_2021and2022", source = "comp")
Returns the names of datasets in the Item Response Warehouse (IRW) that match user-specified metadata, tag values, variable presence, and license criteria.
irw_filter( n_responses = NULL, n_categories = NULL, n_participants = NULL, n_items = NULL, responses_per_participant = NULL, responses_per_item = NULL, density = c(0.5, 1), var = NULL, age_range = NULL, child_age__for_child_focused_studies_ = NULL, construct_type = NULL, construct_name = NULL, sample = NULL, measurement_tool = NULL, item_format = NULL, primary_language_s_ = NULL, longitudinal = NULL, n_actors = NULL, n_respondents = NULL, n_attributes = NULL, outcome = NULL, country = NULL, domain = NULL, choice_object = NULL, source = "core", comp = FALSE, sim = FALSE, nom = FALSE, license = NULL, collection = NULL )irw_filter( n_responses = NULL, n_categories = NULL, n_participants = NULL, n_items = NULL, responses_per_participant = NULL, responses_per_item = NULL, density = c(0.5, 1), var = NULL, age_range = NULL, child_age__for_child_focused_studies_ = NULL, construct_type = NULL, construct_name = NULL, sample = NULL, measurement_tool = NULL, item_format = NULL, primary_language_s_ = NULL, longitudinal = NULL, n_actors = NULL, n_respondents = NULL, n_attributes = NULL, outcome = NULL, country = NULL, domain = NULL, choice_object = NULL, source = "core", comp = FALSE, sim = FALSE, nom = FALSE, license = NULL, collection = NULL )
n_responses |
Numeric vector of length 1 or 2. Filters datasets by total number of responses.
|
n_categories |
Numeric vector of length 1 or 2. Filters by number of unique response categories. |
n_participants |
Numeric vector of length 1 or 2. Filters by number of unique participants ( |
n_items |
Numeric vector of length 1 or 2. Filters by number of unique items. |
responses_per_participant |
Numeric vector of length 1 or 2. Filters by average responses per participant. |
responses_per_item |
Numeric vector of length 1 or 2. Filters by average responses per item. |
density |
Numeric vector of length 1 or 2, or
|
var |
Character vector. Filters datasets by presence of variables.
|
age_range |
Character vector. Filters by participant age group (e.g., |
child_age__for_child_focused_studies_ |
Character vector. Filters by child age subgroup.
See |
construct_type |
Character vector. Filters by high-level construct category
(e.g., |
construct_name |
Character vector. Filters by specific construct (e.g., |
sample |
Character vector. Filters by sample type or recruitment method
(e.g., |
measurement_tool |
Character vector. Filters by instrument type (e.g., |
item_format |
Character vector. Filters by item format (e.g., |
primary_language_s_ |
Character vector. Filters by language used (e.g., |
longitudinal |
Logical or
|
n_actors |
Numeric vector of length 1 or 2. Competition-only filter for the
number of actors. Only used when |
n_respondents |
Numeric vector of length 1 or 2. Conjoint-only: number of
respondents. Only used when |
n_attributes |
Numeric vector of length 1 or 2. Conjoint-only: number of attributes varied on each profile. |
outcome |
Character, |
country |
Character vector of ISO 3166 alpha-2 codes (e.g. |
domain |
Character vector. Conjoint-only: what the study is about, its
setting rather than the attribute it manipulates (a candidate conjoint that
varies gender is |
choice_object |
Character vector. Conjoint-only: what one profile
represents, one value per table: |
source |
Character. The data family: |
comp |
Deprecated. Use |
sim |
Deprecated. Use |
nom |
Deprecated. Use |
license |
Character vector. Filters datasets by license (e.g., |
collection |
Character vector. Filters datasets by collection membership
(e.g., |
Filtering is based on:
Numeric metadata: number of responses, participants, items, etc.
Tag metadata: e.g., construct type, sample, measurement tool
Variable presence: e.g., rt, wave, cov_
License type: e.g., "CC BY 4.0", "CC0 1.0"
To explore available metadata:
summary(irw_metadata()) — numeric summaries (e.g., n_responses, density)
irw_tags() — full tag metadata table (1 row per dataset)
irw_tag_options("column_name") — valid values (with counts) for any tag column
irw_license_options() — available license values with frequencies
irw_collections() — the 22 collections, with kind, definition and coverage
irw_collection("name") — the table names in one collection
Tag-based metadata (e.g., construct_type, sample, item_format) can be passed
directly as named arguments. See the parameter list below for supported tag columns.
Tag filters are available for source = "core" and source = "nom"; "comp"
and "sim" have no tags by design and reject them.
A sorted character vector of dataset names that match all specified filters, or character(0) if no match is found.
# Numeric filters irw_filter(n_responses = c(1000, Inf), n_items = c(10, 50)) irw_filter(n_participants = c(500, Inf), density = c(0.3, 0.9)) # Variable presence irw_filter(var = "rt") irw_filter(var = c("wave", "cov_"), density = NULL) # Tag metadata filtering irw_filter(construct_type = "Affective/mental health", sample = "Educational") irw_tag_options("construct_type") # view tag values # License filtering irw_license_options() irw_filter(license = "CC BY 4.0") # Collection filtering irw_collections() # what exists irw_filter(collection = "rct") irw_filter(collection = "depression", n_participants = c(500, Inf)) irw_filter(collection = c("rct", "response_time")) # union, not intersection # Filter by response category complexity irw_filter(n_categories = 2, density = NULL) # binary irw_filter(n_categories = c(3, 5), density = NULL) # small multi-category irw_filter(n_categories = c(10, Inf), density = NULL) # large category sets irw_filter(source = "sim", n_items = c(10, Inf)) irw_filter(source = "comp", n_actors = c(2, 10)) irw_filter(source = "conj", outcome = "rating", country = c("US", "GB")) irw_filter(source = "conj", domain = "immigration_asylum") # the immigration conjoints irw_filter(source = "conj", domain = c("candidate_choice", "parties_platforms"), choice_object = "person")# Numeric filters irw_filter(n_responses = c(1000, Inf), n_items = c(10, 50)) irw_filter(n_participants = c(500, Inf), density = c(0.3, 0.9)) # Variable presence irw_filter(var = "rt") irw_filter(var = c("wave", "cov_"), density = NULL) # Tag metadata filtering irw_filter(construct_type = "Affective/mental health", sample = "Educational") irw_tag_options("construct_type") # view tag values # License filtering irw_license_options() irw_filter(license = "CC BY 4.0") # Collection filtering irw_collections() # what exists irw_filter(collection = "rct") irw_filter(collection = "depression", n_participants = c(500, Inf)) irw_filter(collection = c("rct", "response_time")) # union, not intersection # Filter by response category complexity irw_filter(n_categories = 2, density = NULL) # binary irw_filter(n_categories = c(3, 5), density = NULL) # small multi-category irw_filter(n_categories = c(10, Inf), density = NULL) # large category sets irw_filter(source = "sim", n_items = c(10, Inf)) irw_filter(source = "comp", n_actors = c(2, 10)) irw_filter(source = "conj", outcome = "rating", country = c("US", "GB")) irw_filter(source = "conj", domain = "immigration_asylum") # the immigration conjoints irw_filter(source = "conj", domain = c("candidate_choice", "parties_platforms"), choice_object = "person")
Returns the names of competition tables that match user-specified criteria. Competition filtering uses:
Numeric metadata: n_responses, n_actors
License: via comp_biblio (Derived_License)
irw_filter_comp(n_responses = NULL, n_actors = NULL, license = NULL)irw_filter_comp(n_responses = NULL, n_actors = NULL, license = NULL)
n_responses |
Numeric vector length 1 or 2. Filters by number of responses.
|
n_actors |
Numeric vector length 1 or 2. Filters by number of actors. |
license |
Character vector. Filters by license (e.g., "CC BY 4.0").
See |
Notes:
Competition datasets do not have tags or item text metadata.
Competition metadata table names are stored in lowercase.
A sorted character vector of competition table names (lowercase),
or character(0) if no match is found.
Shows which Redivis version each IRW dataset is being read at, and whether
that version is pinned for the session or is simply the current release.
Record these tags to make an analysis reproducible; replay them with
irw_set_version.
irw_get_version(dataset = NULL)irw_get_version(dataset = NULL)
dataset |
Optional character vector of dataset names to report on. Defaults to every IRW dataset. |
A data frame with columns dataset, version, and
pinned.
irw_set_version, irw_reset_version
irw_get_version() irw_get_version("item_response_warehouse")irw_get_version() irw_get_version("item_response_warehouse")
Fetching and listing IRW tables needs no Redivis login: the warehouse is
public, and redivis 0.12.14 and later send those requests
anonymously. A login is still needed for the server-side queries behind
irw_table_sets, and for every warehouse call on an older
redivis, which authenticates unconditionally. In an interactive
session irw opens the browser login when one is needed; in a script or other
non-interactive session it stops with instructions instead. This function
reports whether the redivis client and a login are already in place,
so code can skip the calls that would otherwise stop.
irw_has_credentials()irw_has_credentials()
TRUE if redivis is installed and credentials are
available (a REDIVIS_API_TOKEN environment variable or a cached
login), otherwise FALSE.
irw_has_credentials()irw_has_credentials()
Compare two sets of predicted probabilities for the same binary outcomes. The IMV expresses how much better the second model predicts than the first, on the scale of a weighted coin: each model's geometric mean likelihood is converted to the weight of a coin with the same entropy, and the IMV is the proportional gain in that weight.
irw_imv(data, p1, p2, resp = "resp", eps = 1e-06)irw_imv(data, p1, p2, resp = "resp", eps = 1e-06)
data |
A data frame holding the outcomes and both sets of predicted
probabilities, or a numeric vector of binary outcomes. When |
p1 |
Predictions from the baseline model: a column name in |
p2 |
Predictions from the comparison model, in the same form as
|
resp |
The binary outcome. Ignored when |
eps |
Clamping tolerance for predicted probabilities. Default 1e-6. |
An IMV of 0 means the two models predict equally well; 0.05 means model 2
is equivalent to a coin 5\
is not symmetric: irw_imv(data, "p1", "p2") is the gain from moving
from p1 to p2, and swapping the arguments does not simply
flip the sign.
Predicted probabilities are clamped to [eps, 1 - eps] before the
likelihoods are computed, so predictions of exactly 0 or 1 do not produce
an infinite log-likelihood.
The computation is imv.binary from the imv
package; irw_imv() adds the data-frame interface and input checks.
Out-of-sample predictions are the intended use: comparing in-sample predictions will favour the more flexible model by construction. The "Comparing Models Out of Sample with the IMV" article works through a cross-validated comparison of a Rasch model against a 2PL.
A single numeric value: the proportional gain in coin weight from
p1 to p2.
Domingue, B. W., Rahal, C., Faul, J., Freese, J., Kanopka, K., Rigos, A., Stenhaug, B., & Tripathi, A. (2025). The InterModel Vigorish (IMV) as a flexible and portable approach for quantifying predictive accuracy with binary outcomes. PLOS ONE, 20(3), e0316491. doi:10.1371/journal.pone.0316491
irw_predict for producing p1 and p2
from fitted mirt models.
set.seed(1) truth <- rbinom(500, 1, 0.7) # A model that knows the base rate beats one that guesses at random. irw_imv(truth, p1 = rep(0.5, 500), p2 = rep(0.7, 500))set.seed(1) truth <- rbinom(500, 1, 0.7) # A model that knows the base rate beats one that guesses at random. irw_imv(truth, p1 = rep(0.5, 500), p2 = rep(0.7, 500))
Prints information about the IRW datasets or a specific table.
irw_info( table_name = NULL, details = FALSE, source = "core", comp = FALSE, sim = FALSE, nom = FALSE )irw_info( table_name = NULL, details = FALSE, source = "core", comp = FALSE, sim = FALSE, nom = FALSE )
table_name |
Optional. Table name to describe; if |
details |
Logical. When |
source |
Character. The data family: |
comp |
Deprecated. Use |
sim |
Deprecated. Use |
nom |
Deprecated. Use |
If table_name is NULL, shows combined totals across all IRW datasets.
Use details = TRUE to also print a per-dataset breakdown (main IRW only).
If a table name is provided, shows details for that table.
Invisibly returns NULL.
irw_info() # Combined totals irw_info(details = TRUE) # Combined + per-dataset breakdown irw_info("frac20") # Specific IRW table irw_info("t20_hyper", source = "comp") # Competition table irw_info("gilbert_meta_3", source = "sim")irw_info() # Combined totals irw_info(details = TRUE) # Combined + per-dataset breakdown irw_info("frac20") # Specific IRW table irw_info("t20_hyper", source = "comp") # Competition table irw_info("gilbert_meta_3", source = "sim")
Returns item-level text metadata for a given IRW table, if available.
If no item text table is available for the specified table, the function returns NULL
and prints a message.
irw_itemtext(table_name)irw_itemtext(table_name)
table_name |
Character. The name of the IRW table to look up (e.g., |
A tibble containing item text metadata, or NULL if unavailable.
IRW item text is reconstructed from published articles, codebooks, and
supplementary materials using a largely automated pipeline with partial human
review, and is provided for research purposes only. We make no
guarantee that the text is accurate, complete, or correctly aligned with the
item identifiers in the corresponding IRW response data; the original
source document is always authoritative. Users are responsible for verifying
item text against that source before drawing substantive conclusions.
Documented discrepancies are listed at
https://itemresponsewarehouse.org/itemtext_issues.html.
Note also that the licenses recorded for IRW response data do not extend to
the instruments themselves. Inclusion of item text here implies no license to
reuse an instrument; copyright and related rights remain with the original
rights holders, and users are responsible for obtaining any permissions their
intended use requires. The exception is a table whose wording its source
released under an open licence: that licence is printed after the fetch and
is returned by irw_itemtext_licence.
irw_itemtext("gilbert_meta_49")irw_itemtext("gilbert_meta_49")
Most IRW item text carries no licence of its own: the response-data licence
does not extend to the instrument, and inclusion implies no licence to reuse
it. A minority of tables are different: their wording was released by its
source under an open licence (CC BY-SA 4.0, CC BY-NC 4.0, ...), and IRW
republishes it under that licence, with attribution and a note of its
changes. This function returns that record for one table, or NULL
when the wording carries no licence of its own.
irw_itemtext_licence(table_name)irw_itemtext_licence(table_name)
table_name |
Character. The IRW table name (case-insensitive). |
The record is the IRW repository's itemtext/itemtext_licences.csv,
fetched once per session. irw_itemtext() prints the same line after
fetching a licensed table.
A one-row data frame with columns table, licence,
licence_url, attribution, changes and basis,
or NULL if the wording carries no licence of its own (or the record
could not be fetched, in which case a warning says so).
irw_itemtext_licence("iowa_gambling_task")irw_itemtext_licence("iowa_gambling_task")
Returns a data frame showing the number of datasets associated with each license.
irw_license_options(source = "core", comp = FALSE, sim = FALSE, nom = FALSE)irw_license_options(source = "core", comp = FALSE, sim = FALSE, nom = FALSE)
source |
Character. The data family: |
comp |
Deprecated. Use |
sim |
Deprecated. Use |
nom |
Deprecated. Use |
A data.frame with 'license' and 'count' columns.
Returns a character vector of IRW table names for which item text is available.
irw_list_itemtext_tables()irw_list_itemtext_tables()
A sorted character vector of IRW table names with item text metadata.
IRW item text is reconstructed from published articles, codebooks, and
supplementary materials using a largely automated pipeline with partial human
review, and is provided for research purposes only. We make no
guarantee that the text is accurate, complete, or correctly aligned with the
item identifiers in the corresponding IRW response data; the original
source document is always authoritative. Users are responsible for verifying
item text against that source before drawing substantive conclusions.
Documented discrepancies are listed at
https://itemresponsewarehouse.org/itemtext_issues.html.
Note also that the licenses recorded for IRW response data do not extend to the instruments themselves. Inclusion of item text here implies no license to reuse an instrument; copyright and related rights remain with the original rights holders, and users are responsible for obtaining any permissions their intended use requires.
irw_list_itemtext_tables()irw_list_itemtext_tables()
Retrieves a summary of available tables in the IRW database, including their name, number of rows, and variable count, sorted alphabetically by table name.
irw_list_tables(source = "core", sim = FALSE, comp = FALSE, nom = FALSE)irw_list_tables(source = "core", sim = FALSE, comp = FALSE, nom = FALSE)
source |
Character. The data family: |
sim |
Deprecated. Use |
comp |
Deprecated. Use |
nom |
Deprecated. Use |
A data frame with the following columns:
name |
The name of the table, sorted alphabetically. |
numRows |
The number of rows in the table. |
variableCount |
The number of variables in the table. |
irw_list_tables() # Main IRW database irw_list_tables(source = "sim") # Simulation dataset irw_list_tables(source = "comp") # Competition datasetirw_list_tables() # Main IRW database irw_list_tables(source = "sim") # Simulation dataset irw_list_tables(source = "comp") # Competition dataset
Converts an IRW-compliant dataset from long format to wide format while handling optional metadata elements and filtering by wave.
irw_long2resp( df, wave = NULL, id_density_threshold = 0.1, agg_method = NULL, check_resp = FALSE, resp_col = "resp" )irw_long2resp( df, wave = NULL, id_density_threshold = 0.1, agg_method = NULL, check_resp = FALSE, resp_col = "resp" )
df |
A data frame containing IRW-compliant item response data in long format. |
wave |
(Optional) A numeric value specifying which wave to filter.
If the dataset does not have a |
id_density_threshold |
A numeric value between |
agg_method |
A string specifying how to handle multiple
|
check_resp |
Logical; if |
resp_col |
Character string giving the column in |
This function applies a default sparsity filter with a threshold
of 0.1 for id density to avoid excessive sparsity.
Users can disable filtering by setting id_density_threshold = NULL.
If check_resp = TRUE, the function will run a basic diagnostic
using default thresholds (min_count = 5, min_prop = 0.01),
attach the results as an attribute "resp_checks" on returned object,
and add a short NOTE with counts of flagged items.
A response category is considered sparse if it has fewer than
min_count responses OR a within-item proportion smaller than
min_prop. For more control, use irw_check_resp() directly.
A data frame in wide format where rows represent id values
and columns represent item_* responses. The column used for
response values is recorded in the "resp_col" attribute.
If check_resp = TRUE, an attribute "resp_checks"
is attached:
single_category_items: character vector of item IDs
with only one observed category.
sparse_category_items: named list; each element is
a data.frame with sparse categories for that item
(columns: resp, count, prop).
Identifies and merges tables that share the same DOI or, if DOI is missing, the same BibTex entry. If tables do not have the same structure, only those with identical structures will be merged. This function performs several consistency checks before merging, and prompts the user for confirmation if inconsistencies are found.
irw_merge(table_name, add_source_column = TRUE)irw_merge(table_name, add_source_column = TRUE)
table_name |
A character string specifying the name of the table to find merge candidates for. |
add_source_column |
A boolean value indicating whether to add the |
irw_merge() performs the following checks before proceeding with the merge:
Number of Respondents Check:
The function checks if the number of respondents is consistent across all tables.
If the number of respondents is consistent, the merge proceeds.
If the number of respondents is inconsistent across tables, a WARNING message is displayed:
=== WARNING === The number of respondents (N) is not consistent across tables. Merging tables with inconsistent N respondents may require human judgment.
ID Consistency Check:
Checks if all tables share the same set of IDs.
Checks if the IDs form a strict sequence (e.g., 1, 2, 3, ...).
If IDs are not consistent across tables, a NOTE message is displayed:
=== NOTE: === - IDs do not match across tables. - IDs are sequential (1...n). You may need to manually verify the IDs, as there could be multiple studies with different subjects, where IDs are the same in both studies.
Item Column Overlap Check:
Verifies that there is no overlap of item columns across tables.
If overlapping items are found, a NOTE message is displayed:
=== NOTE: === - There are items that overlap across tables.
Tables whose bibliography entry is missing (recorded as "NA" in the biblio
table) are never treated as merge candidates for one another.
In a non-interactive session the confirmation prompts cannot be answered, so the merge proceeds by default; the checks above are still reported as messages.
A merged data frame containing all tables with the same DOI or BibTex, or NULL if no merge candidates are found.
Fetches the metadata table from Redivis and returns it as a tibble. Automatically checks for updates and refreshes only when needed.
irw_metadata(source = "core", sim = FALSE, comp = FALSE, nom = FALSE)irw_metadata(source = "core", sim = FALSE, comp = FALSE, nom = FALSE)
source |
Character. The data family: |
sim |
Deprecated. Use |
comp |
Deprecated. Use |
nom |
Deprecated. Use |
Each source has its own columns. For source = "conj" a row is one
conjoint experiment: n_respondents, n_rows, n_tasks,
n_profiles, n_attributes, outcomes,
n_optout_tasks, and the design facts country,
display_language, label_language, restrictions
(none, yes, observed or unknown),
restrictions_note, task_source and profile_source
(recorded or inferred from row order), and the topic tags
domain (what the study is about; one or more values joined with
";", primary first) and choice_object (what one profile
represents). Both are filters in irw_filter, which documents
their vocabularies.
For source = "rank" a row is one rankings table: the counts
n_respondents, n_rows, n_tasks, n_items,
max_resp (highest position marked) and n_duplicate_marks,
and the design record (method, seats, n_positions,
n_candidates, n_ballots_cast, n_ballots_with_marks,
jurisdiction, date, office, ...), whose codes are
documented in the irw repo's data/rankings/README.md.
A tibble containing metadata information.
Attach per-response predicted probabilities from a fitted unidimensional,
dichotomous mirt model to long-format IRW data. This is the piece
needed to compare models out of sample with irw_imv.
irw_predict(model, resp, newdata = NULL, ability = "EAP")irw_predict(model, resp, newdata = NULL, ability = "EAP")
model |
A fitted unidimensional mirt model with dichotomous items. |
resp |
The wide response frame used to fit |
newdata |
(Optional) A long-format data frame with columns |
ability |
Scoring method passed to |
Person abilities are taken from the fit itself with
mirt::fscores(), so row i of the scored matrix is person
resp$id[i]. Passing the wide frame that produced the fit is what
lets the function recover that mapping; supplying ids in a different order
than the rows given to mirt::mirt() would silently mispair people
with abilities.
Probabilities come from mirt::probtrace(), so any dichotomous
mirt item type (Rasch, 2PL, 3PL, 4PL, ...) is handled without
assuming a particular parameterisation.
newdata may contain any id/item pairs, including ones
held out of the fit, as long as each person appears in resp and each
item was estimated. That is the cross-validation case: fit on part of the
data, predict the rest.
Requires the mirt package.
newdata with an added numeric column p, the predicted
probability of a response of 1.
df <- irw_simdata(n_id = 200, n_item = 10, model = "2PL", seed = 1) wide <- irw_long2resp(df) fit <- mirt::mirt(wide[setdiff(names(wide), "id")], 1, "Rasch") preds <- irw_predict(fit, wide)df <- irw_simdata(n_id = 200, n_item = 10, model = "2PL", seed = 1) wide <- irw_long2resp(df) fit <- mirt::mirt(wide[setdiff(names(wide), "id")], 1, "Rasch") preds <- irw_predict(fit, wide)
Rankings tables (source = "rank") keep the core column names, but
resp is a position: one row per respondent (id), ranking
(task) and marked position, resp = 1 for the first choice,
as recorded. Two things in the stored table need care before a
person-by-item pivot or a Plackett-Luce fit: a skipped position stays a gap
(a ballot marked at positions 1 and 3 keeps resp 1 and 3), and a
candidate marked twice keeps both rows. Counting rules for both differ by
jurisdiction, so the table does not apply one; this function applies the
common one.
irw_rank_compress(df, drop_repeats = TRUE)irw_rank_compress(df, drop_repeats = TRUE)
df |
A rankings table, as returned by
|
drop_repeats |
Logical. Drop an item's later marks within a ranking?
Default |
Within each id x task, rows are taken in resp order.
With drop_repeats = TRUE an item that has already been marked at an
earlier position is dropped at every later one (most counting rules treat
the later mark as a skip). The reserved items (write-in) and
(overvote) are never dropped: two write-in rows are usually two
different people, and two overvote rows are two separate events. Then
resp is renumbered 1..k in rank order, so the gaps close.
Every other column is kept as it was. The result is sorted by id,
task, resp.
The Python package's irw.rank_compress() does exactly the same; the
two are tested on one shared fixture.
A data frame with the same columns as df, resp an
integer running 1..k within each id x task.
irw_fetch, irw_metadata with
source = "rank" for each table's design record.
d <- data.frame(id = c(1, 1, 1, 2), task = 1, item = c("c01", "c03", "c01", "c02"), resp = c(1, 3, 4, 2)) irw_rank_compress(d) irw_rank_compress(d, drop_repeats = FALSE) ## Not run: d <- irw_fetch("eurovision_2016_final", source = "rank") first_choices <- subset(irw_rank_compress(d), resp == 1) ## End(Not run)d <- data.frame(id = c(1, 1, 1, 2), task = 1, item = c("c01", "c03", "c01", "c02"), resp = c(1, 3, 4, 2)) irw_rank_compress(d) irw_rank_compress(d, drop_repeats = FALSE) ## Not run: d <- irw_fetch("eurovision_2016_final", source = "rank") first_choices <- subset(irw_rank_compress(d), resp == 1) ## End(Not run)
Replaces the values of identifier columns (by default id and
item) with short ASCII codes such as P0001 and I0001.
This is useful when identifiers are in a script or use characters that are
awkward to type on a US keyboard, which makes subsetting, writing model
formulas, and reading wide-format column names difficult.
irw_recode(df, cols = c("id", "item"), prefix = NULL)irw_recode(df, cols = c("id", "item"), prefix = NULL)
df |
A data frame in IRW long format. |
cols |
Character vector of columns to recode. Defaults to
|
prefix |
Optional named character vector overriding the default code
prefixes, e.g. |
Codes are assigned in sorted order of the unique non-missing values of each column, so they are deterministic for a given set of values. They are, however, only meaningful relative to their key: two different subsets of the same table will generally not produce the same codes.
The mapping is attached to the result as an attribute and can be retrieved
with irw_recode_key(). Save it if you need it later, because most
base R operations on a data frame drop attributes. The original values can
be restored with irw_decode().
Note that recoding item breaks manual joins against
irw_itemtext() output, which is keyed on the original item
identifiers. Use irw_recode_key() to map back before joining.
df with the requested columns replaced by character codes and
an "irw_recode_key" attribute holding a data frame with columns
column, original, and code.
df <- data.frame( id = c("María-01", "María-01", "René-02"), item = c("Q_alpha", "Q_beta", "Q_alpha"), resp = c(1, 0, 1), stringsAsFactors = FALSE ) d <- irw_recode(df) head(d) irw_recode_key(d) identical(irw_decode(d)$item, df$item)df <- data.frame( id = c("María-01", "María-01", "René-02"), item = c("Q_alpha", "Q_beta", "Q_alpha"), resp = c(1, 0, 1), stringsAsFactors = FALSE ) d <- irw_recode(df) head(d) irw_recode_key(d) identical(irw_decode(d)$item, df$item)
Retrieve the Recode Key from an Object Returned by irw_recode()
irw_recode_key(x)irw_recode_key(x)
x |
An object returned by |
A data frame with columns column, original, and
code.
Returns one dataset, or the whole session, to reading the current release.
irw_reset_version(dataset = NULL)irw_reset_version(dataset = NULL)
dataset |
Optional character vector of dataset names to unpin. Defaults to every pinned dataset. |
Invisibly, the named character vector of pins still in effect.
irw_set_version, irw_get_version
irw_reset_version("item_response_warehouse") irw_reset_version() # unpin everythingirw_reset_version("item_response_warehouse") irw_reset_version() # unpin everything
Inverse of irw_long2resp(): converts a wide response data frame/matrix
into long format with columns id, item, resp.
irw_resp2long(x, id = TRUE)irw_resp2long(x, id = TRUE)
x |
A wide response object (data.frame or matrix). If produced by
|
id |
Logical. If TRUE (default), expects an |
A data.frame with columns id, item, resp.
Saves BibTeX entries for one or more IRW tables to a specified output file. Updates the BibTeX key to match the table name.
irw_save_bibtex( table_names, output_file, source = "core", comp = FALSE, sim = FALSE, nom = FALSE )irw_save_bibtex( table_names, output_file, source = "core", comp = FALSE, sim = FALSE, nom = FALSE )
table_names |
A character vector of table names for which BibTeX entries are generated. |
output_file |
A character string giving the file path the BibTeX
entries are written to, e.g. |
source |
Character. The data family: |
comp |
Deprecated. Use |
sim |
Deprecated. Use |
nom |
Deprecated. Use |
A table the IRW found through another collection, such as openESM, also
gets that collection's own entry (e.g. siepe2026openesm), added once
however many of its tables are requested.
Invisibly returns BibTeX entries as a character vector.
Fixes the version of one IRW dataset for the remainder of the R session, so that fetches, listings, and metadata are reproducible. Pin at the top of an analysis script and the script will return the same data when it is re-run, even after IRW has been updated.
irw_set_version(dataset, version)irw_set_version(dataset, version)
dataset |
Character. Name of the IRW dataset to pin, e.g.
|
version |
Character. A released version tag, e.g. |
The pin covers every lookup that reads the dataset, not just fetches:
irw_fetch(), irw_filter(), irw_list_tables(), and
metadata all read the pinned version.
Each IRW dataset is versioned independently on Redivis, so pinning is
per-dataset. irw_get_version() reports the versions currently in use,
which is how you find the tags to write into a script.
A table that does not exist in the pinned version is an error rather than a silent fetch from the current release: quietly mixing versions would break the reproducibility the pin exists to provide.
Invisibly, the named character vector of all pins in effect.
irw_get_version, irw_reset_version
irw_set_version("item_response_warehouse", "v32.0") irw_set_version("item_response_warehouse_2", "v1.8") df <- irw_fetch("kfcovid_fear_Li2020") # served from v32.0 irw_reset_version() # back to the current releaseirw_set_version("item_response_warehouse", "v32.0") irw_set_version("item_response_warehouse_2", "v1.8") df <- irw_fetch("kfcovid_fear_Li2020") # served from v32.0 irw_reset_version() # back to the current release
Simulates item response data from 1PL, 2PL, or 3PL logistic IRT models.
Returns a long-format data frame with id, item, and resp columns.
irw_simdata( n_id = 1000, n_item = 20, model = "1PL", a = NULL, b = NULL, g = NULL, theta = NULL, theta_mean = 0, theta_sd = 1, seed = NULL, return_params = FALSE )irw_simdata( n_id = 1000, n_item = 20, model = "1PL", a = NULL, b = NULL, g = NULL, theta = NULL, theta_mean = 0, theta_sd = 1, seed = NULL, return_params = FALSE )
n_id |
Number of respondents. Ignored if |
n_item |
Number of items. Default is 20. |
model |
Character string: one of |
a |
Optional vector of item discriminations. If |
b |
Optional vector of item difficulties. If |
g |
Optional vector of guessing parameters. Required for 3PL; if |
theta |
Optional vector of person abilities. If provided, overrides |
theta_mean |
Mean of theta distribution (if |
theta_sd |
Standard deviation of theta distribution. Default is 1. |
seed |
Optional integer for reproducibility. |
return_params |
Logical. If |
A data frame with columns id, item, resp, or a list with additional parameters if return_params = TRUE.
# 1PL (default) dat <- irw_simdata(n_item = 5) # 3PL with latent traits drawn from N(-0.5, 1) sim <- irw_simdata(n_item = 5, model = "3PL", theta_mean = -0.5, return_params = TRUE) head(sim$data)# 1PL (default) dat <- irw_simdata(n_item = 5) # 3PL with latent traits drawn from N(-0.5, 1) sim <- irw_simdata(n_item = 5, model = "3PL", theta_mean = -0.5, return_params = TRUE) head(sim$data)
Generates pairwise outcomes among n_agent agents using the Davidson model with ties.
(See https://link.springer.com/article/10.3758/s13428-021-01714-2).
Returns one row per comparison with agent_a, agent_b, and winner.
irw_simdata_comp( n_agent = 100, n_pairs = 10000, nu = 0, theta = NULL, theta_mean = 0, theta_sd = 1, seed = NULL, return_params = FALSE )irw_simdata_comp( n_agent = 100, n_pairs = 10000, nu = 0, theta = NULL, theta_mean = 0, theta_sd = 1, seed = NULL, return_params = FALSE )
n_agent |
Integer. Number of agents (ignored if |
n_pairs |
Integer. Number of pairwise comparisons to sample. Default 10000. |
nu |
Numeric. Tie propensity in the Davidson model. Larger values yield more ties. Default 0. |
theta |
Optional numeric vector of length |
theta_mean |
Mean of the theta distribution (used if |
theta_sd |
SD of the theta distribution (used if |
seed |
Optional integer for reproducibility. |
return_params |
Logical. If TRUE, return a list with |
A data.frame with columns:
agent_a (int): index of first agent
agent_b (int): index of second agent
winner (chr): one of "agent_a","agent_b", or "draw".
If return_params = TRUE, returns a list with:
data: the simulated data frame.
theta: vector of simulated thetas used
nu: tie parameter
# --- Basic usage --- d <- irw_simdata_comp(n_agent = 100, n_pairs = 10000, nu = 0) head(d) # Simulate pairwise comparison data and recover abilities with a Davidson model if (requireNamespace("gnm", quietly = TRUE) && requireNamespace("BradleyTerry2", quietly = TRUE)) { th <- rnorm(n = 50, mean = 0.5, sd = 3) pairs <- irw_simdata_comp( n_agent = 50, n_pairs = 3000, nu = 0.1, theta = th, seed = 1, return_params = TRUE ) x <- pairs$data x$winner <- ifelse(x$winner == "agent_b", -1, 1) x$winner <- ifelse(x$winner == "draw", 0, x$winner) x$agent_a <- as.factor(x$agent_a) x$agent_b <- as.factor(x$agent_b) x$pair <- seq_len(nrow(x)) # add pair id for expandCategorical library(gnm) library(BradleyTerry2) pairs.tri <- expandCategorical(x, "winner", idvar = "pair") dav <- gnm( count ~ GenDavidson( winner == 1, winner == 0, winner == -1, player1 = agent_a, player2 = agent_b ) - 1, eliminate = pair, family = poisson, data = pairs.tri ) plot( pairs$theta, coef(dav)[-1], xlab = "True theta", ylab = "Estimated ability (shifted)", main = "Davidson recovery using gnm" ) abline(lm(coef(dav)[-1] ~ pairs$theta), lty = 2) }# --- Basic usage --- d <- irw_simdata_comp(n_agent = 100, n_pairs = 10000, nu = 0) head(d) # Simulate pairwise comparison data and recover abilities with a Davidson model if (requireNamespace("gnm", quietly = TRUE) && requireNamespace("BradleyTerry2", quietly = TRUE)) { th <- rnorm(n = 50, mean = 0.5, sd = 3) pairs <- irw_simdata_comp( n_agent = 50, n_pairs = 3000, nu = 0.1, theta = th, seed = 1, return_params = TRUE ) x <- pairs$data x$winner <- ifelse(x$winner == "agent_b", -1, 1) x$winner <- ifelse(x$winner == "draw", 0, x$winner) x$agent_a <- as.factor(x$agent_a) x$agent_b <- as.factor(x$agent_b) x$pair <- seq_len(nrow(x)) # add pair id for expandCategorical library(gnm) library(BradleyTerry2) pairs.tri <- expandCategorical(x, "winner", idvar = "pair") dav <- gnm( count ~ GenDavidson( winner == 1, winner == 0, winner == -1, player1 = agent_a, player2 = agent_b ) - 1, eliminate = pair, family = poisson, data = pairs.tri ) plot( pairs$theta, coef(dav)[-1], xlab = "True theta", ylab = "Estimated ability (shifted)", main = "Davidson recovery using gnm" ) abline(lm(coef(dav)[-1] ~ pairs$theta), lty = 2) }
This function generates simulated item difficulties by drawing from normal distributions centered around existing difficulty estimates and their associated standard errors. The result is a mixture distribution, from which new difficulties are sampled using inverse CDF sampling.
irw_simu_diff( num_items = 10, num_replications = 1, irw_names = NULL, difficulty_pool = NULL )irw_simu_diff( num_items = 10, num_replications = 1, irw_names = NULL, difficulty_pool = NULL )
num_items |
Number of item difficulties to simulate per replication. |
num_replications |
Number of replications to perform. If 1, returns a numeric vector. If >1, returns a data frame. |
irw_names |
Optional character vector of IRW dataset names to filter from |
difficulty_pool |
Optional custom data frame with columns |
By default, the function uses diff_long, a built-in dataset included in the irw package.
This dataset contains item difficulty estimates and standard errors from a curated
subset of IRW datasets. You can:
Use the full IRW difficulty pool (diff_long)
Filter to specific IRW datasets via irw_names
Provide your own difficulty pool via difficulty_pool
This method is based on Zhang et al. (2025), which constructs realistic empirical distributions by accounting for uncertainty around item difficulty estimates.
A numeric vector of difficulties (if num_replications = 1), or a data frame
with replication and difficulty columns (if num_replications > 1).
Zhang, L., Liu, Y., Molenaar, D., & Domingue, B. (2025). Realistic Simulation of Item Difficulties. https://doi.org/10.31234/osf.io/jbhxy_v1
# Use all IRW data (default) irw_simu_diff(num_items = 5) # Filter to specific IRW datasets irw_simu_diff(num_items = 5, irw_names = c("psychtools_epi", "psychtools_blot")) # Use a custom difficulty pool my_pool <- data.frame(dataset = "x", difficulty = c(-0.2, 0.1), SE = c(0.1, 0.2)) irw_simu_diff(num_items = 5, difficulty_pool = my_pool) # Explore built-in IRW difficulty pool head(diff_long) unique(diff_long$dataset)# Use all IRW data (default) irw_simu_diff(num_items = 5) # Filter to specific IRW datasets irw_simu_diff(num_items = 5, irw_names = c("psychtools_epi", "psychtools_blot")) # Use a custom difficulty pool my_pool <- data.frame(dataset = "x", difficulty = c(-0.2, 0.1), SE = c(0.1, 0.2)) irw_simu_diff(num_items = 5, difficulty_pool = my_pool) # Explore built-in IRW difficulty pool head(diff_long) unique(diff_long$dataset)
Answers set and summary questions about a table – which item codes it
contains, which response values occur, how many rows each item has – using
server-side aggregate queries rather than exporting the table. This matters
for large tables: computing the item set of a 68-million-row table with
irw_fetch() downloads all 68 million rows, while
irw_table_sets() returns the same answer in seconds and does not
consume the Redivis export quota.
irw_table_sets(name, source = "core", per_item = FALSE)irw_table_sets(name, source = "core", per_item = FALSE)
name |
Character vector of one or more IRW table names. Several names run the same queries once per table, still without an export, so this is the way to sweep many tables. |
source |
Character. The data family: |
per_item |
Logical. If TRUE, also return a per-item summary (row count, response minimum, maximum, and number of distinct response values). One extra query; the result has one row per distinct item. Defaults to FALSE. |
For a single name, a list with elements:
Fully qualified Redivis reference for the table.
Total number of rows.
Sorted character vector of distinct item values.
Sorted vector of distinct resp values, numeric when
all values are numeric and character otherwise. "NA" and empty
strings are treated as missing, matching irw_fetch().
Data frame of per-item summaries, or NULL when
per_item = FALSE or the table has no item or
resp column.
For several names, a named list of those lists, one per table, in the order given. Each element is exactly what the single-name call returns.
sets <- irw_table_sets("rosenberg_selfesteem") sets$items sets$resp irw_table_sets("condon_2024_sapa_personality", per_item = TRUE)$per_item # Several tables at once: no export, one set of queries per table sweep <- irw_table_sets(c("rosenberg_selfesteem", "environment_ltm")) lengths(lapply(sweep, `[[`, "items"))sets <- irw_table_sets("rosenberg_selfesteem") sets$items sets$resp irw_table_sets("condon_2024_sapa_personality", per_item = TRUE)$per_item # Several tables at once: no export, one set of queries per table sweep <- irw_table_sets(c("rosenberg_selfesteem", "environment_ltm")) lengths(lapply(sweep, `[[`, "items"))
Returns a data frame of unique tag values from a given tag metadata column,
along with the number of datasets each tag appears in. Multi-tag fields hold a
comma-joined list; no tag value contains a comma (see .irw_split_tags).
irw_tag_options(column, source = "core")irw_tag_options(column, source = "core")
column |
A character string specifying the tag column name. |
source |
Character. The data family: |
A data.frame with columns: tag and count, sorted by descending frequency.
Fetches the tags table from Redivis and returns it as a tibble. Link to Redivis table: https://redivis.com/datasets/bdxt-4fqe5tyf4/tables/7nkh-6m7wq01yv Automatically checks for updates and refreshes only when needed.
irw_tags(tables = NULL, source = "core")irw_tags(tables = NULL, source = "core")
tables |
Optional. A character vector of table name(s) to filter by. |
source |
Character. The data family: |
A tibble containing tags information.
irw_tags() # core irw_tags(source = "nom") # nominalirw_tags() # core irw_tags(source = "nom") # nominal
Pins every IRW dataset at once to what a single IRW version held, so that
irw_fetch() and everything around it return the same data whenever the
script is re-run – even after IRW has been corrected or extended. This is
the reproducibility switch: put one call at the top of an analysis and the
rest of the script is frozen.
irw_use_version(version = NULL, date = NULL, quiet = FALSE)irw_use_version(version = NULL, date = NULL, quiet = FALSE)
version |
Optional IRW version number, e.g. |
date |
Optional date or time to pin the corpus as it was then, e.g.
|
quiet |
Logical. Suppress the per-dataset summary. |
irw_use_version(332)
df <- irw_fetch("gilbert_meta_12") # v332's copy, today and next year
Called with no arguments it pins the newest version and reports its number: run it at the start of a project and record the number it prints.
The pin covers the metadata and item text datasets too, not just response
data, and lasts for the session; irw_reset_version() lifts it.
Invisibly, a data frame of dataset and version as pinned, with
the IRW version number in the attribute irw_version.
The response data is spread over several Redivis warehouses ("shards"), each
released on its own schedule, so one IRW version means a different Redivis
version in each. That is handled: every dataset is pinned to the tag the
manifest records for it, and a single irw_fetch() call may read several
shards at different versions.
irw_use_version(200) # shard 1 at v36.0, shard 2 at v3.3
L <- irw_fetch(c("idcr_martinez_2023_numSeries", "gcb5_2025"))
Not every IRW dataset has a release in every IRW version – the sixth warehouse shard is younger than the first. Rather than let those fall through to the current release and silently mix versions into a "reproduced" run, they are pinned to nothing and error if something reads them. Fetches are unaffected: a table that did not exist then is simply not found.
A date has to be resolved to a version, and before 21 July 2026 that
resolution is approximate for the older warehouse shards – see
irw_version(). Pinning by date therefore warns; pinning by number never
has to.
irw_version(), irw_get_version(), irw_reset_version()
irw_use_version(332) # read the corpus as v332 held it irw_use_version() # freeze today's version; record the number irw_use_version(date = "2026-08-01") irw_reset_version() # back to the current releaseirw_use_version(332) # read the corpus as v332 held it irw_use_version() # freeze today's version; record the number irw_use_version(date = "2026-08-01") irw_reset_version() # back to the current release
IRW is made of eleven Redivis datasets that are versioned independently, so no single Redivis version describes the corpus. The IRW version number does: it increments whenever any dataset is published and names one exact combination of the eleven. Cite it in a paper and a reader can reconstruct the data you used.
irw_version(date = NULL, version = NULL)irw_version(date = NULL, version = NULL)
date |
Optional. A date or time to look up, as |
version |
Optional. An IRW version number, e.g. |
Called with no argument, reports the newest IRW version. Called with a
version, reports exactly what that version held. Called with a date,
reports the version that was live then – which is how you recover what an
analysis run months ago was actually reading.
Use irw_use_version() to make the session read one of these versions.
A data frame with one row per dataset and columns dataset,
version, released_at, and approximate. The IRW version number is
attached as the attribute irw_version and printed as a message.
Redivis overwrote its own release timestamps for the older warehouse shards
during a platform migration: 142 of the corpus' 332 released versions claim
to have been released inside one 80-minute window on 2026-07-21. For those,
the manifest records the earliest date the version could have been live
(its creation date) and marks the row bracketed. A lookup that lands on
one warns, because the tag may then be wrong too – a later version could
already have been released inside the bracket. IRW version numbers
themselves are always exact; only the mapping from a date to a version is
affected. This is why a paper should cite the number, not the date.
irw_use_version() to read a whole IRW version,
irw_set_version() to pin one dataset, irw_get_version() for the
versions the current session is actually reading.
irw_version() # the newest IRW version, and its eleven pins irw_version(version = 332) # exactly what v332 held irw_version("2026-08-01") # what was live on 1 August 2026irw_version() # the newest IRW version, and its eleven pins irw_version(version = 332) # exactly what v332 held irw_version("2026-08-01") # what was live on 1 August 2026
A sample dataset sourced from the IRW database to illustrate package functionality and enable users to experiment without needing authentication.
swmd_mokkenswmd_mokken
A data frame with 4557 rows and 4 variables:
Unique identifier for each subject.
Item identifier, specifying the question or measurement.
Response variable, indicating the response provided.
Rater identifier, specifying the rater who provided the response.
This dataset is part of the IRW database and serves as an example for using package functions. It includes basic variables typically present in psychometric datasets such as subject identifiers, item identifiers, and response variables.
IRW Data Warehouse