Commenting Protocol
This page shows you how we comment our code and what the general protocol is.
- Each assigned function needs to have properly documented parameters, a title, one line of description and at least one example. It should follow roxygen2 syntax, and should be written in markdown. See the below Conjoint function for a good example of an overly detailed function (as all our functions should be!)
#' @import dplyr
#' @importFrom aws.s3 s3read_using
#' @importFrom readr read_csv
#' @importFrom readxl read_xlsx
#' @importFrom tools file_ext
#'
#' @title Read Conjoint Data
#'
#' @description Read conjoint data and return a list with Design and Answers
#' suitable for the rest of the `cjt_` functions family.
#'
#' @param path Path to a file (character) to be read or a dataframe object.
#'
#' This file or object should be a dataframe with `response_id` and columns containing `cjt` and `des_`.
#' We use [tidyselect::select_helpers] to determine the answers (`cjt`) and design (`des_`)
#'
#' @param type A character(1).
#' Type of conjoint experiment:
#' * `"CBC-FP"`: (default value) A full profile option with both attributes and levels.
#' * `"CBC-PP-NOLEV"`: A choice based conjoint that consists solely of attributes without any
#' levels that vary in an attribute. Typically contains a large number of attributes (50+) and is
#' thus required to be a partial profile design.
#'
#' @param none A character(1).
#' Type of none response option:
#' * `"NN"`: No None - (default value) There was no `none` choice option.
#' * `"SRN"`: Single-Response None. There was a third choice called none in the choices provided.
#' * `"DRN"`: Dual-Response None. There was a follow-up question asking if given the choice,
#' they'd actually choose it (e.g. would you actually buy the product).
#'
#' @param bucket A character(1). Name of the AWS S3 bucket. If provided data is read from AWS.
#'
#' @return A list.
#' * Two character(1) elements:
#' * `type`: Type of conjoint experiment
#' * `none`: Type of none response option
#' * Two tbl elements:
#' * `design`: Dataset with the design for each respondent
#' * `answers`: Dataset with the choices for each respondent
#'
#' @details
#'
#'
#'The Choice-based conjoint analysis (CBC) (also known as discrete-choice conjoint analysis) is the
#'most common form of conjoint analysis. Choice-based conjoint requires the respondent to choose their
#'most preferred full-profile concept. This choice is made repeatedly from sets of 3–5 full profile
#'concepts.
#'
#'This choice activity is thought to simulate an actual buying situation, thereby mimicking actual
#'shopping behavior. The importance and preference for the attribute features and levels can be
#'mathematically deduced from the trade-offs made when selecting one (or none) of the available choices.
#'Choice-based conjoint designs are contingent on the number of features and levels.
#'Often, that number is large and an experimental design is implemented to avoid respondent fatigue.
#'
#'The output of a Choice-based conjoint analysis provides excellent estimates of the importance of
#'the features, especially in regards to pricing. Results can estimate the value of each level
#'and the combinations that make up optimal products. Simulators report the preference and value
#'of a selected package and the expected choice share (surrogate for market share).
#'
#' @export
#'
#' @examples
#' # Read one of three example datasets available in the package.
#' cbc_fp <- cjt_read_toy_data("CBC-FP", none = 'SRN')
#' cbc_fp_drn <- cjt_read_toy_data("CBC-FP", none = 'DRN')
#' cbc_pp_nolev <- cjt_read_toy_data("CBC-PP-NOLEV")
#'
#' \dontrun{
#' # All the sources could also be read from the rds files.
#' # If bucket is provided the data is read from aws.
#' cjt_read_data(path = "path/to/spss/data/file.sav",
#' type = "yougov",
#' design_file = "path/to/design/data/file.csv",
#' bucket = "bucket/name")
#' }
cjt_read_data <- function(path,
type = c("CBC-FP",
"CBC-PP-NOLEV"),
none = c("NN",
"SRN",
"DRN"),
bucket = NULL) {
type <- match.arg(type)
none <- match.arg(none)
path_is_character <- is.character(path)
# If the path is a character, read the filepath. If not, we assume the object is the data frame.
if(path_is_character){
file_extension <- file_ext(path)
read_fnc <- switch(file_extension,
rds = readRDS,
sav = read_spss,
csv = read_csv,
xlsx = read_xlsx)
bucket_is_null <- is.null(bucket)
if (bucket_is_null) {
if (!file.exists(path)) {
stop("Incorrect file path.")
}
df <- read_fnc(path)
} else {
df <- s3read_using(FUN = read_fnc, object = path, bucket = bucket)
}
} else{
df <- path
}
answers <- df %>% select(response_id, contains('cjt'))
design <- df %>% select(response_id, contains('des_'))
list(type = type, none = none, design = design, answers = answers)
}
#' @export
#'
#' @rdname cjt_read_data
cjt_read_toy_data <- function(type = c("CBC-FP", "CBC-PP-NOLEV"),
none = c("NN",
"SRN",
"DRN")) {
type <- match.arg(type)
none <- match.arg(none)
switch(type,
`CBC-FP` = cjt_read_data(
get_package_data_path(paste0(type,
ifelse(none == "DRN", '-DRN', ''),
".csv")), type, none = none
),
`CBC-PP-NOLEV` = cjt_read_data(
get_package_data_path(paste0(type, ".csv")), type, none = none
))
}
get_package_data_path <- function(file) {
system.file("extdata", file, package = "g6tr.cjt")
}
globalVariables(c("read_spss"))
- Function’s code are explained with comments every 2-3 lines like above