tidymodels / infer

@@ -1,10 +1,10 @@
Loading
1 1
#' Calculate summary statistics
2 2
#'
3 3
#' @description
4 -
#' 
5 -
#' Calculates summary statistics from outputs of [generate()] or 
4 +
#'
5 +
#' Calculates summary statistics from outputs of [generate()] or
6 6
#' [hypothesize()].
7 -
#' 
7 +
#'
8 8
#' Learn more in `vignette("infer")`.
9 9
#'
10 10
#' @param x The output from [generate()] for computation-based inference or the
@@ -23,10 +23,10 @@
Loading
23 23
#' @return A tibble containing a `stat` column of calculated statistics.
24 24
#'
25 25
#' @section Missing levels in small samples:
26 -
#' In some cases, when bootstrapping with small samples, some generated 
27 -
#' bootstrap samples will have only one level of the explanatory variable 
26 +
#' In some cases, when bootstrapping with small samples, some generated
27 +
#' bootstrap samples will have only one level of the explanatory variable
28 28
#' present. For some test statistics, the calculated statistic in these
29 -
#' cases will be NaN. The package will omit non-finite values from 
29 +
#' cases will be NaN. The package will omit non-finite values from
30 30
#' visualizations (with a warning) and raise an error in p-value calculations.
31 31
#'
32 32
#' @examples
@@ -34,18 +34,18 @@
Loading
34 34
#' # calculate a null distribution of hours worked per week under
35 35
#' # the null hypothesis that the mean is 40
36 36
#' gss %>%
37 -
#'  specify(response = hours) %>%
38 -
#'  hypothesize(null = "point", mu = 40) %>%
39 -
#'  generate(reps = 200, type = "bootstrap") %>%
40 -
#'  calculate(stat = "mean")
37 +
#'   specify(response = hours) %>%
38 +
#'   hypothesize(null = "point", mu = 40) %>%
39 +
#'   generate(reps = 200, type = "bootstrap") %>%
40 +
#'   calculate(stat = "mean")
41 41
#'
42 42
#' # calculate a null distribution assuming independence between age
43 43
#' # of respondent and whether they have a college degree
44 44
#' gss %>%
45 -
#'  specify(age ~ college) %>%
46 -
#'  hypothesize(null = "independence") %>%
47 -
#'  generate(reps = 200, type = "permute") %>%
48 -
#'  calculate("diff in means", order = c("degree", "no degree"))
45 +
#'   specify(age ~ college) %>%
46 +
#'   hypothesize(null = "independence") %>%
47 +
#'   generate(reps = 200, type = "permute") %>%
48 +
#'   calculate("diff in means", order = c("degree", "no degree"))
49 49
#'
50 50
#' # More in-depth explanation of how to use the infer package
51 51
#' \dontrun{
@@ -83,7 +83,7 @@
Loading
83 83
    } else if (
84 84
      stat %in% c(
85 85
        "mean", "median", "sum", "sd", "prop", "count", "diff in means",
86 -
        "diff in medians", "diff in props", "slope", "correlation", 
86 +
        "diff in medians", "diff in props", "slope", "correlation",
87 87
        "ratio of props", "odds ratio"
88 88
      )
89 89
    ) {
@@ -92,35 +92,41 @@
Loading
92 92
        "implemented) for `stat` = \"{stat}\". Are you missing ",
93 93
        "a `generate()` step?"
94 94
      )
95 -
      } else if (!(stat %in% c("Chisq", "prop", "count")) &
96 -
                 !(stat == "t" & (attr(x, "theory_type") == "One sample t"))) {
95 +
    } else if (!(stat %in% c("Chisq", "prop", "count")) &
96 +
      !(stat == "t" & (attr(x, "theory_type") == "One sample t"))) {
97 97
      # From `hypothesize()` to `calculate()`
98 98
      # Catch-all if generate was not called
99 -
#      warning_glue("You unexpectantly went from `hypothesize()` to ",
100 -
#                   "`calculate()` skipping over `generate()`. Your current ",
101 -
#                   "data frame is returned.")
99 +
      # warning_glue(
100 +
      #   "You unexpectantly went from `hypothesize()` to ",
101 +
      #   "`calculate()` skipping over `generate()`. Your current ",
102 +
      #   "data frame is returned."
103 +
      # )
102 104
      return(x)
103 105
    }
104 106
  }
105 -
  
107 +
106 108
  if (
107 -
    (stat %in% c("diff in means", "diff in medians", 
108 -
                 "diff in props", "ratio of props", "odds ratio")) ||
109 -
    (
110 -
      !is_nuat(x, "theory_type") &&
111 -
      (attr(x, "theory_type") %in% c("Two sample props z", "Two sample t"))
112 -
    )
109 +
    (stat %in% c(
110 +
      "diff in means", "diff in medians",
111 +
      "diff in props", "ratio of props", "odds ratio"
112 +
    )) ||
113 +
      (
114 +
        !is_nuat(x, "theory_type") &&
115 +
          (attr(x, "theory_type") %in% c("Two sample props z", "Two sample t"))
116 +
      )
113 117
  ) {
114 118
    order <- check_order(x, explanatory_variable(x), order)
115 119
  }
116 120
117 121
  if (!(
118 -
    (stat %in% c("diff in means", "diff in medians", 
119 -
                 "diff in props", "ratio of props", "odds ratio")) ||
120 -
    (
121 -
      !is_nuat(x, "theory_type") &&
122 -
      attr(x, "theory_type") %in% c("Two sample props z", "Two sample t")
123 -
    )
122 +
    (stat %in% c(
123 +
      "diff in means", "diff in medians",
124 +
      "diff in props", "ratio of props", "odds ratio"
125 +
    )) ||
126 +
      (
127 +
        !is_nuat(x, "theory_type") &&
128 +
          attr(x, "theory_type") %in% c("Two sample props z", "Two sample t")
129 +
      )
124 130
  )) {
125 131
    if (!is.null(order)) {
126 132
      warning_glue(
@@ -140,9 +146,9 @@
Loading
140 146
      "Your choice of `stat` is invalid for the types of variables `specify`ed."
141 147
    )
142 148
  }
143 -
#   else {
144 -
#     result <- append_infer_class(result)
145 -
#   }
149 +
  # else {
150 +
  #   result <- append_infer_class(result)
151 +
  # }
146 152
147 153
  result <- copy_attrs(to = result, from = x)
148 154
  attr(result, "stat") <- stat
@@ -162,7 +168,7 @@
Loading
162 168
calc_impl_one_f <- function(f) {
163 169
  function(type, x, order, ...) {
164 170
    col <- base::setdiff(names(x), "replicate")
165 -
    
171 +
166 172
    x %>%
167 173
      dplyr::group_by(replicate) %>%
168 174
      dplyr::summarize(stat = f(!!(sym(col)), ...))
@@ -180,7 +186,7 @@
Loading
180 186
calc_impl_success_f <- function(f, output_name) {
181 187
  function(type, x, order, ...) {
182 188
    col <- base::setdiff(names(x), "replicate")
183 -
    
189 +
184 190
    ## No longer needed with implementation of `check_point_params()`
185 191
    # if (!is.factor(x[[col]])) {
186 192
    #   stop_glue(
@@ -188,14 +194,14 @@
Loading
188 194
    #     "variable is not a factor."
189 195
    #   )
190 196
    # }
191 -
    
197 +
192 198
    if (is_nuat(x, "success")) {
193 199
      stop_glue(
194 200
        'To calculate a {output_name}, the `"success"` argument must be ',
195 -
        'provided in `specify()`.'
201 +
        "provided in `specify()`."
196 202
      )
197 203
    }
198 -
    
204 +
199 205
    success <- attr(x, "success")
200 206
    x %>%
201 207
      dplyr::group_by(replicate) %>%
@@ -204,12 +210,16 @@
Loading
204 210
}
205 211
206 212
calc_impl.prop <- calc_impl_success_f(
207 -
  f = function(response, success, ...) {mean(response == success, ...)},
213 +
  f = function(response, success, ...) {
214 +
    mean(response == success, ...)
215 +
  },
208 216
  output_name = "proportion"
209 217
)
210 218
211 219
calc_impl.count <- calc_impl_success_f(
212 -
  f = function(response, success, ...) {sum(response == success, ...)},
220 +
  f = function(response, success, ...) {
221 +
    sum(response == success, ...)
222 +
  },
213 223
  output_name = "count"
214 224
)
215 225
@@ -256,21 +266,26 @@
Loading
256 266
calc_impl.diff_in_medians <- calc_impl_diff_f(stats::median)
257 267
258 268
calc_impl.Chisq <- function(type, x, order, ...) {
259 -
  ## The following could stand to be cleaned up
269 +
  resp_var <- as.character(attr(x, "response"))
260 270
261 271
  if (is_nuat(x, "explanatory")) {
262 272
    # Chi-Square Goodness of Fit
263 273
    if (!is_nuat(x, "params")) {
264 274
      # When `hypothesize()` has been called
265 275
      p_levels <- get_par_levels(x)
266 -
      x %>%
267 -
        dplyr::summarize(
268 -
          stat = suppressWarnings(stats::chisq.test(
269 -
            # Ensure correct ordering of parameters
270 -
            table(!!(attr(x, "response")))[p_levels],
271 -
            p = attr(x, "params")
272 -
          )$stat
276 +
      chisq_gof <- function(df) {
277 +
        chisq <- suppressWarnings(stats::chisq.test(
278 +
          # Ensure correct ordering of parameters
279 +
          table(df[[resp_var]])[p_levels],
280 +
          p = attr(x, "params")
273 281
        ))
282 +
283 +
        unname(chisq[["statistic"]])
284 +
      }
285 +
286 +
      result <- x %>%
287 +
        dplyr::nest_by(.key = "data") %>%
288 +
        dplyr::summarise(stat = chisq_gof(data), .groups = "drop")
274 289
    } else {
275 290
      # Straight from `specify()`
276 291
      stop_glue(
@@ -280,61 +295,58 @@
Loading
280 295
      )
281 296
    }
282 297
  } else {
283 -
    # This is not matching with chisq.test
284 -
    # obs_tab <- x %>%
285 -
    #   dplyr::filter(replicate == 1) %>%
286 -
    #   dplyr::ungroup() %>%
287 -
    #   dplyr::select(!!attr(x, "response"), !!(attr(x, "explanatory"))) %>%
288 -
    #   table()
289 -
    # expected <- outer(rowSums(obs_tab), colSums(obs_tab)) / n
290 -
    # df_out <- x %>%
291 -
    #   dplyr::summarize(
292 -
    #     stat = sum(
293 -
    #       (table(!!(attr(x, "response")), !!(attr(x, "explanatory"))) -
294 -
    #          expected)^2 / expected,
295 -
    #       ...)
296 -
    #   )
297 -
298 298
    # Chi-Square Test of Independence
299 -
    result <- x %>%
300 -
      dplyr::do(
301 -
        broom::tidy(
302 -
          suppressWarnings(stats::chisq.test(
303 -
            table(
304 -
              .[[as.character(attr(x, "response"))]],
305 -
              .[[as.character(attr(x, "explanatory"))]]
306 -
            )
307 -
          ))
308 -
        )
309 -
      ) %>%
310 -
      dplyr::ungroup()
299 +
    expl_var <- as.character(attr(x, "explanatory"))
300 +
    chisq_indep <- function(df) {
301 +
      res <- suppressWarnings(stats::chisq.test(
302 +
        x = df[[expl_var]],
303 +
        y = df[[resp_var]]
304 +
      ))
305 +
306 +
      res[["statistic"]]
307 +
    }
311 308
312 -
    if (!is_nuat(x, "generate")) {
313 -
      result <- result %>% dplyr::select(replicate, stat = statistic)
314 -
    } else {
315 -
      result <- result %>% dplyr::select(stat = statistic)
309 +
    # Warn about possible unused factor levels
310 +
    if (has_unused_levels(x[[expl_var]])) {
311 +
      warning_glue("Explanatory variable has unused factor levels.")
312 +
    }
313 +
    if (has_unused_levels(x[[resp_var]])) {
314 +
      warning_glue("Response variable has unused factor levels.")
316 315
    }
317 316
318 -
    copy_attrs(
319 -
      to = result, from = x,
320 -
      attrs = c(
321 -
        "response", "success", "explanatory", "response_type",
322 -
        "explanatory_type", "distr_param", "distr_param2", "theory_type"
323 -
      )
324 -
    )
317 +
    # Compute result
318 +
    result <- x %>%
319 +
      dplyr::nest_by(.key = "data") %>%
320 +
      dplyr::summarise(stat = chisq_indep(data), .groups = "drop")
321 +
  }
322 +
323 +
  if (!is_nuat(x, "generate")) {
324 +
    result <- result %>% dplyr::select(replicate, stat)
325 +
  } else {
326 +
    result <- result %>% dplyr::select(stat)
325 327
  }
328 +
329 +
  copy_attrs(
330 +
    to = result, from = x,
331 +
    attrs = c(
332 +
      "response", "success", "explanatory", "response_type",
333 +
      "explanatory_type", "distr_param", "distr_param2", "theory_type"
334 +
    )
335 +
  )
326 336
}
327 337
328 338
calc_impl.function_of_props <- function(type, x, order, operator, ...) {
329 339
  col <- attr(x, "response")
330 340
  success <- attr(x, "success")
331 -
  
341 +
332 342
  x %>%
333 343
    dplyr::group_by(replicate, !!attr(x, "explanatory"), .drop = FALSE) %>%
334 344
    dplyr::summarize(prop = mean(!!sym(col) == success, ...)) %>%
335 345
    dplyr::summarize(
336 -
      stat = operator(prop[!!attr(x, "explanatory") == order[1]],
337 -
        prop[!!attr(x, "explanatory") == order[2]])
346 +
      stat = operator(
347 +
        prop[!!attr(x, "explanatory") == order[1]],
348 +
        prop[!!attr(x, "explanatory") == order[2]]
349 +
      )
338 350
    )
339 351
}
340 352
@@ -349,14 +361,14 @@
Loading
349 361
calc_impl.odds_ratio <- function(type, x, order, ...) {
350 362
  col <- attr(x, "response")
351 363
  success <- attr(x, "success")
352 -
  
364 +
353 365
  x %>%
354 366
    dplyr::group_by(replicate, !!attr(x, "explanatory"), .drop = FALSE) %>%
355 367
    dplyr::summarize(prop = mean(!!sym(col) == success, ...)) %>%
356 368
    dplyr::summarize(
357 369
      prop_1 = prop[!!attr(x, "explanatory") == order[1]],
358 370
      prop_2 = prop[!!attr(x, "explanatory") == order[2]],
359 -
      stat =  (prop_1 / prop_2) / ((1 - prop_1) / (1 - prop_2))
371 +
      stat = (prop_1 / prop_2) / ((1 - prop_1) / (1 - prop_2))
360 372
    ) %>%
361 373
    dplyr::select(stat)
362 374
}
@@ -385,7 +397,7 @@
Loading
385 397
  #   (stat == "slope")
386 398
  # ) {
387 399
  #   explan_string <- as.character(attr(x, "explanatory"))
388 -
  # 
400 +
  #
389 401
  #   x %>%
390 402
  #     dplyr::summarize(
391 403
  #       stat = summary(stats::lm(
@@ -393,7 +405,7 @@
Loading
393 405
  #       ))[["coefficients"]][explan_string, "t value"]
394 406
  #     )
395 407
  # }
396 -
  # 
408 +
  #
397 409
  # # Standardized correlation
398 410
  # else if (
399 411
  #   (attr(x, "theory_type") == "Slope/correlation with t") &&
@@ -410,25 +422,25 @@
Loading
410 422
  else if (attr(x, "theory_type") == "One sample t") {
411 423
    # For bootstrap
412 424
    if (!is_hypothesized(x)) {
413 -
      
414 425
      if (is.null(list(...)$mu)) {
415 426
        message_glue(
416 427
          "No `mu` argument was hypothesized, so the t-test will ",
417 428
          "assume a null hypothesis `mu = 0`."
418 429
        )
419 430
      }
420 -
      
431 +
421 432
      x %>%
422 433
        dplyr::summarize(
423 434
          stat = stats::t.test(!!attr(x, "response"), ...)[["statistic"]]
424 435
        )
425 -
      
426 436
    } else {
427 437
      # For hypothesis testing
428 438
      x %>%
429 439
        dplyr::summarize(
430 440
          stat = stats::t.test(
431 -
            !!attr(x, "response"), mu = attr(x, "params"), ...
441 +
            !!attr(x, "response"),
442 +
            mu = attr(x, "params"),
443 +
            ...
432 444
          )[["statistic"]]
433 445
        )
434 446
    }
@@ -442,7 +454,8 @@
Loading
442 454
    success <- attr(x, "success")
443 455
444 456
    x$explan <- factor(
445 -
      explanatory_variable(x), levels = c(order[1], order[2])
457 +
      explanatory_variable(x),
458 +
      levels = c(order[1], order[2])
446 459
    )
447 460
448 461
    aggregated <- x %>%
@@ -468,7 +481,7 @@
Loading
468 481
    df_out
469 482
  } else if (attr(x, "theory_type") == "One sample prop z") {
470 483
    # One sample proportion
471 -
    
484 +
472 485
    # When `hypothesize()` has been called
473 486
    success <- attr(x, "success")
474 487
@@ -476,10 +489,10 @@
Loading
476 489
    num_rows <- nrow(x) / length(unique(x$replicate))
477 490
478 491
    col <- attr(x, "response")
479 -
#     if (is.null(success)) {
480 -
#       success <- quo(get_par_levels(x)[1])
481 -
#     }
482 -
#     Error given instead
492 +
    # if (is.null(success)) {
493 +
    #   success <- quo(get_par_levels(x)[1])
494 +
    # }
495 +
    # Error given instead
483 496
484 497
    df_out <- x %>%
485 498
      dplyr::summarize(

@@ -2,7 +2,7 @@
Loading
2 2
#'
3 3
#' @description
4 4
#'
5 -
#' Compute a confidence interval around a summary statistic. Currently only
5 +
#' Compute a confidence interval around a summary statistic. Currently, only
6 6
#' simulation-based methods are supported.
7 7
#'
8 8
#' Learn more in `vignette("infer")`.

@@ -2,86 +2,93 @@
Loading
2 2
#'
3 3
#' @description
4 4
#'
5 -
#' Perform repeated sampling of samples of size n. Useful for creating sampling
6 -
#' distributions.
5 +
#' These functions extend the functionality of [dplyr::sample_n()] and
6 +
#' [dplyr::slice_sample()] by allowing for repeated sampling of data.
7 +
#' This operation is especially helpful while creating sampling
8 +
#' distributions—see the examples below!
7 9
#'
8 -
#' @param tbl Data frame of population from which to sample.
9 -
#' @param size Sample size of each sample.
10 +
#' @param tbl,.data Data frame of population from which to sample.
11 +
#' @param size,n Sample size of each sample.
10 12
#' @param replace Should sampling be with replacement?
11 13
#' @param reps Number of samples of size n = `size` to take.
12 -
#' @param prob A vector of probability weights for obtaining the elements of the
13 -
#'   vector being sampled.
14 +
#' @param prob,weight_by A vector of sampling weights for each of the rows in
15 +
#' `tbl`—must have length equal to `nrow(tbl)`.
14 16
#'
15 -
#' @return A tibble of size `rep` times `size` rows corresponding to `rep`
16 -
#'   samples of size n = `size` from `tbl`.
17 +
#' @return A tibble of size `rep * size` rows corresponding to `reps`
18 +
#'   samples of size `size` from `tbl`, grouped by `replicate`.
17 19
#'
18 -
#' @examples
19 -
#' suppressPackageStartupMessages(library(dplyr))
20 -
#' suppressPackageStartupMessages(library(ggplot2))
20 +
#' @details The [dplyr::sample_n()] function (to which `rep_sample_n()` was
21 +
#' originally a supplement) has been superseded by [dplyr::slice_sample()].
22 +
#' `rep_slice_sample()` provides a light wrapper around `rep_sample_n()` that
23 +
#' has a more similar interface to `slice_sample()`.
21 24
#'
22 -
#' # A virtual population of N = 10,010, of which 3091 are hurricanes
23 -
#' population <- dplyr::storms %>%
24 -
#'   select(status)
25 +
#' @examples
26 +
#' library(dplyr)
27 +
#' library(ggplot2)
25 28
#'
26 -
#' # Take samples of size n = 50 storms without replacement; do this 1000 times
27 -
#' samples <- population %>%
29 +
#' # take 1000 samples of size n = 50, without replacement
30 +
#' slices <- gss %>%
28 31
#'   rep_sample_n(size = 50, reps = 1000)
29 -
#' samples
30 32
#'
31 -
#' # Compute p_hats for all 1000 samples = proportion hurricanes
32 -
#' p_hats <- samples %>%
33 +
#' slices
34 +
#'
35 +
#' # compute the proportion of respondents with a college
36 +
#' # degree in each replicate
37 +
#' p_hats <- slices %>%
33 38
#'   group_by(replicate) %>%
34 -
#'   summarize(prop_hurricane = mean(status == "hurricane"))
35 -
#' p_hats
39 +
#'   summarize(prop_college = mean(college == "degree"))
36 40
#'
37 -
#' # Plot sampling distribution
38 -
#' ggplot(p_hats, aes(x = prop_hurricane)) +
41 +
#' # plot sampling distribution
42 +
#' ggplot(p_hats, aes(x = prop_college)) +
39 43
#'   geom_density() +
40 -
#'   labs(x = "p_hat", y = "Number of samples",
41 -
#'   title = "Sampling distribution of p_hat from 1000 samples of size 50")
42 -
#'
43 -
#' @importFrom dplyr pull
44 -
#' @importFrom dplyr inner_join
45 -
#' @importFrom dplyr group_by
44 +
#'   labs(
45 +
#'     x = "p_hat", y = "Number of samples",
46 +
#'     title = "Sampling distribution of p_hat"
47 +
#'   )
48 +
#'   
49 +
#' # sampling with probability weights. Note probabilities are automatically 
50 +
#' # renormalized to sum to 1
51 +
#' library(tibble)
52 +
#' df <- tibble(
53 +
#'   id = 1:5,
54 +
#'   letter = factor(c("a", "b", "c", "d", "e"))
55 +
#' )
56 +
#' rep_sample_n(df, size = 2, reps = 5, prob = c(.5, .4, .3, .2, .1))
46 57
#' @export
47 58
rep_sample_n <- function(tbl, size, replace = FALSE, reps = 1, prob = NULL) {
48 -
  n <- nrow(tbl)
49 -
50 59
  check_type(tbl, is.data.frame)
51 60
  check_type(size, is.numeric)
52 61
  check_type(replace, is.logical)
53 62
  check_type(reps, is.numeric)
54 63
  if (!is.null(prob)) {
55 64
    check_type(prob, is.numeric)
56 -
  }
57 -
58 -
  # assign non-uniform probabilities
59 -
  # there should be a better way!!
60 -
  # prob needs to be nrow(tbl) -- not just number of factor levels
61 -
  if (!is.null(prob)) {
62 -
    if (length(prob) != n) {
65 +
    if (length(prob) != nrow(tbl)) {
63 66
      stop_glue(
64 67
        "The argument `prob` must have length `nrow(tbl)` = {nrow(tbl)}"
65 68
      )
66 69
    }
67 -
68 -
    prob <- tibble::tibble(vals = levels(dplyr::pull(tbl, 1))) %>%
69 -
      dplyr::mutate(probs = prob) %>%
70 -
      dplyr::inner_join(tbl) %>%
71 -
      dplyr::select(probs) %>%
72 -
      dplyr::pull()
73 70
  }
74 71
72 +
  # Generate row indexes for every future replicate (this way it respects
73 +
  # possibility of  `replace = FALSE`)
74 +
  n <- nrow(tbl)
75 75
  i <- unlist(replicate(
76 76
    reps,
77 77
    sample.int(n, size, replace = replace, prob = prob),
78 78
    simplify = FALSE
79 79
  ))
80 -
  rep_tbl <- cbind(
81 -
    replicate = rep(1:reps, rep(size, reps)),
82 -
    tbl[i, ]
83 -
  )
84 -
  rep_tbl <- tibble::as_tibble(rep_tbl)
85 -
  names(rep_tbl)[-1] <- names(tbl)
86 -
  dplyr::group_by(rep_tbl, replicate)
80 +
81 +
  tbl %>%
82 +
    dplyr::slice(i) %>%
83 +
    dplyr::mutate(replicate = rep(seq_len(reps), each = size)) %>%
84 +
    dplyr::select(replicate, dplyr::everything()) %>%
85 +
    tibble::as_tibble() %>%
86 +
    dplyr::group_by(replicate)
87 +
}
88 +
89 +
#' @rdname rep_sample_n
90 +
#' @export
91 +
rep_slice_sample <- function(.data, n = 1, replace = FALSE, weight_by = NULL,
92 +
                             reps = 1) {
93 +
  rep_sample_n(.data, n, replace, reps, weight_by)
87 94
}

@@ -308,6 +308,17 @@
Loading
308 308
  }
309 309
}
310 310
311 +
has_unused_levels <- function(x) {
312 +
  if (is.factor(x)) {
313 +
    present_levels <- unique(as.character(x))
314 +
    unused_levels <- setdiff(levels(x), present_levels)
315 +
316 +
    length(unused_levels) > 0
317 +
  } else {
318 +
    FALSE
319 +
  }
320 +
}
321 +
311 322
# Helpers for hypothesize() -----------------------------------------------
312 323
313 324
match_null_hypothesis <- function(null) {
@@ -519,4 +530,4 @@
Loading
519 530
  }
520 531
  
521 532
  TRUE
522 -
}
Files Coverage
R 99.84%
Project Totals (15 files) 99.84%
1
comment:
2
  layout: "reach, diff, flags, files"
3
  behavior: default
4
  require_changes: false  # if true: only post the comment if coverage changes
5
  require_base: no        # [yes :: must have a base report to post]
6
  require_head: yes       # [yes :: must have a head report to post]
7
  branches: null
Sunburst
The inner-most circle is the entire project, moving away from the center are folders then, finally, a single file. The size and color of each slice is representing the number of statements and the coverage, respectively.
Icicle
The top section represents the entire project. Proceeding with folders and finally individual files. The size and color of each slice is representing the number of statements and the coverage, respectively.
Grid
Each block represents a single file in the project. The size and color of each block is represented by the number of statements and the coverage, respectively.
Loading