Nothing
######################################################
# LAPOP "Multiple-Over" Breakdown Graph Pre-Processing #
######################################################
#' LAPOP "Multiple-Over" Breakdown Graphs
#'
#' This function creates a dataframe which can then be input in lapop_mover() for
#' comparing means across values of secondary variable(s) using LAPOP formatting.
#'
#' @param data A survey object. The data that should be analyzed.
#' @param outcome Character. Outcome variable(s) of interest to be plotted across secondary
#' variable(s).
#' @param grouping_vars A character vector specifying one or more grouping variables.
#' For each variable, the function calculates the average of the outcome variable,
#' broken down by the distinct values within the grouping variable(s).
#' @param rec Numeric. The minimum and maximum values of the frst outcome variable that
#' should be included in the numerator of the percentage. For example, if the variable
#' is on a 1-7 scale and rec is c(5, 7), the function will show the percentage who chose
#' an answer of 5, 6, 7 out of all valid answers. Can also supply one value only,
#' to produce the percentage that chose that value out of all other values.
#' Default: c(1, 1).
#' @param rec2 Numeric. Similar to 'rec' for the second outcome. Default: c(1, 1).
#' @param rec3 Numeric. Similar to 'rec' for the third outcome. Default: c(1, 1).
#' @param rec4 Numeric. Similar to 'rec' for the fourth outcome. Default: c(1, 1).
#' @param ci_level Numeric. Confidence interval level for estimates. Default: 0.95
#' @param mean Logical. If TRUE, will produce the mean of the variable rather than
#' recoding to percentage. Default: FALSE.
#' @param filesave Character. Path and file name to save the dataframe as csv.
#' @param cfmt Changes the format of the numbers displayed above the bars.
#' Uses sprintf string formatting syntax. Default is whole numbers for percentages
#' and tenths place for means.
#' @param ttest Logical. If TRUE, will conduct pairwise t-tests for difference
#' of means between all individual year-xvar levels and save them in attr(x,
#' "t_test_results"). Default: FALSE.
#' @param keep_nr Logical. If TRUE, will convert "don't know" (missing code .a)
#' and "no response" (missing code .b) into valid data (value = 99) and use them
#' in the denominator when calculating percentages. The default is to examine
#' valid responses only. Default: FALSE.
#'
#' @return Returns a data frame, with data formatted for visualization by lapop_mover
#'
#' @examples
#'\donttest{
#' require(lapop); data(ym23)
#'
#' # Set SUrvey Context
#' ym23lpr<-lpr_data(ym23)
#'
#' # Single DV
#' lpr_mover(data = ym23lpr,
#' outcome = "ing4",
#' grouping_vars = c("q1tc_r", "edre"),
#' rec = c(5, 7), ttest = FALSE)
#'
#' # Multiple DV
#' lpr_mover(data = ym23lpr,
#' outcome = c("ing4", "pn4"),
#' grouping_vars = c("q1tc_r", "edre"),
#' rec = c(5, 7), rec2 = c(1, 2),
#' ttest = FALSE)
#'
#' # Single DV X Single IV
#' lpr_mover(data = ym23lpr,
#' outcome="ing4",
#' grouping_vars="pn4",
#' rec=c(5,7),
#' ttest = FALSE)
#'
#' # Multiple DV X Single IV
#' lpr_mover(data = ym23lpr,
#' outcome=c("ing4", "pn4"),
#' grouping_vars="edre",
#' rec=c(5,7), rec2=c(1,2),
#' ttest = FALSE)
#'
#' # Multiple DV X Multiple IV
#' lpr_mover(data = ym23lpr,
#' outcome=c("ing4", "pn4"),
#' grouping_vars=c("edre", "q1tc_r"),
#' rec=c(5,7), rec2=c(1,2),
#' ttest = FALSE)
#'}
#'
#'@export
#'@import dplyr
#'@import srvyr
#'@import purrr
#'@import haven
#'
#'@author Luke Plutowski, \email{luke.plutowski@@vanderbilt.edu} && Robert Vidigal, \email{robert.vidigal@@vanderbilt.edu}
lpr_mover <- function(data,
outcome,
grouping_vars,
rec = list(c(1, 1)),
rec2 = c(1, 1),
rec3 = c(1, 1),
rec4 = c(1, 1),
ci_level = 0.95,
mean = FALSE,
filesave = "",
cfmt = "",
ttest = FALSE,
keep_nr = FALSE) {
if (keep_nr) {
data <- data %>%
mutate(across(all_of(outcome), ~ case_when(
na_tag(.) == "a" | na_tag(.) == "b" ~ 99,
TRUE ~ as.numeric(.)
)))
}
rec_list <- list(rec, rec2, rec3, rec4)
rec_list <- rec_list[seq_along(outcome)] # Ensure only as many rec values as outcomes
# Function to calculate means/proportions for a single outcome and grouping variable
calculate_means <- function(data, outcome_var, grouping_var, rec_range, single_outcome) {
if (!(grouping_var %in% names(data$variables))) {
stop(paste("Grouping variable", grouping_var, "not found in data."))
}
if (!(outcome_var %in% names(data$variables))) {
stop(paste("Outcome variable", outcome_var, "not found in data."))
}
data %>%
filter(!is.na(.data[[grouping_var]])) %>%
group_by(vallabel = haven::as_factor(.data[[grouping_var]])) %>%
{
if (mean) {
summarize(.,
prop = survey_mean(.data[[outcome_var]],
na.rm = TRUE,
vartype = "ci",
level = ci_level)
) %>%
mutate(proplabel = sprintf("%.1f", prop))
} else {
summarize(.,
prop = survey_mean(between(.data[[outcome_var]], rec_range[1], rec_range[2]),
na.rm = TRUE,
vartype = "ci",
level = ci_level) * 100
) %>%
mutate(proplabel = sprintf("%.0f%%", round(prop)))
}
} %>%
mutate(
outcome = if (!is.null(attributes(data$variables[[outcome_var]])$label)) {
attributes(data$variables[[outcome_var]])$label
} else {
outcome_var
},
varlabel = if (single_outcome) {
if (!is.null(attributes(data$variables[[grouping_var]])$label)) {
attributes(data$variables[[grouping_var]])$label
} else {
grouping_var
}
} else {
paste(grouping_var, outcome_var, sep = " x ")
},
vallabel = as.character(vallabel)
) %>%
rename(lb = prop_low, ub = prop_upp) %>%
select(outcome, varlabel, vallabel, prop, proplabel, lb, ub)
}
single_outcome <- length(outcome) == 1
# Apply function to each combination of outcome and grouping variable
mover <- map_dfr(grouping_vars, function(gvar) {
map2_dfr(outcome, rec_list, ~ calculate_means(data, .x, gvar, .y, single_outcome))
})
if (filesave != "") {
write.csv(mover, filesave)
}
# Conduct pairwise t-tests if requested
if (ttest) {
mover <- mover %>%
mutate(se = (ub - lb) / (2 * 1.96))
t_test_results <- data.frame(
outcome = character(),
varlabel = character(),
test = character(),
diff = numeric(),
ttest = numeric(),
pval = numeric(),
stringsAsFactors = FALSE
)
outcomes <- unique(mover$outcome)
for (oc in outcomes) {
mover_subset <- mover %>% filter(outcome == oc)
varlabels <- unique(mover_subset$varlabel)
for (vl in varlabels) {
group_subset <- mover_subset %>% filter(varlabel == vl)
for (i in 1:(nrow(group_subset) - 1)) {
for (j in (i + 1):nrow(group_subset)) {
prop1 <- group_subset$prop[i]
se1 <- group_subset$se[i]
prop2 <- group_subset$prop[j]
se2 <- group_subset$se[j]
diff <- prop1 - prop2
t_stat <- diff / sqrt(se1^2 + se2^2)
df <- (se1^2 + se2^2)^2 / ((se1^2)^2 / (nrow(data) - 1) + (se2^2)^2 / (nrow(data) - 1))
p_value <- 2 * pt(-abs(t_stat), df)
t_test_results <- rbind(t_test_results,
data.frame(outcome = oc,
varlabel = vl,
test = paste(group_subset$vallabel[i], "vs", group_subset$vallabel[j]),
diff = round(diff, 3),
ttest = round(t_stat, 3),
pval = round(p_value, 3)))
}
}
}
}
attr(mover, "t_test_results") <- t_test_results
}
return(mover)
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.