| Type: | Package |
| Title: | Quick Screening of Response Patterns in Test and Survey Items |
| Version: | 0.4.1 |
| Description: | One call screens the item responses of a test or questionnaire for patterns that deserve a closer look before modelling: flat or long-string responding, low intra-individual variability, multivariate outliers, incoherent psychometric synonyms or even-odd halves, overuse of the midpoint or of the extremes, duplicated response vectors and identical patterns that arrive in series of consecutive submissions. Indices follow Curran (2016) <doi:10.1016/j.jesp.2015.07.006>; person fit in item response theory (the standardized log-likelihood) is optional, and cut-offs can be taken from a reference group. Results are returned per person, with flags, frequency tables of response patterns and plots. Whole batches of data (a second collection phase, one classroom) can be compared with a reference group: the item correlation structure, with permutation tests that leave out flat responders and match the response level, and the Jennrich (1970) <doi:10.1080/01621459.1970.10481133> test; the similarity of consecutive rows; and near-duplicate respondents. Flagged respondents can be removed in one step and the same confirmatory or exploratory factor model can be refitted with and without them. |
| License: | GPL (≥ 3) |
| Encoding: | UTF-8 |
| RoxygenNote: | 7.3.2 |
| Depends: | R (≥ 4.1) |
| Imports: | ggplot2 (≥ 3.4.0), stats, utils |
| Suggests: | lavaan, mirt, testthat (≥ 3.0.0) |
| LazyData: | true |
| Config/testthat/edition: | 3 |
| NeedsCompilation: | no |
| Packaged: | 2026-10-25 13:09:01 UTC; PC |
| Author: | Jose Ventura-Leon |
| Maintainer: | Jose Ventura-Leon <jventuraleon@gmail.com> |
| Repository: | CRAN |
| Date/Publication: | 2026-11-08 18:00:02 UTC |
Print and plot a batch comparison
Description
print() shows the groups compared and the tests. plot() draws one of
three views, with ggplot2:
"null"Histograms of each statistic in the reference samples, with the focal value as a vertical line. A line far to the left of the histogram means less structure than any comparable group of reference respondents. Compare the panels of the full and the level-matched reference: when only the first one is extreme, the level explains the difference.
"heatmap"Item correlations of the reference (level-matched when available) and of the focal group, side by side, with the scales marked. Genuine data show blocks along the diagonal.
"structure"Mean correlation within and between scales in each group. The gap between both bars is the structure.
Usage
## S3 method for class 'batch_comparison'
print(x, digits = 3, ...)
## S3 method for class 'batch_comparison'
plot(
x,
type = c("null", "heatmap", "structure"),
lang = c("en", "es"),
base_size = 11,
...
)
Arguments
x |
An object returned by |
digits |
Number of decimals printed. |
... |
Not used. |
type |
One of |
lang |
Language of the labels: |
base_size |
Base font size of the theme. |
Value
print() returns x invisibly. plot() returns a ggplot
object, printed on the current device and returned invisibly.
Examples
sc <- list(F1 = paste0("I", 1:4), F2 = paste0("I", 5:8), F3 = paste0("I", 9:12))
cb <- compare_batches(batch_sim, group = "phase", scales = sc, B = 200)
print(cb, digits = 2)
plot(cb, type = "structure")
Simulated two-phase survey with a hand-filled block
Description
Simulated answers of 260 respondents to a 12-item questionnaire (three
scales of four items, options 1 to 5), collected in two phases. Phase 1
has 200 genuine respondents, 8 of them flat. Phase 2 has 30 genuine
respondents with a higher level and a block of 30 rows filled by hand:
each row copies the previous one and changes two or three answers, and
the sex and age are often copied too. The block has the level of phase 2
but no factor structure. It is the example data of compare_batches(),
order_test() and neighbor_test(). No real person is included.
Usage
batch_sim
Format
A data frame with 260 rows and 17 columns:
- id
Respondent number, in order of arrival.
- phase
Collection phase, 1 or 2.
- sex
"Female"or"Male".- age
Age group:
"17-20","21-25","26-30"or"31+".- source
How the row was generated:
"genuine","flat"or"hand-filled".- I1
Item 1 (scale 1); options 1 to 5.
- I2
Item 2 (scale 1); options 1 to 5.
- I3
Item 3 (scale 1); options 1 to 5.
- I4
Item 4 (scale 1); options 1 to 5.
- I5
Item 5 (scale 2); options 1 to 5.
- I6
Item 6 (scale 2); options 1 to 5.
- I7
Item 7 (scale 2); options 1 to 5.
- I8
Item 8 (scale 2); options 1 to 5.
- I9
Item 9 (scale 3); options 1 to 5.
- I10
Item 10 (scale 3); options 1 to 5.
- I11
Item 11 (scale 3); options 1 to 5.
- I12
Item 12 (scale 3); options 1 to 5.
Source
Simulated with the script data-raw/make_batch_sim.R of the
package source.
Compare the correlation structure of a batch of data with a reference
Description
Asks whether a batch of respondents (a second collection phase, one classroom, the cases entered by one person) answers with the same structure as the rest. In genuine data, items of the same scale move together more than items of different scales, because the answers come from the respondents' traits. Answers filled by hand can copy the level (many 4s and 5s) but rarely reproduce that structure.
Usage
compare_batches(
data,
group,
items = NULL,
scales = NULL,
focal = NULL,
reference = NULL,
drop_flat = TRUE,
match_level = TRUE,
B = 2000,
min_ratio = 3
)
Arguments
data |
A data frame with one row per respondent. |
group |
The batch of each respondent: a column name of |
items |
Item columns. By default, the items in |
scales |
Optional named list of character vectors, one per scale.
Needed for the |
focal |
Group (or groups) under examination. By default, the smallest group. |
reference |
Group (or groups) used as reference. By default, every other group. |
drop_flat |
Logical; remove respondents with the same answer in every item before comparing. |
match_level |
Logical; add the comparison with reference samples paired by level with the focal batch. |
B |
Number of random samples drawn from the reference. |
min_ratio |
Minimum ratio between the reference and the focal group
for the whole batch to be compared in every sample. With a smaller
reference (even one smaller than the batch) the batch is subsampled to
|
Details
Two statistics are computed in the focal batch: the mean inter-item
correlation and, when scales defines two or more scales, the
structure (mean correlation within scales minus mean correlation
between scales). Their null distribution comes from B random samples,
of the size of the focal batch, drawn from the reference group. The
p value is the share of samples with a value as low or lower than the
focal one, so small values mean that the batch has less structure than
any comparable group of reference respondents.
Two precautions avoid false alarms, and both changed the conclusion in the real case that motivated this function:
-
drop_flat: respondents with the same answer in every item inflate the correlations of the group they belong to. They are removed from both groups before comparing. -
match_level: a batch that answers high has less variability, and less variability lowers correlations on its own (range restriction). Each reference sample is then built by pairing every focal respondent with the reference respondent of the closest mean answer, so it reproduces the whole distribution of levels of the batch. When the difference disappears with this control, the low correlations are explained by the level, not by the answers.
The level-matched samples need a reference clearly larger than the
batch, above all when the batch answers at an unusual level. When the
reference has fewer than min_ratio times the focal respondents,
pairing every focal respondent picks nearly the same reference rows in
every sample, the control does not vary and its p values overstate the
evidence. In the real case behind this argument (32 items, a reference
of 150 and a lower-level batch of 210), consecutive matched samples
shared 100% of their rows with the whole reference, 87% with
min_ratio = 2 and 63% with min_ratio = 3. In that case each sample takes a random
subsample of the batch, of the size of the reference divided by
min_ratio, and pairs the reference with it; the focal value reported is
then the median over the focal subsamples, so that both sides are
computed at the same size. This median is more stable than a single
focal sample, which makes the test somewhat conservative. A warning is
given when consecutive level-matched samples still share more than 80%
of their rows.
The Jennrich (1970) test of the equality of the two correlation matrices is reported as well. It is very sensitive: it also rejects when two genuine populations differ, so it says that the matrices differ, not why.
Value
An object of class batch_comparison, a list with:
- groups
One row per group (focal, reference and, if requested, the level-matched reference): respondents, flat respondents removed, respondents used, mean answer, mean within-person standard deviation, mean inter-item correlation and the within, between and structure correlations.
- tests
One row per comparison and statistic: the focal value, the size of the samples compared (
n_sample), the median and the 2.5th percentile of the reference samples, and the p value.- jennrich
Jennrich test of the focal against each reference: chi- square, degrees of freedom and p value.
- null, cor, settings
The values of the reference samples, the correlation matrices and the arguments used, kept for the plots.
settingsalso keeps the focal sample size (focal_sample), whether the batch was subsampled and the share of rows shared by consecutive level-matched samples (matched_overlap).
References
Jennrich, R. I. (1970). An asymptotic chi-square test for the equality of two correlation matrices. Journal of the American Statistical Association, 65(330), 904-912. doi:10.1080/01621459.1970.10481133
See Also
order_test() and neighbor_test() for traces of copying,
and the reference argument of scan_responses() to flag single
respondents with cut-offs taken from a reference group.
Examples
sc <- list(F1 = paste0("I", 1:4), F2 = paste0("I", 5:8), F3 = paste0("I", 9:12))
cb <- compare_batches(batch_sim, group = "phase", scales = sc, B = 200)
cb
plot(cb)
plot(cb, type = "heatmap")
plot(cb, type = "structure", lang = "es")
Fit the same CFA or EFA with and without flagged respondents
Description
A sensitivity analysis in one call: the same factor model is fitted to the full sample and to the data left after each exclusion, and the fit indices, the mean standardized loading and the factor correlations are put side by side. Models are fitted with lavaan, which must be installed.
Usage
compare_fit(
x,
data,
model = NULL,
exclusions = NULL,
type = c("cfa", "efa"),
nfactors = 1,
items = NULL,
ordered = TRUE,
...
)
Arguments
x |
An object returned by |
data |
The data frame that was screened (same rows, same order). |
model |
For |
exclusions |
Named list of exclusions. Each element is |
type |
|
nfactors |
Number of factors for |
items |
Items analysed by the EFA. By default, every screened item. |
ordered |
Logical; treat the items as ordinal (the default, with the WLSMV estimator) or as continuous. |
... |
Further arguments passed to |
Value
An object of class fit_comparison, a list with table (one row
per exclusion: removed and kept respondents, chi-square, degrees of
freedom, CFI, TLI, RMSEA, SRMR, mean_loading (mean over items of the
largest absolute standardized loading of each item), the
factor correlations and a note with warnings or errors; the scaled
versions of the indices are used when the estimator provides them),
fits (the lavaan objects, NULL when a model failed) and data (the
data set used in each fit). It has print() and plot() methods.
Examples
if (requireNamespace("lavaan", quietly = TRUE)) {
res <- scan_responses(survey_sim,
scales = list(A = paste0("A", 1:8), B = paste0("B", 1:10)),
reverse = paste0("A", 1:4), time = "submitted",
pattern_items = paste0("A", 1:8))
m <- "A =~ A1 + A2 + A3 + A4 + A5 + A6 + A7 + A8
B =~ B1 + B2 + B3 + B4 + B5 + B6 + B7 + B8 + B9 + B10"
cf <- compare_fit(res, survey_sim, model = m,
exclusions = list("Full sample" = NULL, "Without series" = "serial",
"Without any flag" = "any"))
cf
plot(cf)
}
Remove flagged respondents or response patterns from the data
Description
Returns the original data without the respondents that meet the chosen
criteria, ready to be passed to any model (for example lavaan::cfa(),
lavaan::efa() or psych::fa()). Criteria can be combined: a respondent
is removed when any of them applies.
Usage
exclude_responses(
x,
data,
flags = "serial",
patterns = NULL,
min_flags = NULL,
rows = NULL
)
Arguments
x |
An object returned by |
data |
The data frame that was screened (same rows, same order). All its columns are kept. |
flags |
Character vector with flag names ( |
patterns |
Character vector with response patterns, as they appear in
|
min_flags |
Remove respondents with at least this number of flags. |
rows |
Additional row positions (integer) or a logical vector of
length |
Value
A data frame with the kept rows of data (original row names are
preserved) and two attributes: excluded, the positions of the removed
rows, and rule, a text that describes the criteria used. A warning is
given when the rule removes more than half of the sample.
Examples
res <- scan_responses(survey_sim, items = paste0("A", 1:8),
reverse = paste0("A", 1:4), time = "submitted")
clean <- exclude_responses(res, survey_sim, flags = "serial")
nrow(clean)
attr(clean, "rule")
# The same pattern, also when it did not arrive in series
nrow(exclude_responses(res, survey_sim, flags = NULL, patterns = "11113333"))
# Respondents with two or more flags
nrow(exclude_responses(res, survey_sim, flags = NULL, min_flags = 2))
Print and plot a fit comparison
Description
Print and plot a fit comparison
Usage
## S3 method for class 'fit_comparison'
print(x, digits = 3, ...)
## S3 method for class 'fit_comparison'
plot(x, lang = c("en", "es"), base_size = 11, ...)
Arguments
x |
An object returned by |
digits |
Number of decimals. |
... |
Not used. |
lang |
Language of the labels: |
base_size |
Base font size of the ggplot2 theme. |
Details
The plot has one panel per fit index, with the usual reference values as dashed lines (CFI and TLI .95, RMSEA .06, SRMR .08), and one panel for the factor correlations, if any, with a dashed line at 1. Each row is one exclusion. If the points barely move from row to row, the decision to exclude does not change the conclusions; if a point crosses a reference line, or the factor correlation changes a lot, the decision matters and should be reported. Exclusions with an improper solution are drawn in red.
Value
print() returns x invisibly. plot() returns a ggplot
object, printed on the current device and returned invisibly.
Examples
if (requireNamespace("lavaan", quietly = TRUE)) {
res <- scan_responses(survey_sim, items = paste0("B", 1:10))
cf <- compare_fit(res, survey_sim, type = "efa", nfactors = 1)
print(cf, digits = 2)
plot(cf, lang = "es")
}
Test for near-duplicate respondents
Description
Exact duplicates are easy to spot; edited copies (a row copied and then changed in two or three items) are not. For every respondent this function counts the items in which they differ from their most similar respondent (the nearest neighbour) and compares the median with two baselines:
Shuffled data: each item is shuffled on its own, which keeps the distribution of every item but breaks any link between rows. Genuine respondents are always somewhat closer than shuffled ones, because people with a high trait answer high almost everywhere, so this baseline alone is not evidence of copying.
A control (when
groupis given): samples of the reference group, of the size of the focal batch and of the same level whenmatch_level = TRUE, go through the same comparison. The statistic is the gap between shuffled and real distances. A focal gap well above the control gaps means rows closer to each other than genuine data of the same level would be.
As in compare_batches(), the control needs a reference clearly larger
than the batch. When the reference has fewer than min_ratio times the
focal respondents, each control sample is paired with a random subsample
of the batch of the same size, and p_control compares the median gap
of those focal subsamples (focal_gap_sample) with the control gaps.
Usage
neighbor_test(
data,
items = NULL,
group = NULL,
focal = NULL,
reference = NULL,
drop_flat = TRUE,
match_level = TRUE,
B = 500,
top = 10,
min_ratio = 3
)
Arguments
data |
A data frame with one row per respondent. |
items |
Item columns. By default, the items in |
group |
Optional batch of each respondent (a column name of |
focal |
Group (or groups) under examination. By default, the smallest group. |
reference |
Group (or groups) used as reference. By default, every other group. |
drop_flat |
Logical; remove respondents with the same answer in every item before comparing. |
match_level |
Logical; add the comparison with reference samples paired by level with the focal batch. |
B |
Number of shuffles and of control samples. |
top |
Number of closest pairs of the focal batch returned. |
min_ratio |
Minimum ratio between the reference and the focal group
for the whole batch to be compared in every sample. With a smaller
reference (even one smaller than the batch) the batch is subsampled to
|
Value
An object of class neighbor_test, a list with:
- table
Respondents, median nearest-neighbour distance (real and shuffled), their gap and the p value against the shuffles; with
group, also the median gap of the control samples and the p value against them (share of control gaps as large or larger). When the batch was subsampled,focal_gap_sampleis the median gap of the focal subsamples, the value compared with the control.- distances
One row per examined respondent: row, distance to the nearest neighbour and the row of that neighbour.
- pairs
The
topclosest pairs of rows and the items in which they differ.- null, settings
Values of the shuffles and control samples and the arguments used, kept for the plots.
See Also
order_test() and compare_batches().
Examples
nt <- neighbor_test(batch_sim, items = paste0("I", 1:12), group = "phase", B = 100)
nt
plot(nt)
plot(nt, type = "distance")
Print and plot a near-duplicate test
Description
print() shows the medians, the gap and the p values, and the closest
pairs. plot() draws one of two views, with ggplot2:
"null"With
group: histogram of the gap (shuffled minus real) in the control samples, with the focal gap as a vertical line. Withoutgroup: histogram of the shuffled medians with the real median."distance"Distribution of the nearest-neighbour distance in the examined group, in its shuffled version and in the control. Edited copies pile up at the left (one to three items of difference).
Usage
## S3 method for class 'neighbor_test'
print(x, ...)
## S3 method for class 'neighbor_test'
plot(
x,
type = c("null", "distance"),
lang = c("en", "es"),
base_size = 11,
...
)
Arguments
x |
An object returned by |
... |
Not used. |
type |
|
lang |
Language of the labels: |
base_size |
Base font size of the theme. |
Value
print() returns x invisibly. plot() returns a ggplot
object, printed on the current device and returned invisibly.
Examples
nt <- neighbor_test(batch_sim, items = paste0("I", 1:12), group = "phase", B = 100)
print(nt)
plot(nt, type = "distance", lang = "es")
Test whether consecutive rows are more alike than chance
Description
When a block of answers is filled by hand, each row tends to be a copy of the previous one with a few changes. That leaves a trace that does not need the submission time: consecutive rows resemble each other more than rows taken in a random order. In genuine data the order of arrival is unrelated to the answers, so the observed order should not be special.
Usage
order_test(
data,
items = NULL,
profile = NULL,
group = NULL,
time = NULL,
B = 5000
)
Arguments
data |
A data frame with one row per respondent, in the order of
submission (or give |
items |
Item columns. By default, every numeric column except
those named in |
profile |
Optional character vector with categorical columns (for example demographic data) whose repetition in consecutive rows is tested as well. |
group |
Optional batch of each respondent (a column name or a vector). The test is run within each batch, in its own order. |
time |
Optional submission time (column name or vector) used to sort the rows; by default the rows are taken in the order given. |
B |
Number of random orders. |
Details
For the items, the statistic is the mean number of items in which each
row differs from the previous one (items answered in both). Its null
distribution comes from B random orders of the same rows, and the
p value is the share of orders with a mean as low or lower. For the
profile columns (for example sex, age group and cycle), the statistic
is the share of consecutive rows with exactly the same profile, and the
p value is the share of random orders with a share as high or higher.
Respondents who answer together (the same classroom, the same session) can produce a mild order effect in genuine data. Use a group of known genuine data as a control: a batch is suspicious when its order effect is much stronger than the control's.
Value
An object of class order_test, a list with:
- table
One row per batch and statistic: respondents, observed value, mean of the random orders, p value.
- consecutive
One row per respondent after the first of its batch: original row, position, items that differ from the previous row and whether the profile is the same.
- null, settings
Values of the random orders and arguments used, kept for the plots.
See Also
neighbor_test() for near-duplicates in any order and
compare_batches() for the correlation structure.
Examples
ot <- order_test(batch_sim, items = paste0("I", 1:12),
profile = c("sex", "age"), group = "phase", B = 500)
ot
plot(ot)
plot(ot, type = "sequence")
Print and plot an order test
Description
print() shows, for each batch, the observed and the expected values and
the p value. plot() draws one of two views, with ggplot2:
"null"Histograms of the statistic in the random orders, with the observed order as a vertical line. Copying shows as a line far to the left (items) or to the right (profile) of the histogram.
"sequence"Items in which each row differs from the previous one, in order, with the value expected at random as a dashed line. A run of short bars marks a stretch of rows that resemble each other, the place to look first with the submission times.
Usage
## S3 method for class 'order_test'
print(x, ...)
## S3 method for class 'order_test'
plot(
x,
type = c("null", "sequence"),
lang = c("en", "es"),
base_size = 11,
...
)
Arguments
x |
An object returned by |
... |
Not used. |
type |
|
lang |
Language of the labels: |
base_size |
Base font size of the theme. |
Value
print() returns x invisibly. plot() returns a ggplot
object, printed on the current device and returned invisibly.
Examples
ot <- order_test(batch_sim, items = paste0("I", 1:12), group = "phase", B = 500)
print(ot)
plot(ot, type = "sequence", lang = "es")
Plot a response screening
Description
Ten views of the same screening, drawn with ggplot2:
"overview"Respondents flagged by each criterion. Bars do not add up: one person can cross several criteria.
"indices"Distribution of each index with its cut-off (dashed line). Look for tails or isolated bars far from the bulk.
"patterns"The most frequent response patterns; the dark part of each bar is the share that arrived in series. A very frequent pattern is suspicious only if it is implausible or arrives in series.
"heatmap"Every answer of every respondent (light = lowest option, dark = highest), with identical patterns grouped together and flagged respondents marked in red on the left. Blocks of identical rows reveal copied or repeated patterns.
"time"Minutes since the previous submission (log scale) along the collection period. Series appear as vertical piles of filled points below the dashed line.
"days"Submissions per day, split into series, other flagged respondents and the rest. Points to the session where something happened.
"overlap"How many respondents share each pair of flags (the diagonal is the total of each flag). Criteria that do not overlap detect different problems.
"profiles"Mean answer to each item (rescaled to 0-1, as answered) for series, other flagged respondents and the rest. A step between direct and reverse-worded items is the signature of a fixed pattern.
"styles"Proportion at the midpoint against proportion at the extremes, a map of response styles.
"scatter"Intra-individual variability against the Mahalanobis distance, with both cut-offs. Points in the left zone answer almost the same everywhere; points above the line answer unusually.
Usage
## S3 method for class 'response_scan'
plot(
x,
type = c("overview", "indices", "patterns", "heatmap", "time", "days", "overlap",
"profiles", "styles", "scatter"),
top = 10,
lang = c("en", "es"),
base_size = 11,
...
)
Arguments
x |
An object returned by |
type |
One of |
top |
Number of patterns shown by |
lang |
Language of the labels: |
base_size |
Base font size of the theme. |
... |
Not used. |
Value
A ggplot object, printed on the current device and returned
invisibly, so it can be modified with further layers or saved with
ggplot2::ggsave().
Examples
res <- scan_responses(survey_sim,
scales = list(A = paste0("A", 1:8), B = paste0("B", 1:10)),
reverse = paste0("A", 1:4), time = "submitted",
pattern_items = paste0("A", 1:8))
plot(res)
plot(res, type = "indices")
plot(res, type = "patterns", top = 8, lang = "es")
plot(res, type = "heatmap")
plot(res, type = "time")
plot(res, type = "days")
plot(res, type = "overlap")
plot(res, type = "profiles")
plot(res, type = "styles")
g <- plot(res, type = "scatter")
g + ggplot2::labs(title = "IRV and Mahalanobis")
Print, summarise and convert a response screening
Description
print() shows how many respondents each criterion flags, the most
frequent pattern and the longest series. summary() returns the main
tables. as.data.frame() returns one row per respondent with every index
and flag, ready to be merged with the original data by position.
Usage
## S3 method for class 'response_scan'
print(x, top = 3, ...)
## S3 method for class 'response_scan'
summary(object, top = 10, ...)
## S3 method for class 'summary.response_scan'
print(x, ...)
## S3 method for class 'response_scan'
as.data.frame(x, row.names = NULL, optional = FALSE, ...)
Arguments
x, object |
An object returned by |
top |
Number of patterns or series to show. |
... |
Not used. |
row.names, optional |
Ignored; present for compatibility with the generic. |
Value
print() returns x invisibly. summary() returns an object of
class summary.response_scan, a list with criteria (one row per
criterion with its rule, number and percentage of flagged respondents),
any (respondents with at least one flag), patterns (the top most
frequent patterns) and series (the top longest series).
as.data.frame() returns a data frame with the columns of x$indices
followed by the logical flags, prefixed with flag_, and n_flags.
Examples
res <- scan_responses(survey_sim, items = paste0("A", 1:8),
reverse = paste0("A", 1:4), time = "submitted")
summary(res)
out <- cbind(survey_sim, as.data.frame(res))
table(out$group, out$n_flags > 0)
Screen item responses for aberrant patterns
Description
One call computes, for every respondent, the usual indices of careless or aberrant responding and flags the cases that cross each criterion. It also tabulates how often each exact response pattern occurs and, when the submission time is available, detects identical patterns that arrive in series of consecutive submissions (forms filled one after another, answers dictated or copied).
Usage
scan_responses(
data,
items = NULL,
scales = NULL,
reverse = NULL,
range = NULL,
time = NULL,
pattern_items = NULL,
min_run = 3,
max_gap = 10,
person_fit = FALSE,
irv_quantile = 0.05,
mahal_p = 0.001,
syn_r = 0.6,
syn_min_pairs = 5,
dup_min_items = 15,
flat_min_items = 6,
eo_min_scales = 6,
reference = NULL,
ref_quantile = 0.05
)
Arguments
data |
A data frame with one row per respondent. |
items |
Character vector with the item columns. By default, every
numeric column of |
scales |
Optional named list of character vectors, one per scale or
subscale. Flat responding is evaluated within each scale, and response
ranges are inferred per scale. By default all |
reverse |
Optional character vector with the reverse-worded items. They are reverse-scored before the indices that assume a common direction (intra-individual variability, Mahalanobis distance, psychometric synonyms, person fit). Patterns, long strings and the heat map always use the responses as given. |
range |
Optional numeric vector |
time |
Optional submission time: a column name of |
pattern_items |
Items used to define a response pattern for the
frequency table and the serial detection. By default, |
min_run |
Minimum number of consecutive submissions with the same pattern to call them a series. |
max_gap |
Maximum minutes between two consecutive submissions of a series. |
person_fit |
Logical. If |
irv_quantile |
Respondents with some variability (IRV > 0) at or
below this quantile of the non-zero values are flagged. Respondents with
IRV = 0 answered the same option everywhere and are already covered by
|
mahal_p |
Significance level for the Mahalanobis distance. |
syn_r |
Minimum inter-item correlation for two items to be treated as psychometric synonyms. |
syn_min_pairs |
Minimum number of disjoint synonym pairs (each item
in one pair only, strongest pairs first) needed to evaluate |
dup_min_items |
Minimum number of items for |
flat_min_items |
Minimum number of items for a scale to be checked for flat responding. In a short scale (three or four items) many genuine respondents choose the same option everywhere. Shorter scales are skipped; when no scale is long enough, flat responding is judged on all items together. |
eo_min_scales |
Minimum number of scales with two or more items needed to compute the even-odd consistency. Each scale is split into its odd- and even-positioned items, and the person's odd and even scale means are correlated across scales (Spearman-Brown corrected). With fewer scales the index rests on too few points and is not evaluated. |
reference |
Optional rows that form a reference group of ordinary
respondents: a logical vector of length |
ref_quantile |
Tail probability used with |
Value
An object of class response_scan, a list with:
- indices
Data frame, one row per respondent:
row(position indata),longstring(longest run of identical consecutive answers),irv(intra-individual standard deviation after rescaling every item to 0-1),mahal_d2andmahal_p,psychsyn(within-person correlation across disjoint synonym pairs),evenodd(even-odd consistency, Spearman-Brown corrected),midpointandextreme(proportion of answers at the midpoint and at either end),patternandpattern_n(the response pattern and how many respondents share it),series(series identifier orNA) and, if requested,zh.- flags
Data frame of logical flags:
flat,low_irv,mahal,psychsyn,evenodd,duplicate,serialand, if requested,zh; plusn_flags.- patterns
Data frame with every distinct pattern, its frequency, percentage and how many of its cases belong to a series, sorted by frequency.
- series
Data frame with one row per detected series (start, end, submissions, minutes, median gap and pattern); empty without
time.- criteria
Data frame describing each criterion, its rule and the number and percentage of flagged respondents.
- responses, time, settings
The item responses as given, the submission time and the arguments used, kept for the plots.
References
Curran, P. G. (2016). Methods for the detection of carelessly invalid responses in survey data. Journal of Experimental Social Psychology, 66, 4-19. doi:10.1016/j.jesp.2015.07.006
Drasgow, F., Levine, M. V., & Williams, E. A. (1985). Appropriateness measurement with polychotomous item response models and standardized indices. British Journal of Mathematical and Statistical Psychology, 38(1), 67-86. doi:10.1111/j.2044-8317.1985.tb00817.x
Meade, A. W., & Craig, S. B. (2012). Identifying careless responses in survey data. Psychological Methods, 17(3), 437-455. doi:10.1037/a0028085
See Also
plot.response_scan() for the plots,
as.data.frame.response_scan() to merge the indices back into the data,
and compare_batches(), order_test() and neighbor_test() to judge a
whole batch of data rather than single respondents.
Examples
res <- scan_responses(survey_sim,
scales = list(A = paste0("A", 1:8), B = paste0("B", 1:10)),
reverse = paste0("A", 1:4), time = "submitted",
pattern_items = paste0("A", 1:8))
res
plot(res, type = "patterns")
plot(res, type = "heatmap")
head(as.data.frame(res))
# Cut-offs taken from an earlier collection (phase 1) to judge phase 2
res2 <- scan_responses(batch_sim, items = paste0("I", 1:12),
reference = batch_sim$phase == 1)
res2$criteria
# One by one, the hand-filled rows look ordinary: they are found by
# judging the batch as a whole, with compare_batches(), order_test()
# and neighbor_test()
table(batch_sim$source, res2$flags$n_flags > 0)
Simulated survey with known aberrant respondents
Description
Simulated answers of 300 respondents to two scales, with groups of
aberrant respondents planted on purpose so that every criterion of
scan_responses() has something to find. No real person is included.
Usage
survey_sim
Format
A data frame with 300 rows and 21 columns:
- id
Respondent number, in order of submission.
- submitted
Submission time (
POSIXct, UTC).- A1
Scale A, item 1; three options (1 = No, 2 = More or less, 3 = Yes), reverse-worded.
- A2
Scale A, item 2; three options (1 = No, 2 = More or less, 3 = Yes), reverse-worded.
- A3
Scale A, item 3; three options (1 = No, 2 = More or less, 3 = Yes), reverse-worded.
- A4
Scale A, item 4; three options (1 = No, 2 = More or less, 3 = Yes), reverse-worded.
- A5
Scale A, item 5; three options (1 = No, 2 = More or less, 3 = Yes).
- A6
Scale A, item 6; three options (1 = No, 2 = More or less, 3 = Yes).
- A7
Scale A, item 7; three options (1 = No, 2 = More or less, 3 = Yes).
- A8
Scale A, item 8; three options (1 = No, 2 = More or less, 3 = Yes).
- B1
Scale B, item 1; five options (1 to 5).
- B2
Scale B, item 2; five options (1 to 5).
- B3
Scale B, item 3; five options (1 to 5).
- B4
Scale B, item 4; five options (1 to 5).
- B5
Scale B, item 5; five options (1 to 5).
- B6
Scale B, item 6; five options (1 to 5).
- B7
Scale B, item 7; five options (1 to 5).
- B8
Scale B, item 8; five options (1 to 5).
- B9
Scale B, item 9; five options (1 to 5).
- B10
Scale B, item 10; five options (1 to 5).
- group
Planted group:
"typical","flat"(same option everywhere),"random","duplicate"(copy of another respondent) or"serial"(the same extreme pattern in scale A, submitted one to two minutes apart).
Source
Simulated with the script data-raw/make_survey_sim.R of the
package source.