如何调试在R中调用validate_and_run()的函数?

时间:2018-01-21 14:33:01

标签: r debugging rstudio

我想调试ShadowCAT包中的函数。 https://github.com/Karel-Kroeze/ShadowCAT/tree/master/R

从此包中获取任何内部函数,它们将通过validate_and_run()函数调用。如果我去了它,我直接呈现输出,我无法浏览我感兴趣的代码的每一行。我认为validate_and_run()创建一个调用函数的环境。

例如我正在尝试使用以下代码从包中调试shadowcat函数:

library(devtools)
install_github("Karel-Kroeze/ShadowCAT")
library(ShadowCAT)
debug(shadowcat)

alpha_beta <- simulate_testbank(model = "GPCM", number_items = 100, 
                                number_dimensions = 3, number_itemsteps = 3)
model <- "GPCM"
start_items <- list(type = 'fixed', item_keys = c("item33", "item5", "item23"), n = 3)
stop_test <- list(min_n = 4, max_n = 30, target = c(.1, .1, .1))
estimator <- "maximum_aposteriori"
information_summary <- "posterior_determinant"
prior_form <- "normal"
prior_parameters <- list(mu = c(0, 0, 0), Sigma = diag(3))

# Initial call: get key of first item to adminster
call1 <- shadowcat(answers = NULL, estimate = c(0, 0, 0), variance = as.vector(diag(3) * 25), 
                   model = model, alpha = alpha_beta$alpha, beta = alpha_beta$beta, 
                   start_items = start_items, stop_test = stop_test, 
                   estimator = estimator, information_summary = information_summary,
                   prior_form = prior_form, prior_parameters = prior_parameters)

在上面的shadowcat()函数中,编写了许多内部函数但我没有看到它们在shadowcat()中的任何地方被调用。我的推测是它在validate_and_run()函数中被调用。

我的问题是如何在shadowcat()内调试这些内部函数,看看每个变量存储的内容以及内部函数被调用时的输入是什么?

编辑1:

在任何常用的R函数中,当调试它时,您可以通过单击RStudio中的下一行来逐行移动调试光标(黄色突出显示的行)。此外,一旦您查看了该行代码,就可以通过在控制台上打印变量名来查看变量的值。我无法在shadowcat()函数中做到这一点。写入内部功能代码但从不以可见形式调用它们。我需要看看它们被调用的位置,需要通过它们进行调试

任何线索都表示赞赏。

编辑2 代码的主体:

function (answers, estimate, variance, model, alpha, beta, start_items, 
    stop_test, estimator, information_summary, prior_form = NULL, 
    prior_parameters = NULL, guessing = NULL, eta = NULL, constraints_and_characts = NULL, 
    lower_bound = NULL, upper_bound = NULL, safe_eap = FALSE, 
    eap_estimation_procedure = "riemannsum") 
{
    result <- function() {
        switch_to_maximum_aposteriori <- estimator == "maximum_likelihood" && 
            !is.null(lower_bound) && !is.null(upper_bound)
        estimator <- get_estimator(switch_to_maximum_aposteriori = switch_to_maximum_aposteriori)
        prior_form <- get_prior_form(switch_to_maximum_aposteriori = switch_to_maximum_aposteriori)
        prior_parameters <- get_prior_parameters(switch_to_maximum_aposteriori = switch_to_maximum_aposteriori)
        beta <- get_beta()
        guessing <- get_guessing()
        number_items <- nrow(alpha)
        number_dimensions <- ncol(alpha)
        number_itemsteps_per_item <- number_non_missing_cells_per_row(beta)
        lp_constraints_and_characts <- get_lp_constraints_and_characts(number_items = number_items)
        item_keys <- rownames(alpha)
        item_keys_administered <- names(answers)
        item_keys_available <- get_item_keys_available(item_keys_administered = item_keys_administered, 
            item_keys = item_keys)
        attr(estimate, "variance") <- matrix(variance, ncol = number_dimensions)
        estimate <- update_person_estimate(estimate = estimate, 
            answers_vector = unlist(answers), item_indices_administered = match(item_keys_administered, 
                item_keys), number_dimensions = number_dimensions, 
            alpha = alpha, beta = beta, guessing = guessing, 
            number_itemsteps_per_item = number_itemsteps_per_item, 
            estimator = estimator, prior_form = prior_form, prior_parameters = prior_parameters)
        continue_test <- !terminate_test(number_answers = length(answers), 
            estimate = estimate, min_n = stop_test$min_n, max_n = stop_test$max_n, 
            variance_target = stop_test$target, cutoffs = stop_test$cutoffs)
        if (continue_test) {
            index_new_item <- get_next_item(start_items = start_items, 
                information_summary = information_summary, lp_constraints = lp_constraints_and_characts$lp_constraints, 
                lp_characters = lp_constraints_and_characts$lp_chars, 
                estimate = estimate, model = model, answers = unlist(answers), 
                prior_form = prior_form, prior_parameters = prior_parameters, 
                available = match(item_keys_available, item_keys), 
                administered = match(item_keys_administered, 
                  item_keys), number_items = number_items, number_dimensions = number_dimensions, 
                estimator = estimator, alpha = alpha, beta = beta, 
                guessing = guessing, number_itemsteps_per_item = number_itemsteps_per_item, 
                stop_test = stop_test, eap_estimation_procedure = eap_estimation_procedure)
            key_new_item <- item_keys[index_new_item]
        }
        else {
            key_new_item <- NULL
        }
        list(key_new_item = as.scalar2(key_new_item), continue_test = as.scalar2(continue_test), 
            estimate = as.vector(estimate), variance = as.vector(attr(estimate, 
                "variance")), answers = answers)
    }
    update_person_estimate <- function(estimate, answers_vector, 
        item_indices_administered, number_dimensions, alpha, 
        beta, guessing, number_itemsteps_per_item, estimator, 
        prior_form, prior_parameters) {
        if (length(answers) > start_items$n) 
            estimate_latent_trait(estimate = estimate, answers = answers_vector, 
                prior_form = prior_form, prior_parameters = prior_parameters, 
                model = model, administered = item_indices_administered, 
                number_dimensions = number_dimensions, estimator = estimator, 
                alpha = alpha, beta = beta, guessing = guessing, 
                number_itemsteps_per_item = number_itemsteps_per_item, 
                safe_eap = safe_eap, eap_estimation_procedure = eap_estimation_procedure)
        else estimate
    }
    get_item_keys_available <- function(item_keys_administered, 
        item_keys) {
        if (is.null(item_keys_administered)) 
            item_keys
        else item_keys[-which(item_keys %in% item_keys_administered)]
    }
    get_beta <- function() {
        if (model == "GPCM" && is.null(beta) && !is.null(eta)) 
            row_cumsum(eta)
        else beta
    }
    get_guessing <- function() {
        if (is.null(guessing)) 
            matrix(0, nrow = nrow(as.matrix(alpha)), ncol = 1, 
                dimnames = list(rownames(alpha), NULL))
        else guessing
    }
    get_estimator <- function(switch_to_maximum_aposteriori) {
        if (switch_to_maximum_aposteriori) 
            "maximum_aposteriori"
        else estimator
    }
    get_prior_form <- function(switch_to_maximum_aposteriori) {
        if (switch_to_maximum_aposteriori) 
            "uniform"
        else prior_form
    }
    get_prior_parameters <- function(switch_to_maximum_aposteriori) {
        if (switch_to_maximum_aposteriori) 
            list(lower_bound = lower_bound, upper_bound = upper_bound)
        else prior_parameters
    }
    get_lp_constraints_and_characts <- function(number_items) {
        if (is.null(constraints_and_characts)) 
            NULL
        else constraints_lp_format(max_n = stop_test$max_n, number_items = number_items, 
            characteristics = constraints_and_characts$characteristics, 
            constraints = constraints_and_characts$constraints)
    }
    validate <- function() {
        if (is.null(estimate)) 
            return(add_error("estimate", "is missing"))
        if (is.null(variance)) 
            return(add_error("variance", "is missing"))
        if (!is.vector(variance)) 
            return(add_error("variance", "should be entered as vector"))
        if (sqrt(length(variance)) != round(sqrt(length(variance)))) 
            return(add_error("variance", "should be a covariance matrix turned into a vector"))
        if (is.null(model)) 
            return(add_error("model", "is missing"))
        if (is.null(alpha)) 
            return(add_error("alpha", "is missing"))
        if (is.null(start_items)) 
            return(add_error("start_items", "is missing"))
        if (is.null(stop_test)) 
            return(add_error("stop_test", "is missing"))
        if (is.null(estimator)) 
            return(add_error("estimator", "is missing"))
        if (is.null(information_summary)) 
            return(add_error("information_summary", "is missing"))
        if (!is.matrix(alpha) || is.null(rownames(alpha))) 
            return(add_error("alpha", "should be a matrix with item keys as row names"))
        if (!is.null(beta) && (!is.matrix(beta) || is.null(rownames(beta)))) 
            return(add_error("beta", "should be a matrix with item keys as row names"))
        if (!is.null(eta) && (!is.matrix(eta) || is.null(rownames(eta)))) 
            return(add_error("eta", "should be a matrix with item keys as row names"))
        if (!is.null(guessing) && (!is.matrix(guessing) || ncol(guessing) != 
            1 || is.null(rownames(guessing)))) 
            return(add_error("guessing", "should be a single column matrix with item keys as row names"))
        if (!is.null(start_items$type) && start_items$type == 
            "random_by_dimension" && length(start_items$n_by_dimension) %not_in% 
            c(1, length(estimate))) 
            return(add_error("start_items", "length of n_by_dimension should be a scalar or vector of the length of estimate"))
        if (!row_names_are_equal(rownames(alpha), list(alpha, 
            beta, eta, guessing))) 
            add_error("alpha_beta_eta_guessing", "should have equal row names, in same order")
        if (!is.null(beta) && !na_only_end_rows(beta)) 
            add_error("beta", "can only contain NA at the end of rows, no values allowed after an NA in a row")
        if (!is.null(eta) && !na_only_end_rows(eta)) 
            add_error("eta", "can only contain NA at the end of rows, no values allowed after an NA in a row")
        if (length(estimate) != ncol(alpha)) 
            add_error("estimate", "length should be equal to the number of columns of the alpha matrix")
        if (length(estimate)^2 != length(variance)) 
            add_error("variance", "should have a length equal to the length of estimate squared")
        if (is.null(answers) && !is.positive.definite(matrix(variance, 
            ncol = sqrt(length(variance))))) 
            add_error("variance", "matrix is not positive definite")
        if (model %not_in% c("3PLM", "GPCM", "SM", "GRM")) 
            add_error("model", "of unknown type")
        if (model != "GPCM" && is.null(beta)) 
            add_error("beta", "is missing")
        if (model == "GPCM" && is.null(beta) && is.null(eta)) 
            add_error("beta_and_eta", "are both missing; define at least one of them")
        if (model == "GPCM" && !is.null(beta) && !is.null(eta) && 
            !all(row_cumsum(eta) == beta)) 
            add_error("beta_and_eta", "objects do not match")
        if (estimator != "maximum_likelihood" && is.null(prior_form)) 
            add_error("prior_form", "is missing")
        if (estimator != "maximum_likelihood" && is.null(prior_parameters)) 
            add_error("prior_parameters", "is missing")
        if (!is.null(prior_form) && prior_form %not_in% c("normal", 
            "uniform")) 
            add_error("prior_form", "of unknown type")
        if (!is.null(prior_form) && !is.null(prior_parameters) && 
            prior_form == "uniform" && (is.null(prior_parameters$lower_bound) || 
            is.null(prior_parameters$upper_bound))) 
            add_error("prior_form_is_uniform", "so prior_parameters should contain lower_bound and upper_bound")
        if (!is.null(prior_form) && !is.null(prior_parameters) && 
            prior_form == "normal" && (is.null(prior_parameters$mu) || 
            is.null(prior_parameters$Sigma))) 
            add_error("prior_form_is_normal", "so prior_parameters should contain mu and Sigma")
        if (!is.null(prior_parameters$mu) && length(prior_parameters$mu) != 
            length(estimate)) 
            add_error("prior_parameters_mu", "should have same length as estimate")
        if (!is.null(prior_parameters$Sigma) && (!is.matrix(prior_parameters$Sigma) || 
            !all(dim(prior_parameters$Sigma) == c(length(estimate), 
                length(estimate))) || !is.positive.definite(prior_parameters$Sigma))) 
            add_error("prior_parameters_sigma", "should be a square positive definite matrix, with dimensions equal to the length of estimate")
        if (!is.null(prior_parameters$lower_bound) && !is.null(prior_parameters$upper_bound) && 
            (length(prior_parameters$lower_bound) != length(estimate) || 
                length(prior_parameters$upper_bound) != length(estimate))) 
            add_error("prior_parameters_bounds", "should contain lower and upper bound of the same length as estimate")
        if (is.null(stop_test$max_n)) 
            add_error("stop_test", "contains no max_n")
        if (!is.null(stop_test$max_n) && stop_test$max_n > nrow(alpha)) 
            add_error("stop_test_max_n", "is larger than the number of items in the item bank")
        if (!is.null(stop_test$max_n) && !is.null(stop_test$cutoffs) && 
            (!is.matrix(stop_test$cutoffs) || nrow(stop_test$cutoffs) < 
                stop_test$max_n || ncol(stop_test$cutoffs) != 
                length(estimate) || any(is.na(stop_test$cutoffs)))) 
            add_error("stop_test_cutoffs", "should be a matrix without missing values, and number of rows equal to max_n and number of columns equal to the number of dimensions")
        if (start_items$n == 0 && information_summary == "posterior_expected_kullback_leibler") 
            add_error("start_items", "requires n > 0 for posterior expected kullback leibler information summary")
        if (!is.null(start_items$type) && start_items$type == 
            "random_by_dimension" && length(start_items$n_by_dimension) == 
            length(estimate) && start_items$n != sum(start_items$n_by_dimension)) 
            add_error("start_items_n", "contains inconsistent information. Total length of start phase and sum of length per dimension do not match (n != sum(n_by_dimension)")
        if (!is.null(start_items$type) && start_items$type == 
            "random_by_dimension" && length(start_items$n_by_dimension) == 
            1 && start_items$n != sum(rep(start_items$n_by_dimension, 
            length(estimate)))) 
            add_error("start_items_n", "contains inconsistent information. Total length of start phase and sum of length per dimension do not match")
        if (!is.null(stop_test$cutoffs) && !is.matrix(stop_test$cutoffs)) 
            add_error("stop_test", "contains cutoff values in non-matrix format")
        if (!all(names(answers) %in% rownames(alpha))) 
            add_error("answers", "contains non-existing key")
        if (estimator %not_in% c("maximum_likelihood", "maximum_aposteriori", 
            "expected_aposteriori")) 
            add_error("estimator", "of unknown type")
        if (information_summary %not_in% c("determinant", "posterior_determinant", 
            "trace", "posterior_trace", "posterior_expected_kullback_leibler")) 
            add_error("information_summary", "of unknown type")
        if (estimator == "maximum_likelihood" && information_summary %in% 
            c("posterior_determinant", "posterior_trace", "posterior_expected_kullback_leibler")) 
            add_error("estimator_is_maximum_likelihood", "so using a posterior information summary makes no sense")
        if (estimator != "maximum_likelihood" && (!is.null(lower_bound) || 
            !is.null(upper_bound))) 
            add_error("bounds", "can only be defined if estimator is maximum likelihood")
        if (!is.null(lower_bound) && length(lower_bound) %not_in% 
            c(1, length(estimate))) 
            add_error("lower_bound", "length of lower bound should be a scalar or vector of the length of estimate")
        if (!is.null(upper_bound) && length(upper_bound) %not_in% 
            c(1, length(estimate))) 
            add_error("upper_bound", "length of upper bound should be a scalar or vector of the length of estimate")
        if (!no_missing_information(constraints_and_characts$characteristics, 
            constraints_and_characts$constraints)) 
            add_error("constraints_and_characts", "constraints and characteristics should either be defined both or not at all")
        if (!characteristics_correct_format(constraints_and_characts$characteristics, 
            number_items = nrow(alpha))) 
            add_error("characteristics", "should be a data frame with number of rows equal to the number of items in the item bank")
        if (!constraints_correct_structure(constraints_and_characts$constraints)) 
            add_error("constraints_structure", "should be a list of length three lists, with elements named 'name', 'op', 'target'")
        if (!constraints_correct_names(constraints_and_characts$constraints, 
            constraints_and_characts$characteristics)) 
            add_error("constraints_name_elements", "should be defined as described in the details section of constraints_lp_format()")
        if (!constraints_correct_operators(constraints_and_characts$constraints)) 
            add_error("constraints_operator_elements", "should be defined as described in the details section of constraints_lp_format()")
        if (!constraints_correct_targets(constraints_and_characts$constraints)) 
            add_error("constraints_target_elements", "should be defined as described in the details section of constraints_lp_format()")
    }
    invalid_result <- function() {
        list(errors = errors())
    }
    validate_and_run()
}

编辑3 validate_and_run()函数:

function () 
{
    .errors <- list()
    add_error <- function(key, value = TRUE) {
        .errors[key] <<- value
    }
    errors <- function() {
        .errors
    }
    validate_and_runner <- function() {
        if (exists("validate", parent.frame(), inherits = FALSE)) 
            do.call("validate", list(), envir = parent.frame())
        if (exists("test_inner_functions", envir = parent.frame(n = 2), 
            inherits = FALSE)) 
            get("result", parent.frame())
        else if (length(errors()) == 0) 
            do.call("result", list(), envir = parent.frame())
        else do.call("invalid_result", list(), envir = parent.frame())
    }
    for (n in ls(environment())) assign(n, get(n, environment()), 
        parent.frame())
    do.call("validate_and_runner", list(), envir = parent.frame())
}

0 个答案:

没有答案