The hardware and bandwidth for this mirror is donated by METANET, the Webhosting and Full Service-Cloud Provider.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]metanet.ch.
This vignette shows the data required by each model. The examples use plain data frames so that the required columns are visible. Column names can differ; name their roles in the fitting function.
Use one row per person and one column per item. Scores begin at zero.
A dichotomous item is coded 0/1; an item with four categories is coded
0, 1, 2 or 3. Missing values may be NA; negative
missing-value codes are also accepted through na_codes.
responses <- data.frame(
person = c("P01", "P02", "P03", "P04"),
group = c("control", "control", "treated", "treated"),
I1 = c(0, 1, 1, 1),
I2 = c(0, 1, 2, 2),
I3 = c(1, 2, 3, NA)
)
responses
#> person group I1 I2 I3
#> 1 P01 control 0 0 1
#> 2 P02 control 1 1 2
#> 3 P03 treated 1 2 3
#> 4 P04 treated 1 2 NAThe identifier and person factors are not item responses. Name them explicitly, or nominate the item columns.
fit <- rasch(
responses,
id = "person",
factors = "group",
items = c("I1", "I2", "I3"),
model = "PCM"
)Use model = "RSM" only when the items share one
rating-scale threshold structure. Items may have different maximum
scores in the partial credit model.
External weights are supplied after fitting. Item weights are a named numeric vector. Set weights additionally need an item-to-set map, except for an EFRM fit, which already contains one.
item_weights <- c(I1 = 2, I2 = 1, I3 = 0.5)
weighted <- weighted_person_estimates(fit, item_weights)
set_of <- c(I1 = "core", I2 = "core", I3 = "extension")
set_weights <- c(core = 2, extension = 1)
weighted_person_estimates(fit, set_weights, by = "set", sets = set_of)
save_outputs(fit, "analysis", person_weights = weighted) # new or empty folderOnly relative weights matter. The weighted estimates are
supplementary; they do not replace the Rasch estimates used for fit,
reliability, targeting or DIF. In the application, use a CSV with
item,weight, or item,set,weight for set
weights. The computed table can also be passed to
save_outputs(), report_html() or
report_document().
The response data remain in the wide form above. A second data frame — the one uploaded as a CSV in the application — describes the items. Its shape depends on the level being explained, and that is the distinction to get right before anything else.
An item-level design has one row per item. The predictors describe the item as a whole, and the model explains the item’s location.
A threshold-level design has one row per fitted
threshold, identified by item and
threshold together. The predictors may vary within an item,
and the model explains each threshold separately.
The number of rows a threshold design needs is fixed by the data, not
chosen: an item scored 0 to m has m thresholds. For
the responses above that is one for I1, two for
I2 and three for I3 — six rows, not three.
items <- c("I1", "I2", "I3")
maxima <- vapply(responses[items], max, 0, na.rm = TRUE)
data.frame(item = items, max_score = maxima, thresholds = maxima,
row.names = NULL)
#> item max_score thresholds
#> 1 I1 1 1
#> 2 I2 2 2
#> 3 I3 3 3
sum(maxima) # rows a threshold-level design must have
#> [1] 6The same two predictors at threshold level. format is a
property of the item, so it simply repeats down that item’s thresholds;
demand now varies between them, which is the reason to work
at this level at all. An item-level predictor is not excluded from a
threshold design — it is constant within each item.
threshold_design <- data.frame(
item = rep(items, maxima),
threshold = sequence(maxima),
format = rep(c("selected", "constructed", "constructed"), maxima),
demand = c(0.2,
0.5, 0.9,
0.4, 0.8, 1.4)
)
threshold_design
#> item threshold format demand
#> 1 I1 1 selected 0.2
#> 2 I2 1 constructed 0.5
#> 3 I2 2 constructed 0.9
#> 4 I3 1 constructed 0.4
#> 5 I3 2 constructed 0.8
#> 6 I3 3 constructed 1.4
nrow(threshold_design) == sum(maxima)
#> [1] TRUEfit <- rasch_explanatory(
responses,
predictors = threshold_design,
formula = ~ format + demand,
level = "threshold",
id = "person",
factors = "group",
items = items
)threshold numbers the thresholds within an item, from 1,
in order. It is not a running count across the instrument:
I2 has thresholds 1 and 2, and so does the first half of
I3. sequence(maxima) above generates exactly
that pattern, and is worth using in place of typing the column out.
Three mistakes account for most refused designs. Each is named precisely when it happens, so the message identifies the rows to fix:
"threshold",
leaving the design short by every threshold after the first, and every
threshold missing where the numbering does not match. Both report
threshold-level predictors are missing, listing the item and
threshold of each;item and threshold pair, which
reports threshold-level predictors need one row per item and
threshold.Categorical predictors should be factors, continuous predictors
numeric, and ordinal predictors ordered factors with their substantive
order declared. In the application, upload the same table as a CSV:
item plus the predictor columns at item level, and
item,threshold plus the predictor columns at threshold
level. The predictor type of each column is set after the upload, so a
column read as text can still be declared ordinal with its order
given.
Long data use one row per observed rating. The required roles are
person, item, score and at least one facet. A rater, task or occasion
can be a facet. A person-group variable is instead supplied through
factors.
ratings <- data.frame(
person = c("P01", "P01", "P02", "P02"),
item = c("Essay1", "Essay2", "Essay1", "Essay2"),
rater = c("R1", "R2", "R2", "R1"),
occasion = c("first", "first", "first", "first"),
score = c(2, 3, 1, 2)
)
ratings
#> person item rater occasion score
#> 1 P01 Essay1 R1 first 2
#> 2 P01 Essay2 R2 first 3
#> 3 P02 Essay1 R2 first 1
#> 4 P02 Essay2 R1 first 2fit <- rasch_mfrm(
ratings,
person = "person",
item = "item",
score = "score",
facets = c("rater", "occasion")
)Wide multiple-ratings data use one row per person-by-facet combination and one score column per item.
wide_ratings <- data.frame(
person = c("P01", "P01", "P02", "P02"),
rater = c("R1", "R2", "R1", "R2"),
Essay1 = c(2, 3, 1, 2),
Essay2 = c(3, 2, 2, 2)
)
wide_ratings
#> person rater Essay1 Essay2
#> 1 P01 R1 2 3
#> 2 P01 R2 3 2
#> 3 P02 R1 1 2
#> 4 P02 R2 2 2fit <- rasch_mfrm(
wide_ratings,
person = "person",
facets = "rater",
items = c("Essay1", "Essay2")
)Long data are usually easier to inspect when a facet varies within items.
EFRM response data use one row per person and one column per item, together with a person-group column. A separate named map assigns each item to exactly one item set. Supplied person identifiers must not repeat; missing or blank identifiers are treated as different unknown persons.
frame_data <- data.frame(
person = paste0("P", 1:6),
group = rep(c("A", "B"), each = 3),
S1I1 = c(0, 1, 1, 0, 1, 1),
S1I2 = c(0, 0, 1, 0, 1, 1),
S2I1 = c(0, 1, 1, 0, 0, 1),
S2I2 = c(0, 1, 1, 0, 1, 1)
)
frame_data
#> person group S1I1 S1I2 S2I1 S2I2
#> 1 P1 A 0 0 0 0
#> 2 P2 A 1 0 1 1
#> 3 P3 A 1 1 1 1
#> 4 P4 B 0 0 0 0
#> 5 P5 B 1 1 0 1
#> 6 P6 B 1 1 1 1
item_sets <- list(
set1 = c("S1I1", "S1I2"),
set2 = c("S2I1", "S2I2")
)
item_sets
#> $set1
#> [1] "S1I1" "S1I2"
#>
#> $set2
#> [1] "S2I1" "S2I2"Persons must connect the item sets, and common items across person
groups must identify the group units. Crossed person-group factors can
be supplied as several column names in groups.
Use one row per comparison. object_a and
object_b identify the pair. For a dichotomous comparison,
winner contains one of those two object names.
comparisons <- data.frame(
object_a = c("A", "A", "B", "A"),
object_b = c("B", "C", "C", "C"),
winner = c("A", "C", "B", "A"),
judge = c("J1", "J1", "J2", "J2")
)
comparisons
#> object_a object_b winner judge
#> 1 A B A J1
#> 2 A C C J1
#> 3 B C B J2
#> 4 A C A J2fit <- btl(
comparisons,
object_a = "object_a",
object_b = "object_b",
winner = "winner",
judge = "judge"
)For ordered comparisons, replace winner with an ordered
response column whose categories run from preference for object B to
preference for object A. A frequency column can represent repeated
identical rows. A judgement-order column is needed to estimate exposure
or carry-over dependence.
Explanatory Comparative Judgement adds one metadata row per object.
The comparison rows additionally identify each judge’s panel. A named list assigns every object to one object set. Both within-set and cross-set comparisons are required to identify set units and origins.
object_sets <- list(
set1 = c("S1A", "S1B", "S1C"),
set2 = c("S2A", "S2B", "S2C")
)
object_sets
#> $set1
#> [1] "S1A" "S1B" "S1C"
#>
#> $set2
#> [1] "S2A" "S2B" "S2C"
# the first four rows compare within a set, the last two across sets
frame_comparisons <- data.frame(
object_a = c("S1A", "S1B", "S2A", "S2B", "S1A", "S1C"),
object_b = c("S1B", "S1C", "S2B", "S2C", "S2A", "S2C"),
winner = c("S1A", "S1C", "S2A", "S2B", "S2A", "S1C"),
judge = c("J1", "J1", "J2", "J2", "J3", "J3"),
panel = c("east", "east", "west", "west", "east", "east")
)
frame_comparisons
#> object_a object_b winner judge panel
#> 1 S1A S1B S1A J1 east
#> 2 S1B S1C S1C J1 east
#> 3 S2A S2B S2A J2 west
#> 4 S2B S2C S2B J2 west
#> 5 S1A S2A S2A J3 east
#> 6 S1C S2C S1C J3 eastThe Simulate page in the Shiny application generates
every structure above, assigns its roles and retains the generating
values. The corresponding R functions are simulate_rasch(),
simulate_btl(), simulate_mfrm(),
simulate_efrm() and simulate_btl_efrm().
Explanatory simulations add the item or object metadata used to generate
the locations. Each simulator stores its parameter values and planted
departures in attr(data, "truth"). The app can download the
data as a CSV or as a bundle containing the generating call, true values
and explanatory metadata.
These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.