Package {appkitr}


Title: Utilities to Work with 'GESIS AppKit' Data
Version: 2.0.0.5
Description: Provides helper functions for importing and processing survey data exported from the 'GESIS AppKit' platform https://www.gesis.org/en/gesis-appkit. Includes support for extracting variable and value labels from 'SPSS' syntax files, and automatically attaching these labels to raw CSV survey data for clean analysis.
License: Apache License (≥ 2)
URL: https://gitlab.com/gesis-appkit/appkitr, https://gesis-appkit.gitlab.io/appkitr
BugReports: https://gitlab.com/gesis-appkit/appkitr/-/work_items
Depends: R (≥ 4.1.0)
Imports: cli, stats, utils, withr
Suggests: testthat (≥ 3.0.0)
Config/roxygen2/version: 8.1.0
Encoding: UTF-8
LazyData: true
NeedsCompilation: no
Packaged: 2026-10-28 12:14:38 UTC; maxhaag
Author: Maximilian Haag ORCID iD [aut, cre], Charlotte de Alwis ORCID iD [aut], Julian Kohne ORCID iD [aut], GESIS - Leibniz Institute for the Social Sciences [cph]
Maintainer: Maximilian Haag <mail@mxhg.org>
Repository: CRAN
Date/Publication: 2026-11-13 16:40:27 UTC

Look up an AppKit Column Name by Key (Internal)

Description

Returns the export column name registered under a key in .appkit_cols.

Usage

.appkit_col(key)

Arguments

key

Single character string, a key from .appkit_cols.

Value

Character string, the corresponding export column name.


AppKit Export Metadata Columns (Internal)

Description

Registry of the metadata columns of AppKit survey exports. Survey item columns are not listed. appkitr never subsets data; unknown columns always pass through.

Usage

.appkit_cols

Format

A data frame with one row per metadata column and four fields:

key

Stable identifier used to reference the column in code.

column

Column name as it appears in AppKit exports.

timestamp

Whether the column is parsed as a timestamp.

min_version

Earliest AppKit version whose exports contain the column, NA if present in all supported versions.


AppKit Timestamp Columns (Internal)

Description

Returns the export column names registered as timestamps in .appkit_cols.

Usage

.appkit_timestamp_cols()

Value

Character vector of timestamp column names.


Apply Labels to Data Frame (Internal)

Description

Internal function to apply extracted variable and value labels to a data frame. Sets the "label" attribute for variables and converts variables with value labels into factors.

Usage

.apply_labels(df, labels)

Arguments

df

Data frame to apply labels to

labels

List containing var_labels and value_labels

Value

Data frame with labels applied


Extract Date from POSIXct (Internal)

Description

Internal function to extract date part from POSIXct

Usage

.as_date(x)

Arguments

x

POSIXct vector

Value

Date vector


Ask for a Validated Choice from a Set of Options (Internal)

Description

Internal function to repeat a console prompt until one of the given option codes is entered (case-insensitive).

Usage

.ask_choice(message, choices, choices_hint)

Arguments

message

Text shown to the user

choices

Character vector of valid option codes (lowercase)

choices_hint

Text describing the choices, shown on invalid input

Value

The matched choice (lowercase)


Ask for a Validated Non-Negative Number (Internal)

Description

Internal function to repeat a console prompt until a valid, non-negative number is entered.

Usage

.ask_number(message, max_decimals = NULL)

Arguments

message

Text shown to the user

max_decimals

Optional integer. If set, rejects input with more decimals (useful for currencies or whole numbers).

Value

A single numeric value


Ask for a Validated Yes/No Answer (Internal)

Description

Internal function to repeat a console prompt until "y"/"yes" or "n"/"no"

Usage

.ask_yes_no(message)

Arguments

message

Text shown to the user

Value

TRUE for yes, FALSE for no


Check a Data Frame for Required Columns (Internal)

Description

Internal function to check that a data frame contains the given columns, erroring informatively when any are missing. Works with arbitrary column names. For missing columns registered in .appkit_cols with a min_version, the error states the required AppKit export version.

Usage

.check_df_cols(df, cols, context = NULL)

Arguments

df

Data frame to check

cols

Character vector of required column names

context

Optional survey name used in error messages

Value

invisible(TRUE) if all columns are present


Drop participants from a single data frame

Description

Drop participants from a single data frame

Usage

.drop_from_df(df, participant_ids, id_col, context = NULL)

Arguments

df

A data frame.

participant_ids

Character vector of IDs to remove.

id_col

Column name containing participant IDs.

context

Optional survey name used in error messages.

Value

A list with data (filtered data frame), n_removed (integer), and ids_found (character vector of IDs that were present).


Extract Variable and Value Labels from SPSS Syntax File (Internal)

Description

Internal function to read an SPSS syntax file and extract variable and value labels with robust quote handling and apostrophe processing.

Usage

.extract_sps_labels(file)

Arguments

file

A character string specifying the path to an SPSS syntax file (.sps).

Value

A list containing var_labels and value_labels.


Extract Next Quoted String (Internal)

Description

Helper function to extract the next quoted string from text with proper apostrophe handling.

Usage

.extract_sps_next_quoted_string(text)

Arguments

text

Character string to parse

Value

List with content and end position, or NULL if no quote found


Extract Value-Label Pairs (Internal)

Description

Helper function to extract value-label pairs from SPSS syntax, properly handling apostrophes.

Usage

.extract_sps_value_label_pairs(text)

Arguments

text

Character string containing value-label pairs

Value

Named character vector of value-label mappings


Convert Character Columns to Logical (Internal)

Description

Internal function to convert character columns that contain only "true"/"false" (ignoring case) and NA values into logical columns.

Usage

.format_char_to_logical(df)

Arguments

df

Data frame to process

Value

Data frame with eligible character columns converted to logical


Format NA Values (Internal)

Description

Internal function to set specific values as NA with proper type checking.

Usage

.format_na_values(df, na_values)

Arguments

df

Data frame to process

na_values

List or vector of values to convert to NA

Value

Data frame with NA values set


Format Survey Data (Internal)

Description

Internal function to handle data formatting including NA values, logical conversion, and timestamp parsing.

Usage

.format_survey_data(
  df,
  na_values = NULL,
  timestamp_cols = .appkit_timestamp_cols()
)

Arguments

df

Data frame to format

na_values

Optional list or vector of values to treat as NA

timestamp_cols

Character vector of column names to parse as timestamps

Value

Formatted data frame


Format Timestamp Columns (Internal)

Description

Internal function to format specified timestamp columns. Replaces "FALSE" values with NA before calling timestamp parsing.

Usage

.format_timestamp_columns(df, timestamp_cols)

Arguments

df

Data frame to process

timestamp_cols

Character vector of column names to process as timestamps

Value

Data frame with formatted timestamp columns


Normalize survey input into a list of data frames

Description

Internal helper for participation_table() and calculate_payout(). Both functions accept either a single survey data frame or a list of survey data frames. The name for a single data frame is passed in via fallback_name. The functions participation_table() and calculate_payout() must compute their own deparse(substitute(data)) and pass the result in as fallback_name.

Usage

.normalize_survey_data(data, fallback_name)

Arguments

data

A single data frame, or a list of data frames.

fallback_name

Character. Name to use for data if it is a single data frame.

Value

A list of data frames.


Parse Timestamps with Multiple Formats (Internal)

Description

Internal function to parse timestamp columns with multiple format attempts. Tries ISO 8601 (AppKit >= 1.17.0) first, then falls back to older formats. Uses locale-safe parsing with English month names. If input is already POSIXct, returns it unchanged.

Usage

.parse_timestamps(
  timestamp_vector,
  orders = c("ymd_T_HMS_z", "ymd HMS", "dmy HMS", "ymd", "dmy")
)

Arguments

timestamp_vector

Character vector of timestamps to parse, or POSIXct vector

orders

Character vector of format orders. Can be simplified orders like "ymd HMS" or full format strings like "%Y-%m-%d %H:%M:%S%z"

Value

POSIXct vector of parsed timestamps


Report drop results for a single data frame

Description

Report drop results for a single data frame

Usage

.report_drop(result, participant_ids)

Arguments

result

List as returned by .drop_from_df().

participant_ids

The originally requested IDs.


Strip HTML Formatting (Internal)

Description

Internal helper to remove HTML tags from character values while preserving the enclosed text. Whitespace is normalized after tags are removed.

Usage

.strip_html(x)

Arguments

x

Character vector containing text that may include HTML formatting.

Value

Character vector with HTML tags removed.


Convert to Title Case (Internal)

Description

Internal function to convert strings to title case, replacing stringr::str_to_title

Usage

.to_title_case(x)

Arguments

x

Character vector to convert

Value

Character vector with title case


Example Entry Survey Data

Description

This is synthetic example data intended to allow users to test the package's functions. The variables are from a study conducted by the GESIS AppKit Team on measuring emotionality in social interactions through momentary assessments. This is the entry survey, which includes items from the affect intensity measure questionnaire.

Usage

appkit_survey_entry

Format

A data frame with 20 rows and 40 columns:

personalParticipantCode

PersonalParticipantCode

generalLoginCode

GeneralLoginCode

status

Participant Status

lastStatusChange

Last Status Change

note

Note

firstOpened

First Opened

committed

Committed

scheduled

Scheduled

expired

Expired

published

Published

exported

Exported

osVersion

OS Version

smartphoneType

SmartphoneType

pushNotificationAllowed

Push Notification Allowed

notificationType

Notification Type

notificationTitle

Notification Title

notificationText

Notification Text

age

How old are you (in years)?

sex

Which sex was assigned to you at birth?

gender

What is your gender?

aim01

When I feel happiness, it is a quite type of contentment.

aim02

When a person in a wheelchair can't get through a door, I have strong feelings of pity.

aim03

I get upset easily.

aim04

When I succeed at something, my reaction is calm contentment.

aim05

I get really happy or really unhappy.

aim06

I am a fairly quiet person.

aim07

When I'm happy, I feel fairly energetic.

aim08

Seeing a picture of some violent car accident in a newspaper makes me feel sick to my stomach.

aim09

When I'm happy, I feel like I'm bursting with joy.

aim10

I would be very upset, if I got a traffic ticket.

aim11

Looking at beautiful scenery really doesn't affect me much.

aim12

The weather doesn't affect my mood.

aim13

Others tend to get more excited than I do.

aim14

I am not an extremely enthusiastic individual.

aim15

Calm and cool could easily describe me.

aim16

When I'm feeling well it is easy for me to go from being in a good mood to being really joyful.

aim17

When I worry, it is so mild I hardly notice it.

aim18

I get overly enthusiastic.

aim19

My happy moods are so strong that I feel like I'm 'in heaven'.

aim20

When something bad happens, others tend to be more unhappy than I.


Example ESM Data

Description

This is synthetic example data intended to allow users to test the package's functions. The variables are from a study conducted by the GESIS AppKit Team on measuring emotionality in social interactions through momentary assessments. This is the experience sampling survey, which captures the momentary assessments of emotions in social interactions.

Usage

appkit_survey_esm

Format

A data frame with 180 rows and 36 columns:

personalParticipantCode

PersonalParticipantCode

generalLoginCode

GeneralLoginCode

status

Participant Status

lastStatusChange

Last Status Change

note

Note

firstOpened

First Opened

committed

Committed

scheduled

Scheduled

expired

Expired

published

Published

exported

Exported

osVersion

OS Version

smartphoneType

SmartphoneType

pushNotificationAllowed

Push Notification Allowed

notificationType

Notification Type

notificationTitle

Notification Title

notificationText

Notification Text

screening

Have you been part of any social interaction in the last two hours?

description

Please briefly describe the type of social interaction.

delay

How many minutes ago did this interaction take place?

duration

How long did the interaction last?

groupsize

How many people took part in the interaction (you included)?

partner_gender

What gender do you ascribe to your (main) interaction partner?

partner_close

How close do you consider the relationship to your (main) interaction partner?

interaction_quality

Please indicate your perceived quality of the interaction.

interaction_intimacy

Please indicate the intimacy of the interaction.

interaction_control

Please indicate your perceived degree of control over the interaction in comparison to your main interaction partner.

interaction_intensity

Please indicate the overall intensity of your emotional experience during the interaction.

emo_happy

Please indicate how happy you felt during the interaction.

emo_sad

Please indicate how sad you felt during the interaction.

emo_nervous

Please indicate how nervous you felt during the interaction.

emo_surprise

Please indicate how surprised you felt during the interaction.

emo_angry

Please indicate how angry you felt during the interaction.

emo_embarrassed

Please indicate how embarrassed you felt during the interaction.

emo_ashamed

Please indicate how ashamed you felt during the interaction.

dataquality

Thank you very much for supporting our research. For ensuring data quality, please indicate whether you answered the questions within this survey conscientiously:


Example Exit Survey Data

Description

This is synthetic example data intended to allow users to test the package's functions. The variables are from a study conducted by the GESIS AppKit Team on measuring emotionality in social interactions through momentary assessments. This is the exit survey, which includes items from the personal attributes questionnaire.

Usage

appkit_survey_exit

Format

A data frame with 20 rows and 33 columns:

personalParticipantCode

PersonalParticipantCode

generalLoginCode

GeneralLoginCode

status

Participant Status

lastStatusChange

Last Status Change

note

Note

firstOpened

First Opened

committed

Committed

scheduled

Scheduled

expired

Expired

published

Published

exported

Exported

osVersion

OS Version

smartphoneType

SmartphoneType

pushNotificationAllowed

Push Notification Allowed

notificationType

Notification Type

notificationTitle

Notification Title

notificationText

Notification Text

paqf1

I am emotional.

paqf2

I am able to devote myself completely to others.

paqf3

I am understanding.

paqf4

I am gentle.

paqf5

I am helpful to others.

paqf6

I am kind.

paqf7

I am unaware of the feelings of others.

paqf8

I am warm in relation to others.

paqm1

I am independent.

paqm2

I am a proactive person.

paqm3

I am competitive.

paqm4

I have difficulties making decisions.

paqm5

I give up easily.

paqm6

I feel superior.

paqm7

I am self-confident.

paqm8

I function well under pressure.


Calculate payout per participant based on survey participation

Description

Calculates the payout per participant according to a payout scheme. Supports two payment types per survey: a fixed amount per committed questionnaire, and/or a one-time bonus once a minimum number of committed questionnaires per survey is reached.

Usage

calculate_payout(
  data,
  payout_scheme,
  participant_col = .appkit_col("participant"),
  scheduled_col = .appkit_col("scheduled"),
  committed_col = .appkit_col("committed"),
  exported_col = .appkit_col("exported")
)

Arguments

data

Either a single survey data frame (as returned by read_appkit_survey()), or a list of survey data frames (as returned by read_appkit_surveys(), or assembled manually, e.g. list(entry = entry_survey, exit = exit_survey)).

payout_scheme

A data frame with one row per payout rule, and columns:

survey

Character. Survey name, must match a name in data.

amount

Numeric. Amount per questionnaire (default rule type, "per_questionnaire"), or one-time bonus amount ("threshold" rule type).

type

Optional. Character, either "per_questionnaire" (pay amount for every committed questionnaire in this survey) or "threshold" (pay amount once if the participant's committed count for this survey is >= threshold_n). Defaults to "per_questionnaire" for every row if the column is omitted entirely.

threshold_n

Optional. Integer, minimum number of committed questionnaires required for a "threshold" rule. Required (non-NA) only for rows with type = "threshold". Omit the column if you only use "per_questionnaire" rules.

participant_col

Character string naming the participant ID column (default: "personalParticipantCode").

scheduled_col

Character string naming the scheduled-timestamp column (default: "scheduled").

committed_col

Character string naming the committed-timestamp column (default: "committed").

exported_col

Character string naming the export-timestamp column, used internally by participation_table() (default: "exported").

Value

A data frame with one row per participant and one column per survey (payout amount for that survey), plus a total column (sum across all surveys).

Disclaimer

This function is provided as a calculation aid only. It comes with no guarantee of correctness. Always manually verify payout amounts before making any actual payments.

Examples

payout_scheme <- data.frame(
  survey = c("appkit_survey_esm", "appkit_survey_esm"),
  type = c("per_questionnaire", "threshold"),
  threshold_n = c(NA, 10),
  amount = c(2.00, 15.00)
)

payout <- calculate_payout(appkit_survey_esm, payout_scheme)
head(payout)


Interactively create a payout scheme

Description

This command walks the user through each survey in the input data, asking whether to include a payout rule for each one and, if so, which type(s). This avoids manually constructing a payout_scheme data frame, which might be more error-prone.

Usage

create_payout_scheme(data)

Arguments

data

Either a single survey data frame (as returned by read_appkit_survey()), or a list of survey data frames (as returned by read_appkit_surveys(), or assembled manually, e.g. list(entry = entry_survey, exit = exit_survey)).

Value

A payout_scheme data frame, suitable for calculate_payout().

See Also

calculate_payout()

Examples

if (interactive()) {
  payout_scheme <- create_payout_scheme(appkit_survey_esm)
  payout_scheme
}


Drop Participants from Survey Data

Description

Removes rows matching specified participant IDs from a data frame or a list of data frames (as returned by read_appkit_surveys()).

Usage

drop_participants(data, participant_ids, id_col = .appkit_col("participant"))

Arguments

data

A data frame or a named list of data frames.

participant_ids

Character vector of participant IDs to remove.

id_col

Character string naming the column that contains participant IDs (default: the AppKit participant code column "personalParticipantCode").

Details

When data is a list of data frames, the function applies the drop operation to each element and reports results per survey.

If any values in participant_ids are not found in the data, a warning is issued listing the unmatched IDs.

Value

Object of the same type as data, with matching rows removed.

Examples

# Drop two participants from the bundled example survey
ids <- appkit_survey_entry$personalParticipantCode[1:2]
entry_small <- drop_participants(appkit_survey_entry, ids)

# Drop participants from a named list of surveys
surveys <- list(entry = appkit_survey_entry)
surveys <- drop_participants(surveys, ids)


Inspect a Single Variable

Description

Extracts and formats information about a single variable including its label, unique values, and value labels.

Usage

inspect_variable(var, var_name = NULL, max_unique = 10, max_width = 50)

Arguments

var

The variable to inspect

var_name

The name of the variable (optional, auto-detected if not provided)

max_unique

Maximum number of unique values to display (default: 10)

max_width

Maximum width for displaying unique values (default: 50)

Value

A one-row data frame with variable information

Examples

# Inspect a single variable of the bundled example survey
var_info <- inspect_variable(appkit_survey_entry$aim01)


Inspect Variables in a Data Frame or Single Variable

Description

Provides a formatted overview of variables in a data frame, showing variable names, labels, unique values, and value labels. Can also inspect a single variable.

Usage

inspect_variables(data, max_unique = 10, max_width = 50, verbose = TRUE)

Arguments

data

A data frame or a single variable to inspect

max_unique

Integer indicating the maximum number of unique values to display (default: 10)

max_width

Integer indicating the maximum width for displaying unique values (default: 50)

verbose

Logical, if set to FALSE, suppresses all console output (default: TRUE)

Value

A tibble-like display of variable information (returned invisibly)

Examples

# Inspect all variables in the bundled example survey
inspect_variables(appkit_survey_entry)


Report committed questionnaires by participant

Description

Creates a table summarizing, for each participant, how many questionnaires they committed per survey, either as absolute counts or as a percentage.

Usage

participation_table(
  data,
  value = c("count", "percentage"),
  include_future_scheduled = FALSE,
  participant_col = .appkit_col("participant"),
  scheduled_col = .appkit_col("scheduled"),
  committed_col = .appkit_col("committed"),
  exported_col = .appkit_col("exported")
)

Arguments

data

Either a single survey data frame (as returned by read_appkit_survey()), or a list of survey data frames (as returned by read_appkit_surveys(), or assembled manually, e.g. list(entry = entry_survey, exit = exit_survey)).

value

Character. Either "count" (absolute number of committed questionnaires per participant per survey, default) or "percentage" (committed questionnaires as a percentage of that participant's total questionnaires recorded for that survey, i.e. a per-participant completion rate).

include_future_scheduled

Logical. The export contains rows for questionnaires scheduled in the future. Calculating percentages mid-study can therefore be misleading. If FALSE (default), rows with a scheduled timestamp after the export's exported timestamp are excluded; this requires AppKit >= 1.17.0. Set to TRUE to include them in the calculation.

participant_col

Character string naming the participant ID column (default: "personalParticipantCode").

scheduled_col

Character string naming the scheduled-timestamp column (default: "scheduled").

committed_col

Character string naming the committed-timestamp column (default: "committed").

exported_col

Character string naming the export-timestamp column, used as the reference time for include_future_scheduled. (default: "exported").

Value

A data frame with one row per participant and one column per survey (plus personalParticipantCode), containing counts or completion percentages. Participants are included if they appear in at least one of the supplied surveys.

Examples

# count of committed questionnaires per participant
survey_count <- participation_table(appkit_survey_esm, include_future_scheduled = TRUE)
head(survey_count)

# percentage of committed questionnaires per participant
survey_pct <- participation_table(
  appkit_survey_esm,
  value = "percentage",
  include_future_scheduled = TRUE
)
head(survey_pct)

# participation for multiple surveys, combined in a list
surveys_count <- participation_table(
  list(survey_esm = appkit_survey_esm, survey_exit = appkit_survey_exit),
  include_future_scheduled = TRUE
)
head(surveys_count)


Read AppKit Survey Data from Directory

Description

Reads an AppKit survey dataset from a directory containing both a CSV file and an SPS syntax file. Automatically applies variable and value labels, converts eligible character columns to logical, and handles NA values.

Usage

read_appkit_survey(
  survey_directory,
  na_values = list(-1, "", "Not applicable", "N/A"),
  timestamp_cols = .appkit_timestamp_cols()
)

Arguments

survey_directory

A character string specifying the path to a directory containing both a .csv data file and a .sps syntax file.

na_values

Optional list or vector of values to treat as NA (default: list(-1, "", "Not applicable", "N/A")). All specified values will be converted to NA across all columns with appropriate type handling.

timestamp_cols

Character vector of column names to parse as timestamps (default: the AppKit timestamp columns lastStatusChange, firstOpened, committed, scheduled, expired, published, exported). Columns not present in the data are ignored.

Details

The function performs the following operations

Value

A data frame containing the processed survey data with variable and value labels applied as attributes and appropriate data types set.

Examples

survey_dir <- system.file("extdata", "example_survey",
  package = "appkitr", mustWork = TRUE
)

# Read survey from directory with default settings
survey <- read_appkit_survey(survey_dir)

# Read survey and treat custom values as missing
survey <- read_appkit_survey(survey_dir, na_values = c(-1, -99))


Read Multiple AppKit Surveys from Directory

Description

Reads multiple AppKit surveys from a parent directory where each subdirectory contains one survey (CSV + SPS files). Returns a named list of data frames.

Usage

read_appkit_surveys(
  surveys_directory,
  na_values = list(-1, "", "Not applicable", "N/A"),
  duplicate_names = "error",
  timestamp_cols = .appkit_timestamp_cols()
)

Arguments

surveys_directory

A character string specifying the path to a directory containing subdirectories, each with survey data (CSV + SPS files).

na_values

Optional list or vector of values to treat as NA across all surveys (default: list(-1, "", "Not applicable", "N/A")). All specified values will be converted to NA across all columns with appropriate type handling.

duplicate_names

Character string specifying how to handle surveys with identical names. Options are:

"error"

(default) Throw an error when duplicate survey names are found

"merge"

Combine surveys with the same name using rbind()

"distinct"

Keep surveys distinct by adding numeric suffixes (e.g., "survey", "survey_2", "survey_3")

timestamp_cols

Character vector of column names to parse as timestamps across all surveys (default: the AppKit timestamp columns). Columns not present in a survey are ignored.

Value

A named list where each element is a processed survey data frame. Names are derived from the CSV filenames (with .csv extension removed and spaces replaced with underscores).

Examples

surveys_dir <- system.file("extdata", "example_surveys",
  package = "appkitr", mustWork = TRUE
)

# Read all surveys from a parent directory (default: error on duplicates)
surveys <- read_appkit_surveys(surveys_dir)

# Read surveys and merge those with identical names
surveys <- read_appkit_surveys(surveys_dir, duplicate_names = "merge")

# Read surveys and keep duplicates distinct with suffixes
surveys <- read_appkit_surveys(surveys_dir, duplicate_names = "distinct")

# Read surveys with custom NA values
surveys <- read_appkit_surveys(surveys_dir, na_values = c(-1, -99, ""))

# Access individual surveys
survey1 <- surveys[["survey_name_1"]]