forcats/0000755000176200001440000000000013242624336011720 5ustar liggesusersforcats/tests/0000755000176200001440000000000012752645041013063 5ustar liggesusersforcats/tests/testthat.R0000644000176200001440000000007212752645041015045 0ustar liggesuserslibrary(testthat) library(forcats) test_check("forcats") forcats/tests/testthat/0000755000176200001440000000000013242624336014722 5ustar liggesusersforcats/tests/testthat/test-utils.R0000644000176200001440000000042113241141773017155 0ustar liggesuserscontext("test-utils.R") test_that("check_factor() fails when needed", { expect_error(check_factor(1), "factor") }) test_that("check_factor_list() fails when needed", { expect_error(check_factor_list(1), "list") expect_error(check_factor_list(list(1)), "factor") }) forcats/tests/testthat/helper-lump.R0000644000176200001440000000015012754332005017267 0ustar liggesuserslump_test <- function(x) { paste(ifelse(in_smallest(x), "X", letters[seq_along(x)]), collapse = "") } forcats/tests/testthat/test-count.R0000644000176200001440000000076013241136271017150 0ustar liggesuserscontext("test-count.R") test_that("0 count for empty levels", { f <- factor(levels = c("a", "b")) out <- fct_count(f) expect_equal(out$n, c(0, 0)) }) test_that("counts NA even when not in levels", { f <- factor(c("a", "a", NA)) out <- fct_count(f) expect_equal(out$n, c(2, 1)) }) test_that("sort = TRUE brings most frequent values to top", { f <- factor(c("a", "b", "b")) out <- fct_count(f, sort = TRUE) expect_equal(out$f, factor(c("b", "a"), levels = c("a", "b"))) }) forcats/tests/testthat/test-fct_c.R0000644000176200001440000000057013241142210017063 0ustar liggesuserscontext("fct_c") test_that("uses tidy_dots", { fs <- list(factor("a"), factor("b")) fab <- factor(c("a", "b")) expect_equal(fct_c(!!!fs), fab) expect_equal(fct_c(fs[[1]], fs[[2]]), fab) }) test_that("all inputs must be factors", { expect_error(fct_c("a"), "must be factors") }) test_that("empty input yields empty factor", { expect_equal(fct_c(), factor()) }) forcats/tests/testthat/test-fct_lump.R0000644000176200001440000001027213240076170017630 0ustar liggesuserscontext("fct_lump") test_that("positive values keeps most commmon", { f <- c("a", "a", "a", "b", "b", "c", "d", "e", "f", "g") expect_equal(levels(fct_lump(f, n = 1)), c("a", "Other")) expect_equal(levels(fct_lump(f, n = 2)), c("a", "b", "Other")) expect_equal(levels(fct_lump(f, prop = 0.25)), c("a", "Other")) expect_equal(levels(fct_lump(f, prop = 0.15)), c("a", "b", "Other")) }) test_that("ties are respected", { f <- c("a", "a", "a", "b", "b", "b", "c") expect_equal(levels(fct_lump(f, 1)), c("a", "b", "Other")) }) test_that("negative values drop most common" ,{ f <- c("a", "a", "a", "a", "b", "b", "b", "b", "c", "d") expect_equal(levels(fct_lump(f, n = -1)), c("c", "d", "Other")) expect_equal(levels(fct_lump(f, prop = -0.2)), c("c", "d", "Other")) }) test_that("return original factor when all element satisfy n / p condition", { f <- c("a", "a", "a", "b", "b", "c", "d", "e", "f", "g") expect_equal(levels(fct_lump(f, n = 4)), c("a", "b", "c", "d", "e", "f", "g")) expect_equal(levels(fct_lump(f, n = 10)), c("a", "b", "c", "d", "e", "f", "g")) expect_equal(levels(fct_lump(f, n = -10)), c("a", "b", "c", "d", "e", "f", "g")) expect_equal(levels(fct_lump(f, prop = 0.01)), c("a", "b", "c", "d", "e", "f", "g")) expect_equal(levels(fct_lump(f, prop = -1)), c("a", "b", "c", "d", "e", "f", "g")) }) test_that("different behaviour when apply tie function", { f <- c("a", "a", "a", "b", "b", "c", "d", "e", "f", "g") expect_equal(levels(fct_lump(f, n = 4, ties.method = "min")), c("a", "b", "c", "d", "e", "f", "g")) expect_equal(levels(fct_lump(f, n = 4, ties.method = "max")), c("a", "b", "Other" )) # Rank of c, d, e, f, g is (3+4+5+6+7)/5 = 5 expect_equal(levels(fct_lump(f, n = 4, ties.method = "average")), c("a", "b", "Other" )) expect_equal(levels(fct_lump(f, n = 5, ties.method = "average")), c("a", "b", "c", "d", "e", "f", "g")) expect_equal(levels(fct_lump(f, n = 4, ties.method = "first")), c("a", "b", "c", "d", "Other")) if (getRversion() >= "3.3.0") { expect_equal(levels(fct_lump(f, n = 4, ties.method = "last")), c("a", "b", "f", "g", "Other")) } }) test_that("NAs included in total", { f <- factor(c("a", "a", "b", rep(NA, 7))) o1 <- fct_lump(f, prop = 0.10) expect_equal(levels(o1), c("a", "Other")) o2 <- fct_lump(f, w = rep(1, 10), prop = 0.10) expect_equal(levels(o2), c("a", "Other")) }) test_that("bad weights generate error messages", { expect_error(fct_lump(letters, w = letters), "must be a numeric vector") expect_error(fct_lump(letters, w = 1:10), "must be the same length") expect_error(fct_lump(letters, w = rep(-1, 26)), "must be non-negative") }) test_that("values are correctly weighted", { f <- c("a", "a", "a", "b", "b", "c", "d", "e", "f", "g") w <- c( 0.2, 0.2, 0.6, 2, 2, 6, 4, 2, 2, 1) f2 <- c( "a", rep("b", 4), rep("c", 6), rep("d", 4), rep("e", 2), rep("f", 2), "g" ) expect_equal(levels(fct_lump(f, w = w)), levels(fct_lump(f2))) expect_equal( levels(fct_lump(f, n = 1, w = w)), levels(fct_lump(f2, n = 1)) ) expect_equal( levels(fct_lump(f, n = -2, w = w, ties.method = "first")), levels(fct_lump(f2, n = -2, ties.method = "first")) ) expect_equal( levels(fct_lump(f, n = 99, w = w)), levels(fct_lump(f2, n = 99)) ) expect_equal( levels(fct_lump(f, prop = 0.01, w = w)), levels(fct_lump(f2, prop = 0.01)) ) expect_equal( levels(fct_lump(f, prop = -0.25, w = w, ties.method = "max")), levels(fct_lump(f2, prop = -0.25, ties.method = "max")) ) }) # Default ----------------------------------------------------------------- test_that("lumps smallest", { expect_equal(lump_test(c(1, 2, 3, 6)), "Xbcd") expect_equal(lump_test(c(1, 2, 3, 7)), "XXXd") expect_equal(lump_test(c(1, 2, 3, 7, 13)), "XXXde") expect_equal(lump_test(c(1, 2, 3, 7, 14)), "XXXXe") }) test_that("doesn't lump if none small enough", { expect_equal(lump_test(c(2, 2, 4)), "abc") }) test_that("order doesn't matter", { expect_equal(lump_test(c(2, 2, 5)), "XXc") expect_equal(lump_test(c(2, 5, 2)), "XbX") expect_equal(lump_test(c(5, 2, 2)), "aXX") }) forcats/tests/testthat/test-reorder.R0000644000176200001440000000232413241141527017460 0ustar liggesuserscontext("test-reorder.R") test_that("can reorder by 2d summary", { df <- tibble::tribble( ~g, ~x, "a", 3, "a", 3, "b", 2, "b", 2, "b", 1 ) f1 <- fct_reorder(df$g, df$x) expect_equal(levels(f1), c("b", "a")) f2 <- fct_reorder(df$g, df$x, .desc = TRUE) expect_equal(levels(f2), c("a", "b")) }) test_that("can reorder by 2d summary", { df <- tibble::tribble( ~g, ~x, ~y, "a", 1, 10, "a", 2, 5, "b", 1, 5, "b", 2, 10 ) f1 <- fct_reorder2(df$g, df$x, df$y) expect_equal(levels(f1), c("b", "a")) f2 <- fct_reorder(df$g, df$x, .desc = TRUE) expect_equal(levels(f2), c("a", "b")) }) test_that("complains if summary doesn't return single number", { fun1 <- function(x, y) c(1, 2) fun2 <- function(x, y) "a" expect_error(fct_reorder("a", 1, fun1), "single number per group") expect_error(fct_reorder("a", 1, fun2), "single number per group") expect_error(fct_reorder2("a", 1, 2, fun1), "single number per group") expect_error(fct_reorder2("a", 1, 2, fun2), "single number per group") }) test_that("fct_infreq respects missing values", { f <- factor(c("a", "b", "b", NA, NA, NA), exclude = FALSE) expect_equal(levels(fct_infreq(f)), c(NA, "b", "a")) }) forcats/tests/testthat/test-as_factor.R0000644000176200001440000000054713241142430017756 0ustar liggesuserscontext("as_factor") test_that("equivalent to fct_inorder", { x <- c("a", "z", "g") expect_equal(as_factor(x), fct_inorder(x)) }) test_that("leaves factors as is", { f1 <- factor(letters) f2 <- as_factor(f1) expect_identical(f1, f2) }) test_that("supports NA (#89)", { x <- c("a", "z", "g", NA) expect_equal(as_factor(x), fct_inorder(x)) }) forcats/tests/testthat/test-rev.R0000644000176200001440000000022713241140440016603 0ustar liggesuserscontext("test-rev.R") test_that("reverses levels", { f1 <- factor(c("a", "b", "a")) f2 <- fct_rev(f1) expect_equal(levels(f2), c("b", "a")) }) forcats/tests/testthat/test-fct_relabel.R0000644000176200001440000000200013241142770020250 0ustar liggesuserscontext("fct_relabel") test_that("identity", { f1 <- factor(c("a", "b")) expect_identical(fct_relabel(f1, identity), f1) }) test_that("error if not function", { f1 <- factor("a") expect_error(fct_relabel(f1, 1), "function") }) test_that("error if level not character", { f1 <- factor("a") expect_error(fct_relabel(f1, function(x) 1), "character") }) test_that("error if level has different length", { f1 <- factor(letters) expect_error(fct_relabel(f1, function(x) x[-1]), "expected 26.*got 25") }) test_that("total collapse", { f1 <- factor(letters) new_levels <- function(x) rep("1", length(x)) expect_identical(fct_relabel(f1, new_levels), factor(new_levels(letters))) }) test_that("additional arguments", { f1 <- factor(letters) expect_identical(fct_relabel(f1, paste0, "."), factor(paste0(letters, "."))) }) test_that("formulas are coerced to functions", { f1 <- factor(letters) expect_identical( fct_relabel(f1, ~paste0(.x, ".")), factor(paste0(letters, ".")) ) }) forcats/tests/testthat/test-collapse.R0000644000176200001440000000100113241140030017573 0ustar liggesuserscontext("test-collapse.R") test_that("can collapse multiple values", { f1 <- factor(letters[1:3]) f2 <- fct_collapse(f1, x = c("a", "b"), y = "c") expect_equal(f2, factor(c("x", "x", "y"))) }) test_that("empty dots yields unchanged factor", { f1 <- factor(letters[1:3]) f2 <- fct_collapse(f1) expect_identical(f1, f2) }) test_that("can collapse missing levels", { f1 <- factor(c("x", NA), exclude = NULL) f2 <- fct_collapse(f1, y = NA_character_) expect_equal(f2, factor(c("x", "y"))) }) forcats/tests/testthat/test-fct_drop.R0000644000176200001440000000116213240104364017612 0ustar liggesuserscontext("fct_drop") test_that("doesn't add NA level", { f1 <- factor(c("a", NA), levels = c("a", "b")) f2 <- fct_drop(f1) expect_equal(levels(f2), "a") }) test_that("can optionally restrict levels to drop", { f1 <- factor("a", levels = c("a", "b", "c")) expect_equal(levels(fct_drop(f1, only = "b")), c("a", "c")) expect_equal(levels(fct_drop(f1, only = "a")), c("a", "b", "c")) }) test_that("preserves ordered class and attributes", { f1 <- ordered(letters[1:2], letters[1:3]) attr(f1, "x") <- "test" f2 <- fct_drop(f1) expect_s3_class(f2, "ordered") expect_equal(attr(f2, "x"), attr(f1, "x")) }) forcats/tests/testthat/test-shuffle.R0000644000176200001440000000026513241140611017445 0ustar liggesuserscontext("test-shuffle.R") test_that("reproducibility shuffles", { set.seed(1014) f1 <- factor(c("a", "b")) f2 <- fct_shuffle(f1) expect_equal(levels(f2), c("a", "b")) }) forcats/tests/testthat/test-shift.R0000644000176200001440000000060313241140304017121 0ustar liggesuserscontext("test-shift.R") test_that("can shift in either direction", { f1 <- factor(c("a", "b", "c")) f2_l <- fct_shift(f1, 1) expect_equal(levels(f2_l), c("b", "c", "a")) f2_r <- fct_shift(f1, -1) expect_equal(levels(f2_r), c("c", "a", "b")) }) test_that("0 shift leaves unchanged", { f1 <- factor(c("a", "b", "c")) f2 <- fct_shift(f1, 0) expect_identical(f1, f2) }) forcats/tests/testthat/test-lvls_reorder.R0000644000176200001440000000214613241142372020521 0ustar liggesuserscontext("lvls_reorder") test_that("changes levels, not values", { f1 <- factor(c("a", "b")) f2 <- factor(c("a", "b"), levels = c("b", "a")) expect_equal(lvls_reorder(f1, 2:1), f2) }) test_that("idx must be numeric", { f <- factor(c("a", "b")) expect_error(lvls_reorder(f, "a"), "must be numeric") }) test_that("must have one integer per level", { f <- factor(c("a", "b", "c")) expect_error(lvls_reorder(f, c(1, 2)), "one integer for each level") expect_error(lvls_reorder(f, c(1, 2, 2)), "one integer for each level") expect_error(lvls_reorder(f, c(1, 2.5)), "one integer for each level") }) test_that("can change ordered status of output", { f1 <- factor(letters[1:3]) f2 <- ordered(f1) expect_equal(is.ordered(lvls_reorder(f1, 1:3)), FALSE) expect_equal(is.ordered(lvls_reorder(f1, 1:3, ordered = FALSE)), FALSE) expect_equal(is.ordered(lvls_reorder(f1, 1:3, ordered = TRUE)), TRUE) expect_equal(is.ordered(lvls_reorder(f2, 1:3)), TRUE) expect_equal(is.ordered(lvls_reorder(f2, 1:3, ordered = FALSE)), FALSE) expect_equal(is.ordered(lvls_reorder(f2, 1:3, ordered = TRUE)), TRUE) }) forcats/tests/testthat/test-lvls.R0000644000176200001440000000246613240077457017016 0ustar liggesuserscontext("lvls") # lvls_expand ------------------------------------------------------------- test_that("changes levels, not values", { f1 <- factor(c("a")) f2 <- factor(c("a"), levels = c("a", "b")) expect_equal(lvls_expand(f1, c("a", "b")), f2) }) test_that("must include all existing levels", { f1 <- factor(c("a", "b")) expect_error(lvls_expand(f1, c("a", "c")), "include all existing levels") }) # lvls_revalue ------------------------------------------------------------ test_that("changes values and levels", { f1 <- factor(c("a", "b")) f2 <- factor(c("b", "a"), levels = c("b", "a")) expect_equal(lvls_revalue(f1, c("b", "a")), f2) }) test_that("can collapse values", { f1 <- factor(c("a", "b")) f2 <- factor(c("a", "a")) expect_equal(lvls_revalue(f1, c("a", "a")), f2) }) test_that("preserves missing values", { f1 <- factor(c("a", NA), exclude = NULL) f2 <- lvls_revalue(f1, levels(f1)) expect_equal(levels(f2), levels(f1)) }) test_that("`new_levels` must be a character", { f1 <- factor(c("a", "b")) expect_error(lvls_revalue(f1, 1:5), "character vector") }) test_that("`new_levels` must be same length as existing levels", { f1 <- factor(c("a", "b")) expect_error(lvls_revalue(f1, c("a")), "same length") expect_error(lvls_revalue(f1, c("a", "b", "c")), "same length") }) forcats/tests/testthat/test-fct_other.R0000644000176200001440000000104613241142307017770 0ustar liggesuserscontext("fct_other") test_that("keeps levels in keep", { x1 <- factor(c("a", "b")) x2 <- fct_other(x1, keep = "a") expect_equal(levels(x2), c("a", "Other")) }) test_that("drops levels in drop", { x1 <- factor(c("a", "b")) x2 <- fct_other(x1, drop = "a") # other always placed at end expect_equal(levels(x2), c("b", "Other")) }) test_that("must supply exactly one of drop and keep", { f <- factor(c("a", "b")) expect_error(fct_other(f), "supply one of") expect_error(fct_other(f, keep = "a", drop = "a"), "supply one of") }) forcats/tests/testthat/test-explicit_na.R0000644000176200001440000000074613241136610020320 0ustar liggesuserscontext("test-explicit_na.R") test_that("factor unchanged if no missing levels", { f1 <- factor(letters[1:3]) f2 <- fct_explicit_na(f1) expect_identical(f1, f2) }) test_that("converts implicit NA", { f1 <- factor(c("a", NA)) f2 <- fct_explicit_na(f1) expect_equal(f2, fct_inorder(c("a", "(Missing)"))) }) test_that("converts explicit NA", { f1 <- factor(c("a", NA), exclude = NULL) f2 <- fct_explicit_na(f1) expect_equal(f2, fct_inorder(c("a", "(Missing)"))) }) forcats/tests/testthat/test-fct_recode.R0000644000176200001440000000213513031476264020121 0ustar liggesuserscontext("fct_recode") test_that("warns about unknown levels", { f1 <- factor(c("a", "b")) expect_warning(f2 <- fct_recode(f1, d = "e"), "Unknown levels") expect_equal(levels(f2), levels(f1)) }) test_that("can collapse levels", { f1 <- factor(c("a1", "a2", "b1", "b2")) f2 <- factor(c("a", "a", "b", "b")) expect_equal(fct_recode(f1, a = "a1", a = "a2", b = "b1", b = "b2"), f2) }) test_that("can recode multiple levels to NA", { f1 <- factor(c("a1", "empty", "a2", "b", "missing")) f2 <- factor(c("a", NA, "a", "b", NA)) expect_equal(fct_recode(f1, NULL = "missing", NULL = "empty", a = "a1", a = "a2"), f2) }) test_that("can just remove levels", { f1 <- factor(c("a", "missing")) f2 <- factor(c("a", NA)) expect_equal(fct_recode(f1, NULL = "missing"), f2) }) # check_recode_levels ----------------------------------------------------- test_that("new levels must be character", { expect_error(check_recode_levels(a = 1), "Problems at positions: 1") }) test_that("new levels must be length 1", { expect_error(check_recode_levels(a = c("a", "b")), "Problems at positions: 1") }) forcats/tests/testthat/test-fct_relevel.R0000644000176200001440000000122013032731562020304 0ustar liggesuserscontext("fct_relevel") test_that("warns about unknown levels", { f1 <- factor(c("a", "b")) expect_warning(f2 <- fct_relevel(f1, "d"), "Unknown levels") expect_equal(levels(f2), levels(f1)) }) test_that("moves supplied levels to front", { f1 <- factor(c("a", "b", "c", "d")) f2 <- fct_relevel(f1, "c", "b") expect_equal(levels(f2), c("c", "b", "a", "d")) }) test_that("can moves supplied levels to end", { f1 <- factor(c("a", "b", "c", "d")) f2 <- fct_relevel(f1, "a", "b", after = 2) f3 <- fct_relevel(f1, "a", "b", after = Inf) expect_equal(levels(f2), c("c", "d", "a", "b")) expect_equal(levels(f3), c("c", "d", "a", "b")) }) forcats/tests/testthat/test-anon.R0000644000176200001440000000047213241137443016755 0ustar liggesuserscontext("test-anon.R") test_that("new levels are padded numerics", { f1 <- factor(letters[1:10]) f2 <- fct_anon(f1) expect_equal(levels(f2), sprintf("%02d", 1:10)) }) test_that("prefix added to start of level", { f1 <- factor("x") f2 <- fct_anon(f1, prefix = "X") expect_equal(levels(f2), "X1") }) forcats/NAMESPACE0000644000176200001440000000124513240100057013124 0ustar liggesusers# Generated by roxygen2: do not edit by hand S3method(as_factor,character) S3method(as_factor,factor) export("%>%") export(as_factor) export(fct_anon) export(fct_c) export(fct_collapse) export(fct_count) export(fct_drop) export(fct_expand) export(fct_explicit_na) export(fct_infreq) export(fct_inorder) export(fct_lump) export(fct_other) export(fct_recode) export(fct_relabel) export(fct_relevel) export(fct_reorder) export(fct_reorder2) export(fct_rev) export(fct_shift) export(fct_shuffle) export(fct_unify) export(fct_unique) export(last2) export(lvls_expand) export(lvls_reorder) export(lvls_revalue) export(lvls_union) importFrom(magrittr,"%>%") importFrom(stats,median) forcats/NEWS.md0000644000176200001440000000444013242605010013004 0ustar liggesusers# forcats 0.3.0 ## API changes * `fct_c()` now requires explicit splicing with `!!!` if you have a list of factors that you want to combine. This is consistent with an emerging standards for handling `...` throughout the tidyverse. * `fct_reorder()` and `fct_reorder2()` have renamed `fun` to `.fun` to avoid spurious matching of named arguments. ## New features * All functions that take `...` use "tidy" dots: this means that you use can `!!!` to splice in a list of values, and trailing empty arguments are automatically removed. Additionally, all other arguments gain a `.` prefix in order to avoid unhelpful matching of named arguments (#110). * `fct_lump()` gains `w` argument (#70, @wilkox) to weight value frequencies before lumping them together (#68). ## Improvements to NA handling * `as_factor()` and `fct_inorder()` accept NA levels (#98). * `fct_explicit_na()` also replaces NAs encoded in levels. * `fct_lump()` correctly acccounts for `NA` values in input (#41) * `lvls_revalue()` preserves NA levels. ## Minor improvements and bug fixes * Test coverage increased from 80% to 99%. * `fct_drop()` now preserves attributes (#83). * `fct_expand()` and `lvls_expand()` now also take character vectors (#99). * `fct_relabel()` now accepts objects coercible to functions by `rlang::as_function` (#91, @alistaire47) # forcats 0.2.0 ## New functions * `as_factor()` which works like `as.factor()` but orders levels by appearance to avoid differences between locales (#39). * `fct_other()` makes it easier to convert selected levels to "other" (#40) * `fct_relabel()` allows programmatic relabeling of levels (#50, @krlmlr). ## Minor improvements and bug fixes * `fct_c()` can take either a list of factors or individual factors (#42). * `fct_drop()` gains `only` argument to restrict which levels are dropped (#69) and no longer adds `NA` level if not present (#52). * `fct_recode()` is now checks that each new value is of length 1 (#56). * `fct_relevel()` gains `after` argument so you can also move levels to the end (or any other position you like) (#29). * `lvls_reorder()`, `fct_inorder()`, and `fct_infreq()` gain an `ordered` argument, allowing you to override the existing "ordered" status (#54). # forcats 0.1.1 * Minor fixes for R CMD check * Add package docs forcats/data/0000755000176200001440000000000012754676654012652 5ustar liggesusersforcats/data/gss_cat.rda0000644000176200001440000021734112754704400014752 0ustar liggesusersBZh91AY&SYC]@UUᖘt|$}u3`Zh!ҬDCD =Ѡ:( /A{@4^z(TքP R((UU@)G )=t6"ҏLeJkFȨU l-jafiz5+U9R P lҪm()VRI@PڶiZiJkjl f MEbE-: tT֮Sz J=P(Dr !U4-` 0H P( @@l@րʠC=1pQz TE tDJ JEP={ PSѥ*@-͖1b)oVڭ6D%h jdF!fPP` t4l)Z0B: ht:į@yP(PU^ƴ4R (@R"T%J$IP B%PJ Q "Un*zJ(  2" ȑS B!I44)hSmz$2L jx"HBFDz 1P= d4O$DFP2RTH5 4 JHOJyMģ6zdz(zOM6Q*`*~,xu\jOYY6˶M<:$=ٵQ Zv0[dngmT[+,AUā"X0EEYCpGGZQřQY"ZhiIl\یҍ;.lYP82mvutu;muf\DqnۺΫ." ($ig ^Fq}ҕM]e&]Fs}o#x"&o!'F/ ZQ{\^%;xgqZEIEֳ,x}fQ$B" C5/'nxq|cS9yKy7*@*K{GqMsݛgǤNKUIu{";P9٣b'T?ؾAn)Glgk(s`M]ɴGW=(4;(޽39ȔmklZՀR}z>ۛ[7'I8זּݼ#nZÒMDNR'g&BrPFgG/o=[j6B󆦗(0fVv,Wj+$㶰rgBe(m_;K$Jfpᵩv-eg VTT %vD9Fmnt,cg8ɵ mnA%Yt۳AEg)ېZ\LM;mm;Sb:ʒ@\Mc8Mb%.KAE%Id%g}9e>=z`F mNjEf J+`O+a[ce6Bn 5C`d!v̡pƈz!4Yd=qأ]8E19}^!!JVaH*(FjWm9ZrHB 7YekR@i `m \ -i%l(A4;6͍DH\|N"Dͺ\p Ek-d|Ѓ l9`$~y9gr7.6R.&0jy;!}G橐K?r XBجa \λe e.["mXM$k5U%D\XBfc4ZPњ[#4&jBJ 6uT7(SM0 6 @L4+&aQOwN U#KazǤsĦ䷵|cHlwCx#V@ʡeݚZ#("td-lh\HaX`ebEJZфD,8=nY92gl#SVFW4ٷa IW;(D!5&۩`V 5kҐ(hWM, R?}-'«UjCg&% 6 "KQ 8pk5da,i@%T u6&BAT(H]e2ǐ%4K5uP Z ,1&&-pl+7eTE$"ŕo[""֖\R"QiYhlF$ZYeC2U*dh,Et [.ܧ5ȵg4)-l"$6g*yiKj@# v@m1GաkZ@H .¬YK,axlr eBR+hc*.@ Fb0 aU14Jˀ2LYIjlf2ֳyUR2lHmB1ENv,[24P DG \ \՘PD`mͺHUJM&pi-) Xn؀AX^v( YR`pb l*`ZJ*FMD47k͛&ٺ VցJQZ`e3KfaJYmFƐ2DVDš%6ŷmfս⍖)$!TeK#4ARXVDՓDf&HB$,dkS\M\VZ(jH6 :>K"6бc TRrXiHdf`\BsT Ndcf:*]̒~\3ݳ5Z:QVɂ=)Dt4#$!0REn4* ʫv=50TO"KwA?ZH.tolyeiv<Ķ^]IKI'AvU2/ fƵDrM3keFY-Q29aʹ3ɱ%zuvYZu6f3@&[CR@%P8NÂdQehɴ[n8tU~tuge;3#mGwg-:ɷH]ZiIhu'ivg$g[c,.® ˲+6sk.(mNtuGqqgVY6ˡ@$E k1ŒJDu7ؾKZZAG<<"`Gfmk;(Ӕ%bi֖۽\y038۷$n8v$.:; ;G,63;0C~{~7 JC8ﵽ=͵r̉ldvD9eeIfu~kB)2l$eNHC+sJëNmpS? _:$:,ȋkr>D;2K0/6;Gp+*Nˊ(.(K+"̣ ;eev7YvVVaQGgvë We @03Zo4B@Mv1Q6A*%vt/J5&&&ͦu-!Fގ퉅\D9HQ7H"B nĂrXIڼe'w\17` ζ6yblY6ֵk:n賬. Vֳ/v¶ݜ$h6KgE KJňL:볤̢¬8;3(,qgGigZucbmДZJq(Rhs٢:]VUe%YG_^GrF]GvؙYUݝUgM" Ec;(wq6J8mqmҿw4K#! ˨YtTYkn*έq%# ֐KJhӤ8"#K))- TE!iݶ(3328&uiEFd "DgM'jCӽ䄄":-E,gaAKJMm`) 4gYGv;c, *:8m]jˬ*[FEUn#*HC45ҚB'sj*(;s΢Ц4δC-.932λ,.nJ3;;.2(8mٕuEtRZFڇQJm%;+";ˋmVgXT\vGgeqTQf]ewhTdtvYBFƑ)( &Ix:;4!&SPѤiZb t RY\qݘ ;㎴롶TQiQkAK R!B:16h 1)Ji(-҅%i [![(it+TPP%!M!FJhN˺Kӊ&CM-;b@Д&[.(Ӥ4(Z#8ҫ8ŗMChjRhiM FFҔSJRINl PaRM C1mBtMItkk bКMh4 H GM.4HWBRѣKFÎ;P:Ѡ1&٢JSNZ4 (bVJjJ %*]Ev$weehZAl kB M&vZt.44)Hi5we6(;KcJ+H[`u@:Cl)R[`h]:4hMPVg\'YvtEVWhJKl-qQZg\EAFJj FBi(m4KUvuݶ"EhiFq!J JZҚCC*4;#:NZ5@eiPBCkA*E:MIH 4DCC PqfVtutTQ +X+FHRwVQۨ:mZK:4:&TRJBҚ4 RҺJF)CHP!CHe+;+:"B:Sb )ZPJҸH- @:Q҆ր5KM&kK2..HJZѥ)(JiqS:(Ȑi4 uJ$";ά,: ]& VWq\uEƝgf] 4 @4Д@%M t.ЦBКi J44І(hBR Hh!I)HPt4&AAJVҭ+H44%(P&i)CKJJ&i: J @!tK D٤ZECJ @Bƕ(ҭ H+J -](ZFBJit@$+:;wtGXQAJP4PP4P.KKl"u]Zj $@$\?|ЫՅ=+说Aa6x$'=LZYXhh&Yg{Ђ pUo!^kXm(>T\01 `w{ƇNV'D"lpCIDWɑxtHujRnC ̎ӟz>:9)+ӮME>njȼJ '#bK\iOuCAu(Р@ߡH%žsӷ"Jgo zHuqi(u"g٤68Ѓͽun""A _ѡ6~c]d#+.uc(>-b3_2l3eG B!ovY>$~wgw ޜ׼yG!>qyPgH  hU3KoZEa8&Nx ~V(_DE䍏wgvyO9ЪaL컭D$>Y`1nۨzX@UTBh%$]RH:*53YC" T߮V[QYSNEhDwT+8;d9r}jJN"Sy [r'ȳW&(BBԿ>bp; u!(K쉆3obl]ŭi[Ȃ}kG^'8 fj`sP䵣Y}BA HpY B$z[%G XIv.+:؂eC,: "9jܛ\>~za=*q0 t(+P ECT ǯ?$!,+YX ^)Ž- Jck;t'7Jzv.붐$'ɫζ(@PF~ MTA+q xpxpC?g8O'є"H2 /ϻ2G_x@zq);H"|nt=cת3> qf'?K,B(I&vtg4VP7T+o {LVH"I؎\w/hI= ȏB9zޚsjb; C"nnXZ QOYZp0>y&.c\j4NW6ϫ.o?;HBz2i3L\4jQ6.Ω'i܅HGOH}@|b x4@2$V)Ia? *m9qpanLhD"'>l zGYEѣM)[E1q*=&  C,+&?8ut3=ȋKHfޙ`MA)Jm1& sMHB"7@ pu ^ҁ4EMb2~8&RsrD[ !ɭ~lw^W7(|Eb3^@̑"Z=P;M1887>.!zS>)L~eDDu=WJ#0Y'91 5eͼR' ÌBDT(906̈́ZTw]G&,K I} ~`ؒAyx0M}HN.FJ4>+~/~G4$F#46"Owc $FVi9 ɥʫhXoͩqᑉp7;@46 BnǞg=DLNb"[.9qI{ 5Jf!)! @Ӥlbx<.HugZ$^=DY~nt'yi+c_wfK cA;9LCbz*m7` jٚB6$AE/K=Z܀n&]t"O+Y/ P$]!@B3@RFĒ1V8 0D{I=_I,]ASZ3 MeO}om+Ć_ 40=Xo ߾L }XDD&6<=~JNxCh >|`$0GH||x!>Ȉ_K$c?9S)4<1CB$1\ brcHQ?7Q<2ZF-''mCtEY"m_EQQ#Gm_x Dv\ U/EPD_ybs,pƤ@7#_gHI4YRngizvyoqdI-`-OʻTDx_c&q&GC塐I6$:SfgY dbHƔg̕pX jk] . s؈5P #K] \z+ؚ *=xALIW8'ǪX0+VSb*?0Ia-a>{'m?6>;*B$,IڰPՆ^V}~3ZXbFtuieXp@<ҕ ?kŒ"#S ҂Hĩ 檵LxT =LT:^qk39'{)rC~ IJ#ӤLLjR ZO H]l~-~k+69b6Ӊ 3p- s&FHF>o3B`p+SR0$Ռev&iDEYDoG=99c{Yg ײy%I?L\d7̤B8 &j7<))YAuwD֔-wg߸(+L XZE &i]Ͻz^֗+>W$+G p.-a9RX 1,|hA'b| R"Aze 4q!s95߲0P #_9p1e )hQ](3j:4rCllNRee~~WίvYu`$Q$M SV@5EFl"C ";vhcH +n]R[g8tEz4r qpud<qU/zU!KH)RA5_QCk[S([y+hz|`]D쁓Dw&Qq}szҹ}H 6h_opF*U>޵z TLB`3n&Ģsh -n fd#P8!dnRH)=ۍə@xHsy₩oK,Kה4YvRJ #|94Vy`[M+Jl2H,-}QZ0>3,AatǓ 4(Obi!x\>B'PϮ+]83İ6{#3DI٣S&GMzlT)j,S/ reհV#ҩ$aT/i:u}śn!;y\?1"Vq&KFNG&qAC$by"M\~{!Z\ /7a1 :O]czESI^wQ.l磝Ftb0%vA$3)Gk"kd1XR(UiX[Hc]r݈gB\*Vf_3/\nHPAb!Y|zPpq[w$rhŏrYσb_= @gr1n340GVHK'ǔƹыu)Cgf(Yi~NA:F@č#C :H진.`u2F8ZjÊd2$mmX0 a힍S{!;tt@Ǿ= !3_ЈdnN$2J{.L# [LQxo‹1mECU b{!{h} C|ߩbzLx־".zxݾ JbHyl'9Od|dM2)'?gD9EqJ) )kȍeqRyh$i#6_F%xdI d !T?cޒZmwc%=Cm @τ~3ٿXp6"lƟH J۹BC .y^IK<3_}l`C$QOߘ蹌w:6EH+O>iQ=7hTҀ$lkӒ6Q{&D.PK@aWJ5>`L&G=AW Ho8<<%qxS"A!>0}6;629=K2ioϞI}NzDW}~}s?dK$8Ʒဈ䣴ϞMXpB@%$V>|~ ǩ/~ o$lXO׭CGT"e 3v4[4ڮT`v,sSR#\4H odIMpr`E"0]rޑ[@ʹK @O8 4ְ xD !L(FWb?K A AaFFlO x#|5+2.c[R@L}`0F!hLy,~lAM[tD7(R[.rV ~R-%,*\"Co|]8Py6ԬZ&p;OQbaTŊ(W4B6Eal1bBIM VP#>?^*& D;"Hv⨐A h"c1aђ Pz+3>$1<XhC" @dZx}#.ܕ,A{EDb|xcU;y79+3h_ kd +I y7ŢxX5hbJ bh3-L>nYG1Avsk<$Zd#aE-xqP$1]FOo<b@ܮl`;IJQ;H L![$!B!Z|?[ofl)}{^ة5%M] HnvT$2Cq(l0wkbvMk><28jFd`s,iYcEd%Bܸxc.*XkN< zMB3<5%z^1+5+.[+e"FDx+0RK mednׅ%Ē.f>9ݰ *WH 8 i.5ZpVlvH羻9^̾!q =Y58)9i]mB,[ L`eblٲ @b %@DIj}{Z>-UBB+PJVU*4wVh88:"8fJKsu<3izٛ1w =^!`Wz=vL% QƇq7,K W=>纍va^8aE:BFi>xO~WӺ=ǩ{ݷP3 /\&/O |-сԴ'tꈹGwd5˦>ı/n}{*!#AX#;BlJg|Qތ91=/ʴ(B>ä$ҞjLP#gv;D9#Qa #Cupf$KlIA$),40ЌkO BI[.R6 _u"1yQxY-t!UTy+T҃ԇݚ:`w^=>GM+dziqe4ȓ88qdn69J&@4_T+m,e"M)}DQ(;^o[On!/~s)lݣi+gS|z54@SrǠRewoꐣclq Y<i{Oo{s1r @ uwvt |KkAC;;"5Zߟv*z4j|"wYIyt(AHN36 HɛL hL#jDv4ȵeZE~p6d2!܁WH.xOB==N,[ q(H5 cZ̙d| GNCD'.T'0۫0J5I%X3fju 9FWnʩxyEGXZXnCL'E5-H8E9_LwTf F*ޕcFy< Ab:}gPvncx ۛH1=.ؐHdkHk*:Dvf̀R 9mCee !G6.K^GҀyd=["LE9,+2$ѴBG7o(eHߜH6K~6^vO,:޶6StPb6B$x=ฒzVQeg:(ۺ@aV0F,1%ٰ5LhҌYX)$uf[ ݬMm̀a[Y1;6Whiavf0baKQfD\ YHJ4h-r[B*%ݾw7^4u=12cݸzX;S3tZ)ƎxrŠTuo0\.l5qpZ$Im#IXvs}1X\ePUg4昪1v9g33z) Cb}̰uLne݃\Tftp]s*G-B% 90ځ6@]$dGt>[6yKK8R5ņc^)E`Ѩq3h1<Ŗ lNb hɁUx BQ&Vhi3*3N(7d o,0< mV@B@,eD ,V%K(O7-9 R9J#JahW.ӸD:ץ6S4om!Wn](".1> jPa9QBnBq`L`0lH읊ex/Ӈw#hcɷkMma/r3$qD& U0pG8eS~צ7 [ jV"&4 .جAJQIBy;-`l@bsg:v76zEX')ݑ:pwq drKϪ0iԐ) eM" !%Ԡ"uaq+8|"S*0!K7/U}7Yd@񗘲 oLxU 0%+ůFF^,-S"-PAD$^u :U2I!S1ŹkɻY:HNi0!Zs&p,A\ PY S[hK3&33&jźVAbz^60PÖ38ۀԀTT3w 9YrMQ4U1<\x!Y 0F/'F²kB9O]5;𘢣wJb8h@J eȔb5'%-;d4z v3<:V&GHyg 4̼eba~k,$'uxi iI&dy}[]t gFCq.jXat@"$ 1n BXRxNÐf _,c[HPq & ]aǡmR'r%x &4l=\C3oh`K9Cp2+sY{Ί?df`" 6Py~ پlkRgu}XmHS!cTbecq!@'B%82AC+y#K%@usI1qw!& ,-(H\e* &6dڀdiYkeub@&]ikKM$H"!BU fpթC vַV;f=1Xt!TcemmȐR"eE`1d8#X*+lwmD ` Q)B)fXKsmzwyyݧ֛f"@ 1c nܠ- UߕH,].\" j@r+LM%ft6 %2¥l &RhshfZ>_8/֭266ɖ/ٱ])\ 9>Q}.֊4D5#edip !YB\l-e%5nJ $ذ@v$mG`H"]%7eղ2 K)D1hK[vޣAHݖ@!5 kUXYI)!V&v؎2>֓6 (!1,c8Y7hp U#U0 F0^ɣD(EZ"B*R!& .2ji( e`M֚ۈDX9a.n&R& ٔ4dγݝe>YFxi#Y ۔~< X^2&фG0$j>yPL p*O{ ʌ)aYVs7HdI $l%9l]' 2D%ZbI4M GlXB&@1$f罞u"+==+|y"<1d%x{,8|󜐚9+kHKV nօ%Ƴ Ie8$̀S+ "$3]Uj)Fl#!%)"Hm B0k ;qXj[J۔F 4S `+ݔ HSX-exz" |`ӟdm>vtci%4!}l/ڰp9 +Cq!H3zw]Cv; .K o~>l6^=9Kq8;eo J)DsS<8Kpf$I L1%M25t l!r{UtQ &U[њ]7Nk95k Snmi\ϧ4A0>wvsǃ H,+HԊ\J6mNj}' 5ң5y;mT,QLL0̈́2$fY*Hm p(~!.Gݲu\($6%/ D) ILR԰!'-4 rÌH([B8@JJ [zYzټ:tFk` \mLՖ,1 [I@ ru ι;11:ul@ )(#7zZP7—=j<\VE2Hx"R73zHL a%\Fh`T!tGH_G>=(zAٺ$S< i۔ IVܫEm)- %%$LaOzl7'!pmI4:pAP`a0ZX T%(RYW;GJt=NcLB1:(*a#<5äxhF"H37y8Y}Ȕû[b.I "O<,xĉ@60` i&j,"3u' #+ ,!YN{pzvN=;eȥyY-0fDIl+|$a @a.FDlh5@$ctŖϓ! P6y3OWmA==ϥ癃F}qUޝ5W ڃ'ʰȲ5pfNYhYx?_}]30P75uow~A4L6IIDLV#AmͰYJFn7XFDKL qnȱ Zovh.a K֬mF(V! WmM9,KM r aRM015ReP"BWn;q`إm D[la+K-yA==tW)% -len5+mJC )Lk( i3Iuݎĉh$ep&2\W!r'o{{/8Lȕg}<y[ǽe^ Mę5H[qBJc5PH(a 04MI43dm53P8d2S!N{1vkJ@Uݻ͑ٸҶ@k4v0$\@iIerQ$J1QYF))(i[Yqӥ&r8ARC^lleYmB0 aQ"dKӾvR#Fs\JB'L;$BX5eRJR&JJBm$S1f6)%b*;`pRb1-}>lm*td"`I!S.Ȑ!D%3 Ѽ;!( a[F҂A P1 c&$KA.A6R ,slJہk™ۡV"5( 0 [!!+1$!Y/۶DI*+d e0W%R R"I}}>폴Ly}݄yyV n".XM WIEelq#$!HnX$! Rbe0 T.wni "HDϾ|i{e0"ξ]5ݱ[%)M3WDQ -9L* E4n+ҳI4T4JGiM$7mlh𣣩yBR"Ai.R@UKpZa<ɤ4)'smL"HbVbd "H4%%9d˥,r ʔT] Q.0Y)IBDI EP"Y Ѻz7vԐ'7nme|(}O{[I&[R$H0ך$8L @cQXv 5ZDdH#v$4mA  +b8 IIScwmܜwxcKfUM2h4{&dm{yYe-yOomYE|ܻ&6w>e|Ӏmr`d])XSwK42l)n[KXAr8m)2&ZKR602rd+K,4a$۫i,2%! YDRa Ёm&\f@f+L 2ī@ Hݹ(]e vՁun&Ai+k©&b, $434Ҙc KRWLbJe&# m@%&S-aZ"H[jca0"d "hiu$ eif]yyF^y^ېRijDVjJD RD"3ftlܠk em@p$ FUC稺;E}:^,`q0R`H4B 'KXcq.75 KV"ě38 %pV3(7Գ1dj̒5wFx #e"LX)tH^qLbzyizWBe۲~[GF54 Dc%/wC/TVU!-2 kd"nMcStq(o:0HOP[ɒx]Z\@(˕}SjIƗ.: 'lK!Q'NIߚ^̏df"OE3FrHzDۦFpO :0(Y s+R'xB2P {.wSxYB ":Ɯ6тZViAP;q"~3<>ܴŠ@H&' .Z/0j荰F2FA@deFlW TzfmgHR;l[ &3ZゼH%jnzܥaC`+:h`%0Txq.WM)Gs$c/BF#,i2\y@$5/_4UN LMaN1ȆL.0 P|$}7 e !.5WDo$1B)kj ?xٱ4,o0 ȃ9nU96t5F0SZ/dy'fCTp{1C1Y)Wk,sc5:pXi3fTDnb2t!XTu$C7 bHK&w1wZ#1-3(T }}[R=cY!ISW4,i<ã̍mTrNM8$`WDpeEYb'2WZ,qц@Y|B;j^m 8/dхM>G7` )Y؂E"ٍcuTcZ |萄Fows)T wm]۫GӍn1_ϛ: bwkk<6M%{Ĺv\Z/*`=2#iWCdqkdGϏ;o4얎=}0D#Ћh>G*\3 %LE1w䍧.gA_K:~n_1XǎuDVrlbfq0-̲"⢫ |Wٝf0Ktsè|}jvS u4k<j>Yպoy;EeyV^S>՛ξ*Lg{i8ՀPT:*6 oppp=ݬcNg9p37&b CoM"uJZJۧ&ps" l`zc̚YÅ,,ddS$H>wwZ P\LmlhÓU˄!t噇 lqP­3nތ!D:8 Ǧ1C#D-:1$ ?*"4Y:kE705ü'uMESBw:YFŨ> \RI#e+(S!cƉ!t:5C*aG0yC$ݩG dLAI<$ Qi0eab$Bl$R:ܒ7aOM]4u ߅DW|8#F"3rjmm,1؂ő{r^ e:1X\&BRm̮JZGZ21Z^$ ^e! J!bؑJg !Y,fRN@,"9,#F@d5ZBхs d*70@ⱸ^5|Al&JS}wGy#ߴs^9v$PvxX4!OA`2,OC/=7Fn(LsG!iIa>z-iReNNNbVn69 d2cYoRMa5[l~;:ހkߙ1X\T܇{;@VFg dڌwqV&&tZVbi?^EەknBT!a$Y>nўbGŚ#6 "XuŊE%i|xI˻Df&[Dw(өa9c5ydZ`j5w{$p ˙Bc$| ?G~$2 ".G|;ކG\ af`R! 6,HaȜlLeK[-YFmQeD0ph̔]#Vx$0k`a&k.2녋VUl82gJg- (ƞ4V6%qcp6yThl7n8* Mt$a^5 `xQe@Uaz ׾=G}|H"}CQ&g|ptuvZtaD"j>wXK: cn 7FkD#iS.ƚB`1 ȑdaeFK%5#'v bA^੕HvXڐdM̳^K1HjgwyRTг1%r)16ŒڪG35%ągC ,e =7nXFN¼4Bg+& "6pA,[1*;F"[%NbB #(;6:A镭&ѨWIe1Y5.Zh^'*r V%}Lh%ô xQ Z&c.!MNH 율Rzos"%(BIXILVB%'[tFWsyfɌ@ص5iR([*apݘD2 | 4v<7 x Bk%-tDZ )4iI*A@w)tZebFvŭ*kCpL̬816FZ li5fZ@[a%YUU( r9P3mvTyZ#WG0T$Bp„mQ,3Yq'U$pڒP"0Y(lzyLt4Ђ&zT-=S ZhQb )JmC`mq˧^)+"-z6HxQB grwV(NMh$X"XrmPfCE]SȀ  #XI$䂡ɨpׄ]!bfZ!"Kq YX䱼Pp)8ّ0V5brdb1Z/1elk2b LQ6AXf(!4/*l7Ka\8\"  uzFM}m;/$hemw]ƴ$p|Q;Ӊ=zlqw0Ѭ'Y8 Ivm0I?&'NH>P62p{"iWa?C/RgF8&o#O^ lx\=o2ك{LOPYO9xC'ЩЉDB;ݝx&H= x-J%*Dax I3t[&pVAAQR;qYunVI(:Xpcx>iOIqC\Ȼ3M;{T d%an]5S̅adWAA XJ5Ҡ tEdN#Q'"SȈfڨX1ZC {ZXRӔc3|y Ս=K37NʚWrҖЅ<M0©1M0MjhZS>7dbV\G6_qCG\c!m$ ̡~ 3 ^&.Rc NK ?'/^%cٳB3Tw+#JYr|dGKtdTZ̆bPr8RNPqFc.*R,i陁Ƒ4*1ܸMi%JYvHEnGf>Z:p,;IdJɆܯ`^ځY1l8Rk* -+YNb4]b|f3,rCDׄ(,T# HoyD%  c!'Yg}_tnt7$lەL4 ƒ0(MF^NЬ7KzŭN;-"ZmӬ}u.3}w/X01"FDz2rJRR@?mΜ2<=pz`pJ-=>U~u؝Rnm >ea,,4ŁAQ5C0Ғ組c[)9q~ =ⱔH|=I1GsraX}6M)$dϳ\?CbGsfב@lb3[aݹǕId,3@FEbG!UVbHЀ*aݥhQ2nzNe @71SH2xP4Ͻ X`fIhR7tVРQE=C,H,I 7gL"}A8ΉB f. ״6gVfO'ӓ!"B_nRmM01ߟ7gldi 16GeHx@X=/Ia0z"BB(Ȱd/K9X#X{u6贳;*J)IvM'c"I`zbXbD)>88mZ F1PC 8@LN !ݷ ~{~wJUaLHC~V1햘J`Kde夦M- c2ãV!;/"m5,fKk+$߭._K_8+M8 bbbI^>5'3ar_6m}AeGF/ŷ -rKs|߲P${_#k?=12'Je4#*EE+3;R0)DÂѰajN[ni):;$/ib ,HCJ7D5,̶ T۠wBо3j=a=fF{{݄WJ}ݪw}/?b`XDX<E]>,+%JbEL@g͛($6g8Chz3Ƿraioe .wUI? }zXC$@/c+/Ed C"mĿ*A$\Ck=W \d8\,1|HD9 ͼfm-~~Ww\UY[,R}VRx:D$1"UFR3bG= Lhɨ}9($CVɺNCLBK Ԫ mܐͶ#76v[RDU& ʐX .TAb 2U@i_^Ilwm[~$D1@@OZb\Ѡb<آ`00 ÊTBT\a gX߮;?{~6l'K8G-*MS{ד32,'CnKsFD:!OeP>3ʐ&ΔH~ D{P"Xec.l`Wi ncz>0i$N{ggy# =S@֖b}Թzjd$D*]" SR|/+b=;S3\d&L6 ?f}9ʭ_hY` T6\ PE'ƌ0a` S@=6eکU zRQ.|hd զrN Ol4Q\)>;+@!el%!Desmv|UH+a((-Lgdц=>xB/nܼM-P6Y-PL!\8lm0AsZڟ{ߧƳi]6[igX`zYKdtP#a HƸ-ͅ N[8nD͇s-NNz އ?UĚLdbV`] ȕ*$צb}|_ g9A eP;a @Hdz@؛#@XYnFszsONjr;B"#2OgЎ\x}^Law(ͯ0 @vרqdTnԉo4"Ǖb{Hz|Tv2! ŅU`J&S)~-a,!,J8 &Q!8~mbLZRR=HBt~1FxOV" ,JhD٢݀dX"8oV㊣o*ӔH;q" ^ȀFn0B B@dyt+~"6Qj5I C>|DL( CH `K }>$.Jh-)~o3ؒW'.Xd ~ϓyv[7gDIՆ#!)Mϛj>~q9V?وFg˙J1+.`>Yj+:tɵR(!Tjc+b@A=@4mB0Ȯ*d3'ٔ [ha)x[b qAK֗,XF ;+.K/~L"Cl B=3yS#4'蔘9Rq/]6BESmGJzv_tZ2$9wAV*I \XF*%4xd$3r0V*T^r0^2QפM$ճa"$I@!/S`F&b,^IܒՑ P&`bڳ;M2^݋6bӳm_]Yzv0 %$E~M{rk0bI|e da%77be$F :4ٟѧƟey?l(ԋ:z\T`.͊@D5.Þ=3I369X:?p! "?B{--}NNH>maP`hGH> t].;[q)R0Ŏ,ֲoSk[XAޫyhXdbe B&@![%ch Ŷ[=|aqFN2;B-sJlr9[[%Z#G@3Y$ F,EX $g0 5ljH8cQi ()!%Ok)ARRg|xjIIL@B,V@U?Ktm'M12Pݥ5V8]tm=o,I4 >`OqYP>|V(Cd[>500>)*V ,Vpk x!%# ?dqF(яHX5dpҁm&= H~7޿{h8N/ܑQc`bH1$ʡ("FBWkj <1$4 (*ݹDu4<3>W6-N )/$F0R d/8~̜H:q$Xyl H2D²&C{?d\'[8Fl5OlH{݀]FdLG0Q9NEH~)խ2QD`0;X!Hn2i +3oS h{X<#/(U  `,apH t,*1Z.YI f!>2Ɥ\3 '-Đ'Jbd ?DtZ ..԰bĔ%u%Y@/bmiqewNB@LΙ9m F}9Ôfd! ?2iT>;ANm4(,K%I;#d=Bp4GY B lbrӼȮkXv|y:p(Hu9w("(b$DіudWFpvଊmfGdW Hc 6 l!v0T01"+0$53)JJHgdӿx@ܼ͟fRiM$5zY$!")s' bܰ }5O^2, ZdCXBEaJI~z̔6v䤤xL_GYHn*,mtǭYl 2j"&#mā<=X{9\VJFyۺ$j Mvۑ&$W# L OזtTo󽶄k1C6L@2G*BAB0~͔=Ь罳pLM# |e2R",pqgfg[s9__N+Y4IX`dX#wd۶YZf`5uQ'y [^PbW󼼻(+,/i(8Nl+Kn~52좞՗E:ױQqu5ӣC贸:Ή'M$A022<>kR% `;{ 4=Oːwr=b^Z ZEi^BVeI)0c&+8f7Y2bL4$ri9:[ׂu6ɧl=a !TF)O)Ihh)th5Cմ2Eq2$q'fD3܇y=MjxIC샐3 B[wu_YΊ(8y^۬ }kBh(t$UYM8mז]WVʓih(hO픵2J@τ89z"@$%blMo]TqAkl #h`wnv[o;_ + ` y:,χ4;JƯ`u4>6$CX٦BEok }kaz#.&D(:1I*\r'pvX$)2xʦ1 Ab`xZpC/?{F(WK>1 z>kyr}5ʼnaK Ͻ7 0310yzۖqvIQ~\wNҐ:dod,A o^>Jl:HqH=) coX5Ltfa2"I,PW 4G-Aݞ룅' 0$0 ؙNMڅdAKG&rc@ha޷ ~}n|ӥ*Ei2  NG݌yfeYg RʇR9FB預i ,RCԅ^QG&Tu6īQC7ME 1tRH 7j@6$4Cg;8`gݞu#>6l,QW}Nqv%ځ 얁ܱ,#Ss4=n6A$ls(Ne\FppI>{#?OL0@HKъUG׶l:wi]Գ;cf9p()v* slfjE)F#!p( NMhsu&rq͈(FՙU.D. wL𾖴CT&y߷pIH+S{oVCODdjOHg~_Mjo^0 !=kgӚ{n}aD fXCGl̆V[I!#/7aKfV˴hQu=nt]m0F!Ӳ4&@nex ^5Ϫ# 2MJ$ %$$Ik*mTall*t x!(τu,X@C ='t&x g-\M ␦MTG4ݤ-jVB3L4AK.~F8-ăbL@Y(Mg "/(d> %`N9_9A&=)b~Y9; (PsD DpB;)K6Xg6flVLKIH/>#5eEk"dلD6aB%:"F$7 !ZB c40{2I&B I3,Q#ţ1B& /)GJ'O8X'_/6= 6z[4MߍJt9 jt@A $T~aVJY#iXU8#>&(fX "$'D>YXXoc8ӵCO`Bɴ $V0䮦Y;VdJCd6l##:ŬHW5rdHAf޲np<>;pbJfs$@ {,vTֺfqAڼ.]x{>_ $IR 7̓$,4id)$dH{M^$酢=+)2XN[$AdfGK@tgX!= b]q)jh@ Xac63İNi[vґ2 1"Q˄eծFD˴5 0Z"K{m863 jg- LKёrpk;ٞ y )so4ߌxHù% 21]P =06"p IJw,ڢpJatjW0=d˘dJI%Ȓ/+IBS~ters}r6cd,\]h'6?OS-'Ӊf0 ,\#8O!8>H۳}pv}&] + ZWZ}{)gW[T$C`|?f gWϮ &28LX@ca @AH4A|yIHn gH !샱W-Zd3xɶe k(NCizpO&* 'I@ӛJ²9#*[p-5cAtum@:lIƚo>9ҩ@'P$iC|,6ȁS}x3 8qɕ *b.c$;6}!*,n`a)VS)ǥ9UΌH9+Y]nfa AtY#W&vIcNh1y 78CӲ8aS]e`2qt? oT=b qtD(K: K?V#g t ͦiA,qp^/P%-`/Wd;j,J hyV:hmaސ%6C܈?|QU?- ?+?}?v8!~Y6Q[c܁PNA$G$a 1@? (!%ou|E_?oGI!&G(/q%b<\6V E+#k+fOu`✔lQ`P `aa$p+/DkPM9m29ex'{~q{+Rqp%vM#yQ'IzL(c9+ԊֳdN{zO 47]/T%)mS>{tn+9 c:OmU$38BhÃ?x  /yz1]ȑ/i)N*T A P~X˷_ԑ{; r?ſn[sU9~?~ڿ3{ T/iOwWd 8a2so2"H4I9't ^ 7SXX]tTڱ v\GjE و۬rJ>3@[V~C~YGRhs9lˁ 13b-$oXZCwoh/)(v=37mj`҉?Xo&5V)J(y.%]fLDg }M8b0"Y_ބj=jYVM hPQUڲ\AAyX72'&x,t +bһTA$O8aң?=_|G0~_^'0 ,y[WsF  @Ն~Q#QUDtOS2:9ym[gTɷG޳P&70%~Dm)E7'w#09A G?WJф-;~8 @Kpy?#c 1ӳڬ?Yy *Boqv KtZT{7Rj+vEx҄cW&9q94C ??_;Z=E=}~bށ$ ?  P_m`o㘎3"V* \jBڀ "ͨݐK[7qcEA3|0YF=i?E?q]~0nNV={QoCjm 2N 2CE\/bX%lAT,N _&/۴O*JF[P$4} GTIteD3& GgܸWh*$(Ѩ#H@3Aj3?t@,@oۈo>p礩 Gh 7 N+s~cϼiȣĔzH|`.#CR]2u`,F/ノVԽkKL 2h!,Muz/b9J[Y3gm#?{:)DhځUY#$^=G(V-UUWuXܡ m|a\ ԁ+g,(_Cumqx@D(nqȊDCX/҃c5wSi/R|J}qH0@C# Dp\O?X)82 m _jx2kPrIm|&q1&l?gd~_o_h} nZҔ 9Lg6r<裈6Oeqf/GCi O3w~6U _Bh"|ݙ#sl{\S|De j4¹B-a4 u܌K~:He~g}7VP.8-Ow&9go7xjʘyDTOJ!_pnIkhY|hy-$u4xkt/=P/P)$S-d]Q%\$~,kNa,#q,q?/hW vI/K%qذJ܀Ϝa)RhC_)86눡\I3.%0_F@Y;Orq=#|vI^8_N0%!__j|T}Aяc ]quZM!Az\&zQ0P@SB?,?pJf?`cx'Tn*bZAP A@ׇ0.㛪 _!uAch9~k_RI;_?g7>K 2C~H?e/4"1h2M:YSZ/$Qjtnh/ N( 6$U>9Fͺ"tUng-eWUTr6S{(DQw+?Qq?2!m3jߺLQj. ‘CࠂM$"9qs:GP\{T -D?d3K,^MAbbDɢX鑢4/f4'N+5طr"?XU N2qpܲv:3t} [>a]P^n郹P:F"AKډ·w949b;xl`%olQp1|f֏Z8TN>IHC5>SLr nW#E(Q뇾IgUM}m7Z\'?Ma$-$N8ƃGOt. ^M:҆f>~Twޑo 329Iw^)qESl`UArPp,HQ?*;_w;2X@=߱S@l)wYuOHS̷RQC$hRF ֮DX |x*y yK{DȥlңʁQ~SDY;ƤMjmuQr} ԳaJˢu4(jVʿO[J> ?9}} l _0 V4J#-$,@~!˜,A| A4Aaq8C Ta":wD<J]Y8`p N0 * (h 8O Z-( XPK7Da?!+s~enO=C-J8k h? ?G=g0 U`eWta鋤#역A6"@Dir^zXY &?mQ۪ hM+-=i}+_.5 ;)l.D&M_:W 8?Ȯv$;PNc0o@m@0P_Ύ>#{ލ 8#" a$C@p_IA_{$>AB+_g`Mp:BWq,"AY [1}kA|jLQ}sE?>ߵ#LyOIg5o'Ty37*?WvC~Is7bj.A?~9$/+ʝ;8-{"QH$ LcyjKaGM-00mD{3#m&i{PħyLO:Sf9FE؛$S̱\3 w=@@$ +&Mdqt?ErIFiA..C64U86P18$$%2L R}J7Q:U ꃿ~x7nwc\۔3X(aWJn]/f1c! F? CBݙF\uxpbyllҀTwV6mhZHtAjpJ7@r*Μ1f̏kT#;gt7eD @,0{a ۼ@jx #fDwlh== ϲP2S>ld2&Q0?!VM$}]%'k,F"LjY0.B" DžDmr}0 cQڒ܌7 l\!n/I̲ \k P;|?EE+1 (f<9Ң7 !rDh G~Cs0Q^j<熈6 Q@?TeaNMxGXz6( Cm {2lͫ/( pM{Bp1D~fK& \{O/w7i)׶y= yc"Pai|ӍI C!td (^Oէlٵ$"1Q蕄VX3aX@4% b.l;OIcM~G? m[=W?&0nG S4r}x\9$^ՙf*bc;(#"Hexade#9k+vFSw 7zI1$ID#H|BX2 4 VM'i[9W?~G|/c~Bڢ :"/ Qw73D~c},J؅eʃsbG%h!i?sO{q6lJvhNlDKʿWp$2iVbhA9+J ~Ūyy._!*CB_a5Ķ!u_ ˷E  <12ۙl +U{µ?XD~Q;LVO'm7ѷ܊|.rP@AEy/~#0Gv' ^QzLڒ P~q9$} ?^˪rcL3)D߁`U?Sc`1M)oboZ)0*PnUx76eGZ"^_)k)%t$u ҄3)aIY ,,3S' d>[C6٧x۰l &t 8L~BR?y:7MvH$)\D h;"hn6=ϹPCͰl ~U1깙pG=ޢ\iT*6Ӳ \6O6K0a`lOP c4z>4{Y&h?i#)`Oe/]e@h|խk`ѹr{wפ͆zN8"E" D}ϡ޺W3'V r+J=̜*EGalCKꆍD =|Nf֙I|Ek1\gWGo'T0lٶ͡!g lai#DZ?wl´IO>\(6("={J~lQ_]C=y.9H+)wcw b/m&.`$}N#!^JhѾ=W$\2XtMtJ#g4$ '>ׇ`ͼ0Dwen((1sE,Ꝼ4bO.;#!C"y^O|xѶ]J8iS5V, PĊ$nٶ=T:fs-9-#\fxgVN ̕ `*bj=͇Fc/qԟ2z;mN"(c(Z6BvN~R"EgwEsRbđ28CF/64j#޽ֈA={oZ |@n"2:3b/t#>`<ɰFܳob4Rl P_M`IA#$[h|2lM&IryB@S<b*C1t~<,EU~{y=Gh3Go,zHIi6D셦xOW'1?|^)'o?^> L_[DHhF$c4Ec>pHdx5ڰ@A"G Ɉ^n"ۋ("!J]d 4Fh'y_W@mdͭ}XH~mNa6@r&2@sal9vDI3q ! o֒ } wf|VdBQO;|F @"/ a>AѱѰoCOidWyrOlbD <9>;Px$1yJr燓c6$ɳQ?=0vQ1=MZMfѳ"Gb͇lɥ`Ř6-D+6p@0/ 4Epv@ď|7Fۗ~8qkIum&^.HvE!l MOj2F?8L?vIIp@O鷆23@ 4g>3''|dۚNI?u>3xp "n0'MB0E:>, I q-˅kxw܋{bH$`/֤3l0y"@Eڍ-{87hX<`Z'bC"0[H rphh ?Rb 7ϓ wxϯ\}לW #rTE $xhdbPA$<{lqʷ~HC$qBZ/"$D8V+l8aM׬{:V#kw"r,;$(}%BkZm>&MyǺ_XNA5C8u|9/R ʰ桒-sllH"Z0' qucudE;bJ 3or$I; ;^+ i"#aN߄=`Ȳ0x;jALP A?_<_jyb7~mo_=M)g?䇑C|lGT-yL,OM$N<1 Xf/p7|u"J]ZwT߬&b ¥a^q[ڄτchih(S{}Qnc"(FontZw?$Z#Sr8Y !"m7?𸑽 RTN?~8oƩ4 قVw3 0]3Wa5l}AU_WrC:/nIӪ6MŽ4LB|VSgnfOMy\u^x$if4qCߌu1]P#w )ZCHމ֪P oz+&kvؘrWxN*on^vbPnyLe?zi9',z~<.eN2\| O i2Ǎ_qn %V1zW@n;?2Xoexu†%8/8nj-ЖxI?BZjЀ F&@n ,"4PTrTE`YJϮ T$Y?Kߠ.џӬ.&EMc"&8@|aD.0S}SO_7J˷k.ϡG_W@OT9NKwq7;b%-S84YRaUh#; iq_f:zOCr>7#$Ǵ; ]>Ʌd @yhպh|$*C3 'E z0ϛ_Юs3PmK.>gV`Bx]iO?)k U`믧+R4j60T oPȒ )[㊖Wb/BA#MحB.ƷaZ3-eUJ$m^DӑJ% hn:ؑ֟p_EYV]:=*=(GscPVpG!XP'Gxey˂E_`"<]|/%ny5|YɏNV0pPߝ&@zz/NsƲߴ`E~L@4٫w R0V1N@ q<#"kJ*".il'c@C*Đ+ xך=[&;`` Ζ_&w>dvRoF&"R@I}n),jZ/WW֑BVX|$`b~]h$ DM^o)Zh/%wK.`KL7-S0jFrpa6qm2b`CÄǦ<@QL5mI/\zr׾$%r3ڮ ZE5z\LJ ]ܻɠu;#WEBELrj'ovpÒE,OߩʷCA '|i+P6Qd`h`'Cgn#*DDk6@:6~8-dtٞ(Km1"=tL(B9\H:Y.0# nlƨs/kDx8xk!@ZAk OYa:w1DiޒUϥg=̊NڠdZ^}qIE mz j9F$:BD('KgRɏ! )P#3qpϙ u?IB\E`\:Bڔ(-qn\k>1mwP(#ULw栯PY;'RpʕQ_[ZN`7SޞCvD^ q21۲)N8HYfbz!E{첝@{0 ңn0YxhV X{ ;&:PFM<Jబ<QY/ɂ} 7$d۶ \K#Z@zt{#J_7$I'6 P1sYrqlF"B@/EG~e6YA1A6X$7P?17HD:pL*O$y_u8՘8PhDB"#y bEM["ly6[x7dq\M&ްx@9aEvΨeߙ3鲸WE&fLΖLI!_2v0c)ŀZǵJAnp2Ѥr,58wAl4_+ jbnNF +"|spo`u-=PֽI@ -v)@zwDٝx6q*U~iY# ͖4O~iDV3>Y03ۥxML$D>G.fF>]B'WU"`[Qiw 7O,x[{rcz#qSpRi۹-#7S r̼Qqx E!Yy"|Qm@Jj #hޡ]eݻ1|l5^E6g&kCIIWiMc #qʉJ^i ywH#i'vot<%HdmK1_<:Ѥ3a]~Ҙ@iKamTPqi%c&&&}NVш[v:b0L phw+4>ieCvQ ;W`䌟Sq~/Ͽ;+Kz+b' #8IČaVʛK0\@wj+[_;"%_jJ\1N \!QN|/cKŌ L:hu^Qƈ5]x|W5sS †PY(*%۵-:|3~ J0dl}3&OFfyR&gٍcuoPvtFnOi؝EO Cū-jiشar,H/J#R⬎2 qtJtaP&Zp@*x@a3=&ڭYQNZApw~R=in մDRP(Gq3ӞtE#OƆj-&,b?77`azlͻY]&z% HSN_,Ð*j_t6!s/o+tE/n;0{ӏyJ}~5og"YX rK]9pIk"s/8 _=tD=>|o%{AE9)\MrYfZ4d({Рh?á+7*h_ Zݸ$*oZ2:bn)c# >gW> oؖO8OM^x[$T"m%y&&(ފo^hܼ>K#=^eM3:rt)g޽ɺzRkb1 D;^uaT-x# D{/IgOt ԔK#S/tÑsךR0PA\k`w-Ā/R kR^\쓋ىf>]#ici`3Ao_)HM8/M@el #{ų\,%%or*Y)UW܁+w (ASpn\uV87T(BH˘e뮄F,Qۓ֢Dj;-MKz 2%XpץWl^TMCڗr9:%{!W5Y ByNB›X3K(O Hm+uy;pZTL2GbY^Ls Fv ?1xfbk7M}c)wy E\,iذn deGҧC!`Ol%9exG# m!D9؏qMb-'A'nBgϾp)OAUgEڈiZ#{k1+LQ0weÑ3_!Qܢmӟ#ڃM}}@Y8%M  I~-7R=<59L^ dQuTTq 4M S RcD{iVG(ů6*=*zśy|:wP3Y(FhxA#*^bE Mkw9_GW;0]c?=_'gig<u #;8''4%+mxw'jWHIpJm5^ , +mˁAIn幋{%Y{sCdYGC2EԘsՓ_(T{"#cU-cBJ~zFC\'p2edBbx3ɒw/46sMwf\-%8>h壀)dZ_ pst~A'ul *9v"kE4ؐ"ؿϥ,Hц=nk:l_I{y^:lcI|dQɔ3+gZvfdz4)B䭾kLqc^6 ؚz,n")@!sgk!˦`EWv0Y{Dս-,lHmVOkN?wmnI449 x׸x O:Jf.]$1B W}6L 5'M tB:E GW*\8wTƌUUS\:̐IvHƁykU)@N견d$. kٰ.R ҫ)O kbVHV#I:oVֲ9֫O`Q3{Z?-_\Zδh Jq-/pۚýeL1LҬ8 {GFºSu5o`bXN.EPIwR+N E~H$V|BA:p`zN[+5}s:UeQN`L Tλ0vHA }ڵ0Z2Ooy 7HA`!vYB#jܜKg:P&% |RQ+num(,mJw喃#cClz-XWĸm!KL;덺hh)W:]x=? ٗ/ilXċHĴdX ݃vFK"B^#'Z[b.)@}Md2 nRWߜn]@d@tp EtYxMʹv~b(p<*RhW_xwߍ* ٺ#LB>NNxrLm+v&]>?l2%s9w5|I(hveA͑c&uPt mڔpP34eW| t»T 'S6u) B0pC?e*:ztIBX %JD:NYLu 5WZ%$iG@dBJl H*¼U(r iU ܠ2xA`"!B;J~Tk) "5} !RmL3>kޯ*xʱvPr>OP@My){ZP)gi85ʹ`ZVh1/+/C& MeWxg= K=+-y?r#O10aVb(8>E[3=ҲT Y%#؜3n(Dd|\;qɬП[4evʳt<-OOar~73k";0qmpn7P^aԕ<4~/1o6W NF!^I1}p-dee :쾮ub#E^6K RzUƛ8NakoESGBJ䔟Y`t|)pk=; O "z6w 6qҏ9Ty9i:v} "tU[n9F)T(CwI4e?3DKX(HfޱgdsGXSk\-P>u^iAYqdp}cbP hk"$! Δf&Βm/B߬џKW˨d@`-QuSM˞Y ~'cϫ-ǖ@q<J~Isʹf;z#fvu0\߂*=bԕ0%&/o31۸u#wo^s>qI{r$,8.nE ȢZ!%9JlpT-\(h| .e=pkLH}A€x}*|Cm D!tS#=}{Mm]YyX3LOU+hϋ=Iʷ~OT>M:M<Fp[ a3D;14(ӓҍt,w \P |Qc9V>~37Hjey荚"#nQ"\;4zDhQxA.[\FV ; >/]A#i'._j5kLyk9i)!w0y-jkZU*4`'mu{~&Tb\$&wv>˽6|7x񇼱 qxgK3lZPFu>`5I7=Tё6A)[:.ys Dg*|r fT:q7 4`V5k(IvP-㵦;1yun-xZU=U`knaiQw/E:\t8 m) jylZwB,~UGQ̍PnOFv, \"U]O2nuyƲyiYY rr@PԘWq l3sV?n"}+]n(zm J"0%8;4<';}ϔh7J!xn{kH\9Mi< #^iT9wX X{>'bvn!.J9cPuizEmSzc)'-z5 Q>'^)usbGu۹[CX3/C?{;iE*fs۵l&% e/VmYx9,IֆP!A/ye9X6[UTr wj S(vC1y8 ɳmM{ƁrR.݁ߋfoqAY̌}/H@sXۏv8ؑzP7M4'E7*K>̂\21(ě'$yD^)cn7fgU=nVdnQ?nGv!6"#4R ,V,lv/ё$bdzg$9p a? oW6<lN#roӘ :pnoS|JH?N8&_zoy+RgпNF,Aƍ]TTGlM%[w!^!mGU Vwʉ6hzKo8u)>9Yu}T=N{Jd7Fvdf9Ք50Hex'`I mf9vu>x`kU"hf.DeN`4H>(#x#뀬{d AĮw owad+T%C߫fq\a~^H2ԹtM503ˊ,Ҵvo^A?AJL)N_w3mx6O~U-A/t@1H{h&hs3l7pH\L⧸J-7US]6#îIA&e!kj~w' q,HPi@Kl1{ n ƀN  ēo弱{F\%!j[,D@0WJgЧ%#-dK WQ_E8Ռʼn;^>8*XqqV@qߩ@dԯ1lہG3 h$P;1k\{u6n![_G ^aT=&NBi!qKL]HgZleY!Ase92'V'GML[粿iE8 0ץ,I\- /}oiG+D4 Läl~ҊFxYB,"ȻG@omJ/ZwBXD:VA-7z | b7%Aה|DD;SK,!GaDc7nDxjtoE.3Sj0I"լۑn1k]q",9a'pT@bqɌJ@+ ~+6jʟ뉡khSZxUᆴ\5an`7EHkgMPn0HCtuon%%##X[[A%2RۉAy|Jog8BJH(2{5oΆtP,"!^䦍&fOuԴ1{) DZ >e>B¨|KUxD^aFg7mvj B '~VYe|rfͲxM 7L|WE!ǖr+$)2՘tU}ht#XGTo06.C@вdӀVt٩?)} 8Fa8:ND0m`9 4*PQ3Q8cm@SqTw]יGK֒rEt\Ky=vVT] Gq]{ZN.: <")èRN- qmG0]!p(^h*'P"DTЭ/VQww]y%A)9'GHrDprss.9@ĔynRWRHpEt\Q!8$BPK;'9RT]ךsfyjJb쳣 *(i&cDPɴtupKډhY|5mZHHQ+شS r$.p: qrtKYXyR'=8μv֧:N(A$9夑@.RA8q!Ĥt hm JqHs6w:KjçCXl[gIdr9 {uCqΧB&"";o"q.9NNNH.D$I p"=S8?9ʢ(y5(hGDHZ=:"8:H8r{vu9'G98tȊN%-Ȋ %9{[2(ݕ'UTRB!B&VB"D@hJ*% H)T U@B"DJ@4 @TRAbsts!' )Zܽܧ!9sNq<7(㻮%""(E)" -b" UJ ЕE]iWwtGn00ZB99 ! q!*c5 *i:$r "ChTTRRlNr"NH'BD1ʑRQJRBG0hRpctQJ*P P%]Up38P[Z]mIIМ\% 5KH=AB*Pg'!;:H)$(N R _l5"AptQ t: ,.pH!::NY7Y=#Y{׷NRqa"\/j\HN=jI'"ttJQ$9jqBI$QG"@hTiDU((TTEQ(fB%("DerL܈8\@yM"TTRtH45TSs8)U(D)X]]S@r99Lh-J4%l1MUl:bVNJJJh&Ӂ*hhT(XJP+l-- (P4Y]vgX3G!NDpDybtq˴q.D yQ:RI^VnHvIE$8'tN~ YI.HjZ3pIQ@%)G'h:kG"q 8g$HBr9P ĤPt 'TOl$tH9 s#mQJ!Gt!;s.H^B"Aӑ[hN䐊RDGqN(&( (JD*R"P @` fdΰFD:r*:"jBbtD h(NlGT5Li.NBVPZTU@PDPFHβ9:;DFfJU F)PPFbhG 䂱"  HB!@*@AtmW`8%3[aӸQ Ien9CDHBEj!9QrCJ .rJ ;;NL8JDDrڭk')ns9<ԅĎ9I9BkjH$B%{V)Ј]wT Kۻ;) *f() œGGwEwQԔDU͊H*$(PHsh" !Q@ZI" FQ)ihUCt1QQtB% A15$۶Y'H)L梁w9!n EH"I.S+Gt) rtN TGG98tSHwGu-D\ȺB`TEhU a h1CM*1RDEDT[fU4*A*!HAU %(((DL" HSBPR P)T]WP([Z8$t#:{`p8^v !"$p]s\D*(&PJ&ET(UARV(҅'..8cp"B$PJ(VT(QH('"!":{]RHHC*ĊRTCʸ8HGHEDHBM(( }CA-4LG'1 (RTH1DLBVT))F$( *@*iWD()Z UPDZPQ*BE(AQH(hSB(t]&Z4 %!@  RH B4!JP Ѐ B"P(( @- @R /~EOx'/G72??:GG~S6#\խcAP(4"P@P( ""}ϭ<:V_D +JҠ qy(w/oa(> >:T&J?5D~9\OX(s Qs~;H9۷OiQ(CȨ9 R P ~o____^~J"*( JҨҪ4 J !_7}>J B P8/P 2_? {~Sh -j~1lnҟ_@?_~~cVߢ>c x@R`{1~]>{2~N'J>Gv;| F=C4@{`/Ae !d7lV` a7("^ g7mo}>a d[_#;z;ion]G]ov}/93_ ~nGr#X$;`0cͿa#? C|`4qq9lDyT>EXh s"دMIAD(?Ea,ianݮ' r *nY@<ޛ!3r4Iu QCFr8C($\4LS}8xC"lr$Nq^1ѩ$쌄Hތt0XxO*])T[<.L@-BPDD$aY҇^uPau3bU{8G)p0#G;_3T'J.)>[~1G-蚬8Y~J: Yw...5by^^Xe/ÛR9NYۤμt"ԆLi )7JD XȔɰ13@Wo\ nYyX8D8g 2]s+wd$hI=6? #> A¢gbcXXVIjCם7Hԇ#zQԆ0k7fX*YLn@$P݅ӧ5K vӞ^iYNTyfNɶi4VrKٙUDh<*EULIud8+YG+䦁gKKgi4 Cߊ~EOϖ^1NihEI;f qgN8 RU6@nt)3@$8391EK,1f Ǐ<2#8Li+9Y]2|˭%>{hk=:duR'IH {&l! BHd<]p @F!rfr׬6pFXFrR5.PU($>7+|$9 (𭓆x#,|873JGPIMYH0Hx4T0x(]#5r!O8C1f#O<# ;adlrXϕH޵?w?w;wǟ>B0/#~Я aG6_1П|T5 `b~?wԽ:H?ܙL!}\"hdY?ϏhNki!0pڙnس)wN;Q".GI zg7q>/u&њfNbi${_=6fH4Bn?&buֳEh$Һ^ 4aCmr:@r7]WD8i7nN*sTe-R`A:t1̺1 dQ3 :"O)S 2Y}ŔʹH#Ӆ3IJs'!qd\@ ( $Q&t Jxf$I:c┉we:g55ɢgܒZ̟z)!d遁$gG\uo=H+q`7lxpiIS INޯVo:\4rSLWHX9K Cy('a읹w$S 7forcats/R/0000755000176200001440000000000013241142770012115 5ustar liggesusersforcats/R/relevel.R0000644000176200001440000000306513240326422013677 0ustar liggesusers#' Reorder factor levels by hand #' #' This is a generalisaton of [stats::relevel()] that allows you to move any #' number of levels to any location. #' #' @param .f A factor (or character vector). #' @param ... Character vector of levels. Any levels not mentioned will be left #' in existing order, after the explicitly mentioned levels. Supports tidy #' dots. #' @param after Where should the new values be placed? #' @export #' @examples #' f <- factor(c("a", "b", "c", "d")) #' fct_relevel(f) #' fct_relevel(f, "c") #' fct_relevel(f, "b", "a") #' #' # Move to the third position #' fct_relevel(f, "a", after = 2) #' #' # Relevel to the end #' fct_relevel(f, "a", after = Inf) #' fct_relevel(f, "a", after = 3) #' #' # Using 'Inf' allows you to relevel to the end when the number #' # of levels is unknown or variable (e.g. vectorised operations) #' df <- forcats::gss_cat[, c("rincome", "denom")] #' lapply(df, levels) #' #' df2 <- lapply(df, fct_relevel, "Don't know", after = Inf) #' lapply(df2, levels) #' #' # You'll get a warning if the levels don't exist #' fct_relevel(f, "e") fct_relevel <- function(.f, ..., after = 0L) { f <- check_factor(.f) first_levels <- rlang::chr(...) old_levels <- levels(f) unknown <- setdiff(first_levels, old_levels) if (length(unknown) > 0) { warning("Unknown levels in `f`: ", paste(unknown, collapse = ", "), call. = FALSE) first_levels <- intersect(first_levels, old_levels) } new_levels <- append(setdiff(old_levels, first_levels), first_levels, after = after) lvls_reorder(f, match(new_levels, old_levels)) } forcats/R/shift.R0000644000176200001440000000137013004646066013362 0ustar liggesusers#' Shift factor levels to left or right, wrapping around at end #' #' This is useful when the levels of an ordered factor are actually cyclical, #' with different conventions on the starting point. #' #' @param f A factor. #' @param n Positive values shift to the left; negative values shift to #' the right. #' @export #' @examples #' x <- factor( #' c("Mon", "Tue", "Wed"), #' levels = c("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"), #' ordered = TRUE #' ) #' x #' fct_shift(x) #' fct_shift(x, 2) #' fct_shift(x, -1) fct_shift <- function(f, n = 1L) { lvls_reorder(f, shift(nlevels(f), n)) } shift <- function(m, n) { stopifnot(is.numeric(m), length(m) == 1L) stopifnot(is.numeric(n), length(n) == 1L) ((seq_len(m) - 1) + n) %% m + 1 } forcats/R/reorder.R0000644000176200001440000000612513241406105013701 0ustar liggesusers#' Reorder factor levels by sorting along another variable #' #' `fct_reorder()` is useful for 1d displays where the factor is mapped to #' position; `fct_reorder2()` for 2d displays where the factor is mapped to #' a non-position aesthetic. `last2()` is a helper for `fct_reorder2()`; #' it finds the last value of `y` when sorted by `x`. #' #' @param .f A factor (or character vector). #' @param .x,.y The levels of `f` are reordered so that the values #' of `.fun(.x)` (for `fct_reorder()`) and `fun(.x, .y)` (for `fct_reorder2()`) #' are in ascending order. #' @param .fun n summary function. It should take one vector for #' `fct_reorder`, and two vectors for `fct_reorder2`. #' @param ... Other arguments passed on to `.fun`. A common argument is #' `na.rm = TRUE`. #' @param .desc Order in descending order? Note the default is different #' between `fct_reorder` and `fct_reorder2`, in order to #' match the default ordering of factors in the legend. #' @importFrom stats median #' @export #' @examples #' boxplot(Sepal.Width ~ Species, data = iris) #' boxplot(Sepal.Width ~ fct_reorder(Species, Sepal.Width), data = iris) #' boxplot(Sepal.Width ~ fct_reorder(Species, Sepal.Width, .desc = TRUE), data = iris) #' #' chks <- subset(ChickWeight, as.integer(Chick) < 10) #' chks <- transform(chks, Chick = fct_shuffle(Chick)) #' #' if (require("ggplot2")) { #' ggplot(chks, aes(Time, weight, colour = Chick)) + #' geom_point() + #' geom_line() #' #' # Note that lines match order in legend #' ggplot(chks, aes(Time, weight, colour = fct_reorder2(Chick, Time, weight))) + #' geom_point() + #' geom_line() + #' labs(colour = "Chick") #' } fct_reorder <- function(.f, .x, .fun = median, ..., .desc = FALSE) { f <- check_factor(.f) stopifnot(length(f) == length(.x)) summary <- tapply(.x, .f, .fun, ...) if (!is.numeric(summary)) { stop("`fun` must return a single number per group", call. = FALSE) } lvls_reorder(f, order(summary, decreasing = .desc)) } #' @export #' @rdname fct_reorder fct_reorder2 <- function(.f, .x, .y, .fun = last2, ..., .desc = TRUE) { f <- check_factor(.f) stopifnot(length(f) == length(.x), length(.x) == length(.y)) summary <- tapply(seq_along(.x), f, function(i) .fun(.x[i], .y[i], ...)) if (!is.numeric(summary)) { stop("`fun` must return a single number per group", call. = FALSE) } lvls_reorder(.f, order(summary, decreasing = .desc)) } #' @export #' @rdname fct_reorder last2 <- function(.x, .y) { .y[order(.x, na.last = FALSE)][length(.y)] } #' Reorder factors levels by first appearance or frequency #' #' @inheritParams lvls_reorder #' @param f A factor #' @export #' @examples #' f <- factor(c("b", "b", "a", "c", "c", "c")) #' f #' fct_inorder(f) #' fct_infreq(f) #' #' fct_inorder(f, ordered = TRUE) fct_inorder <- function(f, ordered = NA) { f <- check_factor(f) idx <- as.integer(f)[!duplicated(f)] idx <- idx[!is.na(idx)] lvls_reorder(f, idx, ordered = ordered) } #' @export #' @rdname fct_inorder fct_infreq <- function(f, ordered = NA) { f <- check_factor(f) lvls_reorder(f, order(table(f), decreasing = TRUE), ordered = ordered) } forcats/R/utils.R0000644000176200001440000000125113241405022013367 0ustar liggesusers#' Pipe operator #' #' See \code{\link[magrittr]{\%>\%}} for more details. #' #' @name %>% #' @rdname pipe #' @keywords internal #' @export #' @importFrom magrittr %>% #' @usage lhs \%>\% rhs NULL check_factor <- function(f) { if (is.character(f)) { factor(f) } else if (is.factor(f)) { f } else { stop("`f` must be a factor (or character vector).", call. = FALSE) } } check_factor_list <- function(fs, arg_name = "fs") { if (!is.list(fs)) { stop("`fs` must be a list", call. = FALSE) } is_factor <- vapply(fs, is.factor, logical(1)) if (any(!is_factor)) { stop("All elements of `", arg_name, "` must be factors", call. = FALSE) } fs } forcats/R/drop.R0000644000176200001440000000142513240326422013203 0ustar liggesusers#' Drop unused levels #' #' Compared to `base::droplevels()`, does not drop `NA` levels that have values. #' #' @param f A factor (or character vector). #' @param only A character vector restricting the set of levels to be dropped. #' If supplied, only levels that have no entries and appear in this vector #' will be removed. #' @export #' @examples #' f <- factor(c("a", "b"), levels = c("a", "b", "c")) #' f #' fct_drop(f) #' #' # Set only to restrict which levels to drop #' fct_drop(f, only = "a") #' fct_drop(f, only = "c") fct_drop <- function(f, only) { f <- check_factor(f) levels <- levels(f) count <- table(f) to_drop <- levels[count == 0] if (!missing(only)) { to_drop <- intersect(to_drop, only) } refactor(f, new_levels = setdiff(levels, to_drop)) } forcats/R/count.R0000644000176200001440000000113013240326422013360 0ustar liggesusers#' Count entries in a factor #' #' @param f A factor (or character vector). #' @param sort If `TRUE`, sort the result so that the most common values #' float to the top. #' @return A tibble with columns `f` and `n`. #' @export #' @examples #' f <- factor(sample(letters)[rpois(1000, 10)]) #' table(f) #' fct_count(f) #' fct_count(f, sort = TRUE) fct_count <- function(f, sort = FALSE) { f <- check_factor(f) f2 <- addNA(f, ifany = TRUE) df <- tibble::tibble( f = fct_unique(f2), n = as.integer(table(f2)) ) if (sort) { df <- df[order(df$n, decreasing = TRUE), ] } df } forcats/R/relabel.R0000644000176200001440000000224613241143251013645 0ustar liggesusers#' Automatically relabel factor levels, collapse as necessary #' #' @param .f A factor. #' @param .fun A function to be applied to each level. Must accept one #' character argument and return a character vector of the same length as #' its input. #' #' You can also use `~` to create as shorthand (in the style of purrr). #' `~ paste(., "x")` is equivalent to `function(.) paste(., "x")` #' @param ... Additional arguments to `fun`. #' @export #' @examples #' gss_cat$partyid %>% fct_count() #' gss_cat$partyid %>% fct_relabel(~ gsub(",", ", ", .x)) %>% fct_count() #' #' convert_income <- function(x) { #' regex <- "^(?:Lt |)[$]([0-9]+).*$" #' is_range <- grepl(regex, x) #' num_income <- as.numeric(gsub(regex, "\\1", x[is_range])) #' num_income <- trunc(num_income / 5000) * 5000 #' x[is_range] <- paste0("Gt $", num_income) #' x #' } #' fct_count(gss_cat$rincome) #' convert_income(levels(gss_cat$rincome)) #' rincome2 <- fct_relabel(gss_cat$rincome, convert_income) #' fct_count(rincome2) fct_relabel <- function(.f, .fun, ...) { .fun <- rlang::as_function(.fun) old_levels <- levels(.f) new_levels <- .fun(old_levels, ...) lvls_revalue(.f, new_levels) } forcats/R/c.R0000644000176200001440000000226613241405033012462 0ustar liggesusers#' Concatenate factors, combining levels #' #' This is a useful way of patching together factors from multiple sources #' that really should have the same levels but don't. #' #' @param ... Individual factors. Uses tidy dots, so you can splice in a list #' of factors with `!!!`. #' @export #' @examples #' fa <- factor("a") #' fb <- factor("b") #' fab <- factor(c("a", "b")) #' #' c(fa, fb, fab) #' fct_c(fa, fb, fab) #' #' # You can also pass a list of factors with !!! #' fs <- list(fa, fb, fab) #' fct_c(!!!fs) fct_c <- function(...) { fs <- rlang::dots_list(...) fs <- check_factor_list(fs, "...") if (length(fs) == 0) { return(factor()) } levels <- lvls_union(fs) all <- unlist(fct_unify(fs, levels), use.names = FALSE) factor(all, levels = levels, exclude = NULL) } #' Unify the levels in a list of factors #' #' @param fs A list of factors #' @param levels Set of levels to apply to every factor. Default to #' union of all factor levels #' @export #' @examples #' fs <- list(factor("a"), factor("b"), factor(c("a", "b"))) #' fct_unify(fs) fct_unify <- function(fs, levels = lvls_union(fs)) { fs <- check_factor_list(fs) lapply(fs, lvls_expand, new_levels = levels) } forcats/R/forcats-package.R0000644000176200001440000000004113004644752015271 0ustar liggesusers#' @keywords internal "_PACKAGE" forcats/R/shuffle.R0000644000176200001440000000041413240326422013670 0ustar liggesusers#' Randomly permute factor levels #' #' @param f A factor (or character vector). #' @export #' @examples #' f <- factor(c("a", "b", "c")) #' fct_shuffle(f) #' fct_shuffle(f) fct_shuffle <- function(f) { f <- check_factor(f) lvls_reorder(f, sample(lvls_seq(f))) } forcats/R/as_factor.R0000644000176200001440000000143613237652277014222 0ustar liggesusers#' Convert input to a factor. #' #' Compared to base R, this function creates levels in the order in which #' they appear, which will be the same on every platform. (Base R sorts in #' the current locale which can vary from place to place.) #' #' This is a generic function. #' #' @param x Object to coerce to a factor. #' @param ... Other arguments passed down to method. #' @export #' @examples #' x <- c("a", "z", "g") #' as_factor(x) #' as.factor(x) as_factor <- function(x, ...) { UseMethod("as_factor") } #' @rdname as_factor #' @export as_factor.factor <- function(x, ...) { x } #' @rdname as_factor #' @export as_factor.character <- function(x, ...) { # Preserve label for future haven compatibility structure( fct_inorder(x), label = attr(x, "label", exact = TRUE) ) } forcats/R/data.R0000644000176200001440000000113112754704614013156 0ustar liggesusers#' A sample of categorical variables from the General Social survey #' #' @source Downloaded from \url{https://gssdataexplorer.norc.org/}. #' @format #' \describe{ #' \item{year}{year of survey, 2000--2014} #' \item{age}{age. Maximum age truncated to 89.} #' \item{marital}{marital status} #' \item{race}{race} #' \item{rincome}{reported income} #' \item{partyid}{party affiliation} #' \item{relig}{religion} #' \item{denom}{denomination} #' \item{tvhours}{hours per day watching tv} #' } #' @examples #' gss_cat #' #' fct_count(gss_cat$relig) #' fct_count(fct_lump(gss_cat$relig)) "gss_cat" forcats/R/lump.R0000644000176200001440000001002013240326422013203 0ustar liggesusers#' Lump together least/most common factor levels into "other" #' #' @param f A factor (or character vector). #' @param n,prop #' If both `n` and `prop` are missing, `fct_lump` lumps #' together the least frequent levels into "other", while ensuring that #' "other" is still the smallest level. It's particularly useful in #' conjunction with \code{\link{fct_inorder}()}. #' #' Positive `n` preserves the most common `n` values. #' Negative `n` preserves the least common `-n` values. #' It there are ties, you will get at least `abs(n)` values. #' #' Positive `prop` preserves values that appear at least #' `prop` of the time. Negative `prop` preserves values that #' appear at most `-prop` of the time. #' @param w An optional numeric vector giving weights for frequency of #' each value (not level) in f. #' @param other_level Value of level used for "other" values. Always #' placed at end of levels. #' @param ties.method A character string specifying how ties are #' treated. See [rank()] for details. #' @export #' @seealso [fct_other()] to convert specified levels to other. #' @examples #' x <- factor(rep(LETTERS[1:9], times = c(40, 10, 5, 27, 1, 1, 1, 1, 1))) #' x %>% table() #' x %>% fct_lump() %>% table() #' x %>% fct_lump() %>% fct_inorder() %>% table() #' #' x <- factor(letters[rpois(100, 5)]) #' x #' table(x) #' table(fct_lump(x)) #' #' # Use positive values to collapse the rarest #' fct_lump(x, n = 3) #' fct_lump(x, prop = 0.1) #' #' # Use negative values to collapse the most common #' fct_lump(x, n = -3) #' fct_lump(x, prop = -0.1) #' #' # Use weighted frequencies #' w <- c(rep(2, 50), rep(1, 50)) #' fct_lump(x, n = 5, w = w) #' #' # Use ties.method to control how tied factors are collapsed #' fct_lump(x, n = 6) #' fct_lump(x, n = 6, ties.method = "max") #' fct_lump <- function(f, n, prop, w = NULL, other_level = "Other", ties.method = c("min", "average", "first", "last", "random", "max")) { f <- check_factor(f) w <- check_weights(w, length(f)) ties.method <- match.arg(ties.method) levels <- levels(f) if (is.null(w)) { count <- as.vector(table(f)) total <- length(f) } else { count <- as.vector(tapply(w, f, FUN = sum)) total <- sum(w) } if (!xor(missing(n), missing(prop))) { new_levels <- ifelse(!in_smallest(count), levels, other_level) } else if (!missing(n)) { if (n < 0) { rank <- rank(count, ties = ties.method) n <- -n } else { rank <- rank(-count, ties = ties.method) } new_levels <- ifelse(rank <= n, levels, other_level) } else if (!missing(prop)) { prop_n <- count / total if (prop < 0) { new_levels <- ifelse(prop_n <= -prop, levels, other_level) } else { new_levels <- ifelse(prop_n > prop, levels, other_level) } } if (other_level %in% new_levels) { f <- lvls_revalue(f, new_levels) fct_relevel(f, other_level, after = Inf) } else { f } } # Lump together smallest groups, ensuring that the collective # "other" is still the smallest group. Assumes x is vector # of counts in descending order lump_cutoff <- function(x) { left <- sum(x) for (i in seq_along(x)) { # After group, there are this many left left <- left - x[i] if (x[i] > left) return(i + 1) } length(x) + 1 } # Given vector of counts, returns logical vector if in # smallest groups in_smallest <- function(x) { ord_x <- order(x, decreasing = TRUE) idx <- lump_cutoff(x[ord_x]) to_lump <- seq_along(x) >= idx # Undo initial ordering to_lump[order(ord_x)] } check_weights <- function(w, n = length(w)) { if (is.null(w)) { return(w) } if (!is.numeric(w)) { stop("`w` must be a numeric vector", call. = FALSE) } if (length(w) != n) { stop( "`w` must be the same length as `f` (", n, "), not length ", length(w), call. = FALSE ) } bad <- w < 0 | is.na(w) if (any(bad)) { stop( "All `w` must be non-negative and non-missing. Problems at positions: ", paste0(which(bad), collapse = ", "), call. = FALSE ) } w } forcats/R/recode.R0000644000176200001440000000341513240326422013501 0ustar liggesusers#' Change factor levels by hand #' #' @param .f A factor (or character vector). #' @param ... A sequence of named character vectors where the #' name gives the new level, and the value gives the old level. #' Levels not otherwise mentioned will be left as is. Levels can #' be removed by naming them `NULL`. Uses tidy dots. #' @export #' @examples #' x <- factor(c("apple", "bear", "banana", "dear")) #' fct_recode(x, fruit = "apple", fruit = "banana") #' #' # If you make a mistake you'll get a warning #' fct_recode(x, fruit = "apple", fruit = "bananana") #' #' # If you name the level NULL it will be removed #' fct_recode(x, NULL = "apple", fruit = "banana") fct_recode <- function(.f, ...) { f <- check_factor(.f) new_levels <- check_recode_levels(...) # Remove any named NULL and finish if all NULLs nulls <- names(new_levels) == "NULL" if (any(nulls)) { f <- factor(f, levels = setdiff(levels(f), new_levels[nulls])) new_levels <- new_levels[!nulls] } # Match old levels with new levels old_levels <- levels(f) idx <- match(new_levels, old_levels) # Handle levels that don't exist if (any(is.na(idx))) { bad <- new_levels[is.na(idx)] warning("Unknown levels in `f`: ", paste(bad, collapse = ", "), call. = FALSE) new_levels <- new_levels[!is.na(idx)] idx <- idx[!is.na(idx)] } old_levels[idx] <- names(new_levels) lvls_revalue(f, old_levels) } check_recode_levels <- function(...) { levels <- rlang::dots_list(...) is_ok <- function(x) is.character(x) && length(x) == 1 ok <- vapply(levels, is_ok, logical(1)) if (!all(ok)) { stop( "Each input to fct_recode must be a single named string. ", "Problems at positions: ", paste0(which(!ok), collapse = ", "), call. = FALSE ) } unlist(levels) } forcats/R/unique.R0000644000176200001440000000046113237652277013564 0ustar liggesusers#' Unique values of a factor #' #' @param f A factor. #' @export #' @examples #' f <- factor(letters[rpois(100, 10)]) #' #' unique(f) # in order of appearance #' fct_unique(f) # in order of levels fct_unique <- function(f) { factor(levels(f), levels(f), exclude = NULL, ordered = is.ordered(f)) } forcats/R/rev.R0000644000176200001440000000044613240326422013035 0ustar liggesusers#' Reverse order of factor levels #' #' This is sometimes useful when plotting a factor. #' #' @param f A factor (or character vector). #' @export #' @examples #' f <- factor(c("a", "b", "c")) #' fct_rev(f) fct_rev <- function(f) { f <- check_factor(f) lvls_reorder(f, rev(lvls_seq(f))) } forcats/R/lvls.R0000644000176200001440000000607113240326445013226 0ustar liggesusers#' Low-level functions for manipulating levels #' #' `lvls_reorder` leaves values as they are, but changes the order. #' `lvls_revalue` changes the values of existing levels; there must #' be one new level for each old level. #' `lvls_expand` expands the set of levels; the new levels must #' include the old levels. #' #' These functions are less helpful than the higher-level `fct_` functions, #' but are safer than the very low-level manipulation of levels directly, #' because they are more specific, and hence can more carefully check their #' arguments. #' #' @param f A factor (or character vector). #' @param idx A integer index, with one integer for each existing level. #' @param new_levels A character vector of new levels. #' @param ordered A logical which determines the "ordered" status of the #' output factor. `NA` preserves the existing status of the factor. #' @name lvls #' @examples #' f <- factor(c("a", "b", "c")) #' lvls_reorder(f, 3:1) #' lvls_revalue(f, c("apple", "banana", "carrot")) #' lvls_expand(f, c("a", "b", "c", "d")) NULL #' @export #' @rdname lvls lvls_reorder <- function(f, idx, ordered = NA) { f <- check_factor(f) if (!is.numeric(idx)) { stop("`idx` must be numeric", call. = FALSE) } if (!setequal(idx, lvls_seq(f)) || length(idx) != nlevels(f)) { stop("`idx` must contain one integer for each level of `f`", call. = FALSE) } refactor(f, levels(f)[idx], ordered = ordered) } #' @export #' @rdname lvls lvls_revalue <- function(f, new_levels) { f <- check_factor(f) if (!is.character(new_levels)) { stop("`new_levels` must be a character vector", call. = FALSE) } if (length(new_levels) != nlevels(f)) { stop( "`new_levels` must be the same length as `levels(f)`: expected ", nlevels(f), " new levels, got ", length(new_levels), ".", call. = FALSE ) } if (anyDuplicated(new_levels)) { # Collapse levels, creating a new factor u_levels <- unique(new_levels) index <- match(new_levels, u_levels) out <- index[f] attributes(out) <- attributes(f) attr(out, "levels") <- u_levels out } else { attr(f, "levels") <- new_levels f } } #' @export #' @rdname lvls lvls_expand <- function(f, new_levels) { f <- check_factor(f) missing <- setdiff(levels(f), new_levels) if (length(missing) > 0) { stop( "Must include all existing levels. Missing: ", paste0(missing, collapse = ", "), call. = FALSE) } refactor(f, new_levels) } lvls_seq <- function(f) { seq_along(levels(f)) } refactor <- function(f, new_levels, ordered = NA) { if (is.na(ordered)) { ordered <- is.ordered(f) } new_f <- factor(f, levels = new_levels, exclude = NULL, ordered = ordered) attributes(new_f) <- utils::modifyList(attributes(f), attributes(new_f)) new_f } #' Find all levels in a list of factors #' #' @param fs A list of factors. #' @export #' @examples #' fs <- list(factor("a"), factor("b"), factor(c("a", "b"))) #' lvls_union(fs) lvls_union <- function(fs) { fs <- check_factor_list(fs) Reduce(function(x, y) union(x, levels(y)), fs, init = character()) } forcats/R/expand.R0000644000176200001440000000074413240326422013521 0ustar liggesusers#' Add additional levels to a factor #' #' @param f A factor (or character vector). #' @param ... Additional levels to add to the factor. Levels that already #' exist will be silently ignored. #' @export #' @examples #' f <- factor(sample(letters[1:3], 20, replace = TRUE)) #' f #' fct_expand(f, "d", "e", "f") #' fct_expand(f, letters[1:6]) fct_expand <- function(f, ...) { f <- check_factor(f) new_levels <- rlang::chr(...) lvls_expand(f, union(levels(f), new_levels)) } forcats/R/collapse.R0000644000176200001440000000146313240326422014043 0ustar liggesusers#' Collapse factor levels into manually defined groups #' #' @param .f A factor (or character vector). #' @param ... A series of named character vectors. The levels in #' each vector will be replaced with the name. #' @export #' @examples #' fct_count(gss_cat$partyid) #' #' partyid2 <- fct_collapse(gss_cat$partyid, #' missing = c("No answer", "Don't know"), #' other = "Other party", #' rep = c("Strong republican", "Not str republican"), #' ind = c("Ind,near rep", "Independent", "Ind,near dem"), #' dem = c("Not str democrat", "Strong democrat") #' ) #' fct_count(partyid2) fct_collapse <- function(.f, ...) { new <- rlang::dots_list(...) levs <- as.list(unlist(new, use.names = FALSE)) names(levs) <- names(new)[rep(seq_along(new), vapply(new, length, integer(1)))] fct_recode(.f, !!!levs) } forcats/R/explicit_na.R0000644000176200001440000000141613241137034014536 0ustar liggesusers#' Make missing values explicit #' #' This gives missing value an explicit factor level, ensuring that they #' appear in summaries and on plots. #' #' @param f A factor (or character vector). #' @param na_level Level to use for missing values. #' @export #' @examples #' f1 <- factor(c("a", "a", NA, NA, "a", "b", NA, "c", "a", "c", "b")) #' table(f1) #' #' f2 <- fct_explicit_na(f1) #' table(f2) fct_explicit_na <- function(f, na_level = "(Missing)") { f <- check_factor(f) is_missing <- is.na(f) is_missing_level <- is.na(levels(f)) if (any(is_missing)) { f <- fct_expand(f, na_level) f[is_missing] <- na_level f } else if (any(is_missing_level)) { levs <- levels(f) levs[is.na(levs)] <- na_level lvls_revalue(f, levs) } else { f } } forcats/R/anon.R0000644000176200001440000000140013237652277013203 0ustar liggesusers#' Anonymise factor levels #' #' Replaces factor levels with arbitary numeric identifiers. Neither #' the values nor the order of the levels are preserved. #' #' @param f A factor. #' @param prefix A character prefix to insert in front of the random labels. #' @export #' @examples #' gss_cat$relig %>% fct_count() #' gss_cat$relig %>% fct_anon() %>% fct_count() #' gss_cat$relig %>% fct_anon() %>% fct_count() #' gss_cat$relig %>% fct_anon("X") %>% fct_count() fct_anon <- function(f, prefix = "") { levels <- paste0(prefix, zero_pad(seq_len(nlevels(f)))) f <- lvls_revalue(f, sample(levels)) lvls_reorder(f, match(levels, levels(f))) } digits <- function(x) nchar(max(x, na.rm = TRUE)) zero_pad <- function(x) { sprintf(paste0("%0", digits(x), "d"), x) } forcats/R/other.R0000644000176200001440000000167513237652277013407 0ustar liggesusers#' Replace levels with "other" #' #' @inheritParams fct_lump #' @param keep,drop `keep` will preserve listed levels, replacing all others #' with `other_level`. `drop` will replace listed levels with `other_level`, #' keeping all others as they are. #' @seealso [fct_lump()] to automatically convert the rarest (or most #' common) levels to "other". #' @export #' @examples #' x <- factor(rep(LETTERS[1:9], times = c(40, 10, 5, 27, 1, 1, 1, 1, 1))) #' #' fct_other(x, keep = c("A", "B")) #' fct_other(x, drop = c("A", "B")) fct_other <- function(f, keep, drop, other_level = "Other") { f <- check_factor(f) if (!xor(missing(keep), missing(drop))) { stop("Must supply one of `keep` and `drop`", call. = FALSE) } levels <- levels(f) if (!missing(keep)) { levels[!levels %in% keep] <- other_level } else { levels[levels %in% drop] <- other_level } f <- lvls_revalue(f, levels) fct_relevel(f, other_level, after = Inf) } forcats/README.md0000644000176200001440000000733013241413600013167 0ustar liggesusers # forcats [![CRAN\_Status\_Badge](http://www.r-pkg.org/badges/version/forcats)](https://cran.r-project.org/package=forcats) [![Travis-CI Build Status](https://travis-ci.org/tidyverse/forcats.svg?branch=master)](https://travis-ci.org/tidyverse/forcats) [![Coverage Status](https://img.shields.io/codecov/c/github/tidyverse/forcats/master.svg)](https://codecov.io/github/tidyverse/forcats?branch=master) ## Overview R uses **factors** to handle categorical variables, variables that have a fixed and known set of possible values. Historically, factors were much easier to work with than character vectors, so many base R functions automatically convert character vectors to factors. (For historical context, I recommend [*stringsAsFactors: An unauthorized biography*](http://simplystatistics.org/2015/07/24/stringsasfactors-an-unauthorized-biography/) by Roger Peng, and [*stringsAsFactors = \*](http://notstatschat.tumblr.com/post/124987394001/stringsasfactors-sigh) by Thomas Lumley. If you want to learn more about other approaches to working with factors and categorical data, I recommend [*Wrangling categorical data in R*](https://peerj.com/preprints/3163/), by Amelia McNamara and Nicholas Horton.) These days, making factors automatically is no longer so helpful, so packages in the [tidyverse](http://tidyverse.org) never create them automatically. However, factors are still useful when you have true categorical data, and when you want to override the ordering of character vectors to improve display. The goal of the **forcats** package is to provide a suite of useful tools that solve common problems with factors. If you’re not familiar with strings, the best place to start is the [chapter on factors](http://r4ds.had.co.nz/factors.html) in R for Data Science. ## Installation ``` r # The easiest way to get forcats is to install the whole tidyverse: install.packages("tidyverse") # Alternatively, install just forcats: install.packages("forcats") # Or the the development version from GitHub: # install.packages("devtools") devtools::install_github("tidyverse/forcats") ``` ## Getting started forcats is now part of the core tidyverse, so you do not need to load it explicitly: ``` r library(tidyverse) ``` Factors are used to describe categorical variables with a fixed and known set of **levels**. You can create factors with the base `factor()` or [`readr::parse_factor()`](http://readr.tidyverse.org/reference/parse_factor.html): ``` r x1 <- c("Dec", "Apr", "Jan", "Mar") month_levels <- c( "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ) factor(x1, month_levels) #> [1] Dec Apr Jan Mar #> Levels: Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec parse_factor(x1, month_levels) #> [1] Dec Apr Jan Mar #> Levels: Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ``` The advantage of `parse_factor()` is that it will generate a warning if values of `x` are not valid levels: ``` r x2 <- c("Dec", "Apr", "Jam", "Mar") factor(x2, month_levels) #> [1] Dec Apr Mar #> Levels: Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec parse_factor(x2, month_levels) #> Warning: 1 parsing failure. #> row # A tibble: 1 x 4 col row col expected actual expected actual 1 3 NA value in level set Jam #> [1] Dec Apr Mar #> attr(,"problems") #> # A tibble: 1 x 4 #> row col expected actual #> #> 1 3 NA value in level set Jam #> Levels: Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ``` Once you have the factor, forcats provides helpers for solving common problems. forcats/MD50000644000176200001440000000746713242624336012246 0ustar liggesusers7408dbdc817847967a5c67d71fb8627a *DESCRIPTION 41ef6f9b7d02ae3774bce06f9ba2b9a5 *NAMESPACE 1993bf506b738553ce1aa6a76ce9b938 *NEWS.md 6fcf996d59a9dbf6ee3ffa63a42399da *R/anon.R c105c4a4602c693e2e9ab0d53818b3e6 *R/as_factor.R bd533a096f73a7ea37ab20ab77103866 *R/c.R e5fe3e8753f0345f756a73247d589a65 *R/collapse.R c8cacaf14d65ac3f598b15b2931d719e *R/count.R 9b8c9f934b7a5c9193cc8f197bbe9b2e *R/data.R 40fa362957bbb0dcc0e87f4632bcf01b *R/drop.R 41aa823f8660c913cd93451449298070 *R/expand.R 97fe369834ad78ad7bbf2735c8d05a24 *R/explicit_na.R b4fe12876c37f8a22cde06e9701eecf0 *R/forcats-package.R 09214419f40ea7fc34ee42cfebf492d4 *R/lump.R cd0818ab06b278ddc2a38b5a3eaab4d9 *R/lvls.R b1e7b497cdbc10912b5b10d0990a0922 *R/other.R 1a71d83d14afc4311a156da51918a160 *R/recode.R 76721819951bc4f01ae91dfa14313926 *R/relabel.R ffbb653a50cb1e5fa9cfbe88a05ab6fa *R/relevel.R 0c837abb3ce0d94b6e1b98a4de075afc *R/reorder.R 2513b5d4ddb3af53f57f9ef368200112 *R/rev.R 6a741a6fb62aa246f865f06dd172de1c *R/shift.R 9aebfd5ecc427de639e076a022cb0a53 *R/shuffle.R ee5201d1d40e6b81689639f92ae9fa2d *R/unique.R c52b4d9474163408c423eb70f81192aa *R/utils.R ba84551233a785aa48a03786952e3acc *README.md a6984b4f6c2e70deebeca86c7b3d76ea *data/gss_cat.rda f45edfe04a475925333c6fb712c9fcc8 *man/as_factor.Rd ae74738c8d74947e1d021899c62e89cc *man/fct_anon.Rd 80cdf4a28ef28084e8ec111b152d4ffb *man/fct_c.Rd 2824921fa8d491a1a3a87148ba442bc1 *man/fct_collapse.Rd 1bbef52ddb99ebcea61b33fcd8170387 *man/fct_count.Rd b0cd3c81c260cd0633223790e79e91f8 *man/fct_drop.Rd 3c8d1e83833685b59fc8df83bd52ff47 *man/fct_expand.Rd 2e44ae3588cff7f8dadb95641c78cd5b *man/fct_explicit_na.Rd c3884fb5873581435d2aa7b072f90596 *man/fct_inorder.Rd 6b7cbf1e4d497bf5028e0aef82141a9d *man/fct_lump.Rd 7c8ed498e688709605b46ca0d6cd0553 *man/fct_other.Rd 74483b01783ddf1d09540940d3cefc3b *man/fct_recode.Rd 10b1c304bf620a65440dbe906635829d *man/fct_relabel.Rd d54a6612e50df0849e110e799292eff1 *man/fct_relevel.Rd e92520dde0b6ee996f30650e68f9be48 *man/fct_reorder.Rd cf766cb9ca0d896a0955c0ad191b1e78 *man/fct_rev.Rd fa07b6aa7ca3c5c73b573f497dc5e68e *man/fct_shift.Rd e37efbf13b7923999c1412bcb819a57b *man/fct_shuffle.Rd 9122ce4e63cfe89aaed8a006a6748c1d *man/fct_unify.Rd 29e25af605ce7b8242ed2bcaad84428f *man/fct_unique.Rd 3c765eeb84bb9fc1e5f64fe7cf9e69fe *man/figures/logo.png e1b34d58fddcef2260b3c93ed2b44051 *man/forcats-package.Rd 0c85674bbbcc6f0164622c5ad556bda2 *man/gss_cat.Rd 679f67140aa7a12ffa8e2644324a1231 *man/lvls.Rd 50ed89e2798ad529ca69dad8d85851dd *man/lvls_union.Rd 0f020b37daf27c2fd4c78c574285ef1b *man/pipe.Rd 7b0f13301043822509977d02384cb6e9 *tests/testthat.R b7276ce56a13629f4741508087849bf6 *tests/testthat/helper-lump.R d54da72338a1e6edf9b7ea1c4b77309a *tests/testthat/test-anon.R 7ac124eea0ec47185188b3e8b0354c2e *tests/testthat/test-as_factor.R 4ee4b5dcc5cad90b78fe0f5084f35bc6 *tests/testthat/test-collapse.R d9c029815bfadece12532e635557b05e *tests/testthat/test-count.R 94ced03ac637bcd6e4da7ed74a6db9cc *tests/testthat/test-explicit_na.R abc6b12c9ac566a532b368df371303cb *tests/testthat/test-fct_c.R 2da1b3ace9cf79139782fb3cb5fcf737 *tests/testthat/test-fct_drop.R 736c2fdbad0de6ba44545ef5c7142e01 *tests/testthat/test-fct_lump.R d2ce880df1564300a215fb5bd839d19e *tests/testthat/test-fct_other.R 73c6685513fd25b80919c7211a0bee93 *tests/testthat/test-fct_recode.R ee7e60d046dbcd133e497b0e341670e6 *tests/testthat/test-fct_relabel.R ea83627dbe4048728bd265657aea6db7 *tests/testthat/test-fct_relevel.R 8bf75dec2477f0bcb482f57cdbcb1c71 *tests/testthat/test-lvls.R e8e369f72b8bd87b6c53c3a881e79e04 *tests/testthat/test-lvls_reorder.R b36134aa96624e9f3d817f99d5423313 *tests/testthat/test-reorder.R 371dc92dbf14f009077b997f00b297cb *tests/testthat/test-rev.R a0df68c919a132b10db11d2d2a37fa9c *tests/testthat/test-shift.R 9804486a2ed35c047035d010ea9b99cc *tests/testthat/test-shuffle.R 01bb70c134253689fbe2790516f53763 *tests/testthat/test-utils.R forcats/DESCRIPTION0000644000176200001440000000202313242624336013423 0ustar liggesusersPackage: forcats Title: Tools for Working with Categorical Variables (Factors) Version: 0.3.0 Authors@R: c( person("Hadley", "Wickham", , "hadley@rstudio.com", role = c("aut", "cre")), person("RStudio", role = c("cph", "fnd")) ) Description: Helpers for reordering factor levels (including moving specified levels to front, ordering by first appearance, reversing, and randomly shuffling), and tools for modifying factor levels (including collapsing rare levels into other, 'anonymising', and manually 'recoding'). License: GPL-3 URL: http://forcats.tidyverse.org, https://github.com/tidyverse/forcats BugReports: https://github.com/tidyverse/forcats/issues Depends: R (>= 3.1) Imports: magrittr, rlang, tibble Suggests: covr, ggplot2, testthat Encoding: UTF-8 LazyData: true RoxygenNote: 6.0.1 NeedsCompilation: no Packaged: 2018-02-19 17:34:45 UTC; hadley Author: Hadley Wickham [aut, cre], RStudio [cph, fnd] Maintainer: Hadley Wickham Repository: CRAN Date/Publication: 2018-02-19 19:43:26 UTC forcats/man/0000755000176200001440000000000013242605264012472 5ustar liggesusersforcats/man/figures/0000755000176200001440000000000013237652300014133 5ustar liggesusersforcats/man/figures/logo.png0000644000176200001440000006307113237652300015610 0ustar liggesusersPNG  IHDRxݠsRGB pHYs B(xiTXtXML:com.adobe.xmp www.inkscape.org 1 UX@IDATx\ŕ.~f'L@`r 6kc.qb/~~^0N ^PNCfY:/W]j@9.ؾ8q<l_4>#q=-@ L-j/owH*#7 6LO~/C-u 7r @&8BCI~q}&r2ˢ2Ͻ{-@! :e`v&dC%r-Nt`9{g^oHn=Q&K b{Y7kؾ9=*r[~:w(ցuIOk:I?vZ W k``^doewLY׃uBNO~64Q u_'!NSNȬ ԇe|dx}zoRw!kjy u= +Wt$3Ad^b4|Y׏F ua1Y3=3ȺVard܉ p ne~vs.u!rBw_VそY7Nl߆~'O)N~Ѹ?.aہklF{2g[x 8]46!|+ Po7|`D7~wum>7.t!D9]g/pG⋥7F?|CKo:N;>F馛]lY .H|ӟr4Mmg-˹;:ujseY_)YտAljEQQ&Y'm]_tŃWW.G։L4xw}wW_uҤI)S$wq.Cֿ|@9 /0|r?.T-#u<>s-ߏ^tJbןRJ)8KrԵL@#_|#2_IS)`v<͙3G͛fss/5ryGt=W.g_vX fff:sss%R7 *lJ!!YGN`̦ S)rҬ_"5ހL` 3J6 #ug౷H5*Тl9c< SӉq ͂ܞ6mfnN4i>nF'dR?#dR7&{#3>OWN;F;w i?@KYYY~0# Pc&س{m&###N [.\~vwg$lk1]W ?|?2Agb`[ʥI 2_^:b\fE}/Rob`d Phu;a !y9`>mٹ>vǷK ('#Ķ'N/hQ^;_B'\޾ Pl9>]hVeݪMo谬]B'nTO,ԾӤh<2r$/O]4h(ː٩r6,mϺ3Xx#KyYS_1-F7]p`=s'_XlWϭu=/8tw@M3&J J (sCKUl(l=x,\SRl=25d&FTId?򑏔|/@a魭5k6RvI&iӸUm?/djJ 5|wuawfa|6/Q;b{r&%` \ؓɓ Ƕ8@#UN4ċ^磾E˗Ms5+ט+VNXWUф1 {;o!OAfƒL %ˋр%2dj?@%r2;PEGS/6w_җ~URRXb2- b #tW+uXʅ+|xa;@k` 4GܒȟG li&}1\ةDn=+f͚׾'h-߸qLs1thPw$?*WU3VT~v$̯@v8za7raehcvٽ}de$,V\xܹS?Frrrb` OL ߽rC`|HL_~"nh;Z >Tll[Svᗆ5h7UKSW/ÇU{4ڇ?Q`?6(DCZEEE`6efǰj?Zl?.e3&?-mF 鵳b~GvQߟ\+۶ll *rh5UYP(zc4_2Q )v8f˒'ҙ2\َK bB"*r70{}@7ϝaub[Kxw#??ŁoI؏_gds#tIoJ Qw뭷߁c ʵUV:};TzF}v̌23Ξd64,>U5=Cx̙iHXQMǟ T"eu=<<1-TPъ8Br  reGV,'g؈[6Q{!{|A"E Ѯ|f7@G3R~I;?D4r!2Lz'~spMٟԧ]*P---͛PJ=A&/ay}Y2wt/.¢?\eu9ы7lTzY`XLqI<8,;%r`dM%E*͞=[)Kn2::*T'OFXPOt\x,fl ߑA \=߾y @礴E܎udO73G2yi|!ɣ 9lMgc8 l*lR슊 FE5D"E`&YeG/D9|`a[+ʲ0|ؐ3/?`82!Aqfya/Α汄 tC"T`v4.a)R^~eAb~_eŢmrݒ2)/࢖2f@p\mfh̾LU44]1ceƈCr2x%rGېxfɽڲeƫ~r-Bzw0ΩR6,96S]^~()3W3$:+CG@yHGf̞V+Y9JPiL(\6JTCe+.UK N[,3h@A{+i,Gl )]y, JsVQ4"Кw5HRJԎMzxyT+% aR04cFEL :뫞4]Kŝ((@-! v))(vWT%SdphXu$  29AVM % >GLVx75JV76 RKx8rR~8޸Ƿ?j [m . jjv%50rU%vq喊Bn떎>S4+E RM Zt#Chlj:%,f8${R 3NN2t)ұaa`'BP vbyϭ?|X6cnLn%V=ye_^OlP E0]}M6N0[2Bu QN2Utx!ǂ/ WRI{J$Ƒٛ=1[<پ}ڠ%K \,#{@±tfq$|$bHam1_|(b$<|m/:{nG &htm{*Vah u?5TDLdýU"f2[Nz!9xrWo6lƃCC g- ꅡ 'd 1S$)8nAL)ud˺>_2GڥnO+'1 m#bhFa-2&]s;_ly):Ui5'yhbI8/8묳xU ̬֭[vlei7tI{o$cŭd%6Pl/({A$\tҏj4tIFVE}~@дPkd[obL#?h=M'DpuOzTPc#F )PNt(.#D*Ry|_%*J8d[V9Jp4զxP8xx#n%3'I'M-_>}-i$|6Fm_]V4y4>Zwϔu;_߮|)+j‹؈$9m g6JKsFqi"{ӷm8L(bLHP@=lf;l!72 (W1On/)t a2;N3Q"DCΫ-3.2h-H,jY8+`iD? \Roucn}m|5G*"P c8Gvpu,y@0vo]xjt:) 1kerfs*1UlgXԖ=hkZήM"gW\lxOR7 O>IU>Nn/¬lYZ*&ϝ/`=Ƹ+*KK%׆ uren4DL{ E$'fvI@IgI^J(D)pHXv JCk+=JD m(sfHِng|? Ů|V*oߞ7fʬ%24Qg 5; ?6["h?7qjQL.,P BQ(w]kʼnlOƢyf"dTژh矕>m: |>04z&rKNB5W'L{ɶÝO!A?n!u9,qtPΐ#Z վzW6h;7pG !Wd V1 n3je$\P=[/5Ć+\捉݋KҴrl7?+ʔvVs$>,=Qg4,1鲳1؁׼ѧ:Fi 3zw>(^x|Q54褃x;3佾Ԩ{Fg,,D]A(G\zAU2!d(KnpPgEKEK3(F\bA*#yfAW~)H0nqs 2mR뮟l`l[-jX:-.=b|s3qcѐedYG1P Js߰pe(PK5`T.øZu_|Q٥"s Nj\ ,ZL.3p.Q5S&Khf\: JpNP"P(W h;PGAH#eղbTٹi :eyrL8C`y{#"ٍ` \,3ϵ5N m%H`C36n:;hAOTx/ N &GIX6;}L*FԈG3G22(}GM*R?^dfϔ2y$w`p0}9hF\<\ pѼh"oM%h0 1Nl`#]~ōS]ꑈ]exf"qŽ{o;a]9+탁Đ nWNu6dI?^({&Č늽|P 3NHs:Ȱ7blN s$ؠ@D+1^4@B4 )H{[_A6}tYcUU'+++U3BNY{)WK6ˬfx 3؝q41 *ɲX'_gGdp(Ljo#p!`B h퓒|D: $MX@Eȑ<)Iuq CTTȰö32 hD3͘j\{vZB>Zsvufk(V6 6@ҟ␊LL,/|Auհ(`By d" T'] 3Y*{̤dƫ9gA^,eyq ^ 'Ւȟ۶b/6sr\YW8CFO(8[.YadYU 'h$gL{L@I@p`* ]lrd/~l/vtFKGa"<x`Յ89{fl8JgYRΤ> UjO)T;`v4j'G `aРk YWt5<ĺrF(N>daaB=APnW;܍%8L#3DkeI)|:OzB!gcV`ԟT83taK,#KbeFŝ>;,oLb]q،z3Uav<*c( LZ6<2|&RY jɡ)DE&Țp: IN@̔΁Aؚh8{jMEԤ&x& 0߁3<)N 'ȔfOAIՔIt1GG.1 !^cST}Dà@<_|@>F\u?H}0AAd0tӊ Aahy>דCh>YL̆'n\sюWwR*rcJB\S399q|&;ߟבXF"$ .R`>or\JԔbFê|e C4 S1@ q{-A4P$Vt<ç7e[1a`QFax 3# *33i2##HɤFLO!9UЪaAf}ة"3*2P d'e&b/;S/߉`>r)x=M&;I@="ϕ d^OUU l7S2CuI9Vuae7> PL"e4Kق|6!㙐`vpH\m6܆ٗK aQ |QC,'H̤ljŔaddwZ<ΠJ fbEk~^EImUP8FfidǤa$r"Y:;$ǸZ c=6lؠI;e|յutɷn]!gO͕ S/ZV n1-([PkČNqVs$<-(`0cҏQ0 J`v@Nz0F9}-G@rHfgWS+08 E͘:Vp?dQ0q>\\f> >LV^O)<{ 5*<.%fmAiL0؄# qɝ_JlѨ'1(Q6 Nsqåe_Y[BCde7v'6ؘ-n#ryVC^'6YS2WJO ঃ{rA66hb#TFI~>}F廒3s ϳslr*:Qq'y>~1B*z6 GXL6/WF 8"MÂEjD'CUNLr̉cC ,`bi pGw$ L%˗%PNѰb^@юXFJe&BA8@ISAz}g+Ш$r?|.jEԢY#В=x_S"L˕Є1qS^K1l w0Y6"d0iPJne`r&6Az dk?V`Cr;(J8M.ni% 6#ltjx8V[؈'kr6`k' 4Y1NAWϴ]Ӳ3iqB^Rwtw̮CRv|eM!*ܪ{Bv{K1vrZIv |kqNͺDOyOZxa &ɽ[dF%<-}a+I6+Ś~z]1H)2 qC&Ѱ!$ccB6b:NEC.*~'J|.lz(j&㏫_ o_*%yS*3.X2b.Lf ;|8)ܒuZ C%̉uD_ 9[d4iאԢ9IqHL r[lEqګ؂r:ɹ2fz+MB.{R& G+ ])44h6}<A76fV΢;I2i`@QɔLW훠rE e<; {c!RU92FR "&_z(P 8rpĆla,)aT~ tx~I2| .Y S}j䬩yRkD7  [5foa)@( s"H2zΆWG)/WdfOgȥ3K>1T'@`VJ'`Q+$K9_GMT[7ZhxBK JLuHdt%Ĥ8!kgRI{W=UUՐυ3;e]:;NFԁ8ʋBznw Gx!xr!Bn8"lrT,M=-E(*$1#qa\, sӦ`U (`ɮ1 ^6фmR>Oa滜U]$K`ǀ?#lG[tL%lhB6Q;Dtuld͂I `q@9JIP3߁d)T`6<6PRo/CY7g&6n<>Wz*̧a R)lzf 7`Ȝ9 :`3B3QYPtlKyoUt.cE\6`7XyuCs K6KmXS,Ae&xlp .'zR;5Ԍ)?u"k'M0S¥տ|Nt>u`_^/2Iآ4ؙٺ8o"(2]7sΓ*31$/X3Jx0Q`Ъ1_s9ܰ !OT5()C(LTcԂ5S,iP*VR6DBg%yg~:o*ˠ$} r ""$] rM] @ScNr'(:αL,mIv9 {A()ڈy=e--J Q@uSRqpKY3a<9m D}{׀?]ADGԜم9{;rV)ktEL͕olkEmE8n4+dؠ,C$Zs(Ngg `>:)駟V|׽[󖏥~48c?෬ .=\W[GcT89=2f0@U/vA>tt0@&W<޾c*/^c d'T^r0LV6CDPBJq"T S뢘S0;$|)I1VJ?`ȋrӹ~]){ӜnSl ك[ xѢkX0|\㕩U2rrKK!:a>e*FN$l:,aK.`hm?(cI!ÍE&kZݣkzXRw t *(wQ .Cq yM:d,%%.*LʖW_ P"Pd4HpTØ͐.XB9}Κgy#vl}ً3g@6lަŹUeh&h*XLje5 4\=, XLo Nl_ʪ2U(F(>d3)iټI~:l,-.SJ`5 9mtu*մP6 )j={zcp7vkr\"Kڱ XP!1pz\3arOZW(q ؋s@ M(0&mX?( |z'uh0r⦺\r,l+GD IJmGAӦHÑFWHIک0Vj"ɤC9rjP%0^]H`Qaj[²^J_[Y6O2SPi tpU-QRv2<32hfbaN5or2EbRdddX"1yFC8waMa;d 3<SƔByW`6o?EǏ=D~D<,q !H=Q3cR |0`C#+h#.و>5,(n8K -xV5fabGD11{%fRФ&F|g~r=q78 -,R\[_%y(gӑB/ jA(*%p/ˋP\P:+RS1AV-Xn\eaU(S- Y$51Sͪ Jpl|1L[%2~,2=^v!/'_/gR%P2ԃ! QhB0X Nz;3* :m[^cz 3 EI,J㔣*yR\Qv w)Sn>V6NI=q| 1M֝ BUYdhp!$+'0܈"Nr8S [,xhb9.Nz:ƯJ ĭD0&yiih-H+*,7^ hpdS+>D܄%5^^? G FRu )Fh#IDAT390 % ܄"l vS}mrk8wjA a*/IJ[;0|Lz΂V %tEz7u.yM؁X@ W[xT,P"=i1Pk (FYa{MAFV|GqβdGzrK{;&);̮QuPnB\v;Iz%W̝?O!W@b%cNiD6:H^(: CA^9*xJU`f5y3C[@e`SOhku*{}\q7bW3~I},!1 t&p-cr0ײsX~my7t1Ŧ„=BqF>|AXvJˤ$'_4Rw1t1a0E 8,8TD%ifSsM-:);O+ Eh:+'XD'PN$QCL:mSu^n*D\CK-5&FD )5FK:f7e'a9`,G#?VV   ˨>Pk$+:͟;Ax~N_21ze;Z:c})Ⱥ9e\4@`PӻBI!BC'4EHu`zV@O>o_p A/NN6㋹CЀ34(;YZw̧mX +葵^aً.X$_nL#ʃn|+{PWZcYCFMfqJ>92ưb`'4a/ET4E7>ԡM "|A> A%WuW˞yͲǡ(px~7Nf"r/^ (3 I AXd "Q}TE ;5󻈌pϣK̅țɟ_=(u|_-{dlqMU8a|Ȁμa/(S\((pmA>`g.FW\xdA IpbjfMj&NT¡j$EB?vyR;HQ(c +UK )w87@ynjP4F~., rՃ()H%;AJ%8(w{uXC?Q]r=娲9N U#4  -=>%|3OPB&L.I 2cd\yi[RW,b.\9; A?qB`0MDdt]GpGX +ch6.?O*&O C@HfR%Њ-P.}biܼt|즛\&7.'#eKA␍Шh'uPnPsVoL:U2 QISO=3Qz2T@06i[R*gWW˝PF䱗a|z 5O*odXNj=cFƮ6@yX9=]2diG{26n pe^yWd,OO%wI"dKhxLͻ`zxB‚93*52,~lSf]AX(91\xv3Tf@G NoԏcɒceX/fk|E*K ϓ=Uߤ+Ii5KR3):"0F`7rkz mGɫmG@=jiXGŨEaӾtr|6Cz;[MZrѴč5i\v hG7/픟<_+Űu&'0%Q+eA7@eR*[ǓSaȢR8"! +29bUk<(R8S +:#Qy54"ƎyXr" sLM{&,o:L ;e^dYX$m)9&š)Y vI0;ٝ)6 k0we >3yjW'06- ,g6PW|7l(Ek얃@a ͇٧ֿ:? h-WHM}D!m(Q&W;l (q/&7([hsWzh>ʖ>9&΄'TYj) nxJvR\V["q k-?q̯)5ׅ5rZRޢ({)l<K1^҆UOnZ>KM)$mQ._+55"*< =rbp|Nt\v̌XX@1dqL,sK\&9Hr',DoZ@l@gCbvi+MkvXn0n-R_* DM}On=@9n;߉AW㫣@5Pz$08qo a`?c깸ю غIid9p;U[0+䞿":Usq)VWeO_^[Ι,מa8mJ&9KgB~Lj*,0֮jۚ䉗^"p.ˑ,, @i1h\ʝê(/Rr tj!5hRIrRD&|c#=}~fH/QV\)3._kM7+玑ŘX&AF#k &PIYqBD@şڰKyr9 ^P3e9]ڍ~Q,&%͎Xѣ_7:M{%5s:>}FX4 쐚*.HJ6ˡTC_\_n^R +z߲CvuKBGBYm<@Sqb6`THj).\CG>ivqhu-)Z Aqhcc[_yUsg3 s> b9TbND#}͇ufIǛbWgD* q\(yR] XiM)͗iִ&JD@!z|.T:A!ΓjlFCHb\hR!@1kyqu̓^ۯ^,5U*4-T$U.6nD6roೱ fbnⵦyٍrռrlTdb8 xK%]otY,1e0tOR*#kZ1W6h܃v?_ͺ/twx'ϓ*?SIm9S ڲ^O"c= HxJ=ytBp'Asa%ݮd7kkn`Μ.yHno|ꥲ*ethTPÊ?4vwKyM\6o!PrhS_51NÌ-w0m;dpW>#{Uy ŏ}@\_",m `}tt84}_JI2=93n'6[_w\mr%k ) &C˔ _|: !(J\F'h Y|V, stVAk][~&yt,@9~y²خ.P~qB$5´1+;Rd; (NV "F%F`p4ͬɅwBl<~w=vMUhu10_J$:PئCQ<;G.RĠ1ގ|NR?6z0-U PjaXΪ|| 2w4K9Idɚ;;tdd/VUUy G1OO>3]`LySLr|U02ħX2}TB!s(ij =[ po`GMoy}s^C_43_X76DB^``}s밿nVzKߺlY1sR,/b9~KB KXS$%#L;QsHT̆K=0c#f AzL яK3 Jpl !d⩮X(PXb6S#0IfǰLa*zP׸Jz;_vr:i,Nk M*' E33XymC>FYq\QW@r2vU?ץ' k;% ja`60(7!P&m>EuF(u6>zʾ.k77fx&6B`ܓ&;Nzű,:9S2zuvG' [ gSeۊ h4&h X&9z^ @ W,ODU aC[xp7 }#R축A% a0?Ol="/= c^FnH11r@Ѥ  )nVc TJR(@*Kñ͍݉_>vlO]akʲ?udnL<sB=WrT>} 澈䌭uP\Qci0Ay d=NWDJyq}3$W.dp:S Ԋo5b)E|(ll8(_,>\tȰ#S=fr+e*u-(W8֞$$FygdlJO%/c_KX%N .aVc89=xj޶P8ZpOZ>tFXNT1 Nhuø?.RlOSZXd&`8+mSBk_Z[e3ނK^MBcxmL-6`t AJٷ*y-}ˤzzR0cl>5}rW߽jmoS.cIy_s8.m|.~mV^6>t'cG:GB0/|'.G3iA>|&Iv&x`]~JI2Q$Zr1lM^! 50Vtr\} IVL*TcetZhy"K'IM pDGd=9g}/jn]05U-)6Ź'k$슉SSVҢᱱOlvM+1FlD~VK*,XRP3]oԬnI:j?FBpޠ!6Ko{#S'ASRa=Jf-at71.?o J3,,_ !`UV$KXWFc7G"GWmm:] DیB6"&zlfJX"HUWFM6w*G@_E(e5>5܁dE)[Je1 ʀ8182ܝhꏮj>͎/[[|l$ R- )-_{WEgv[荭k*-mAKE`lcQ`PC /J5@$lhҋԶ;3~ow[Kl.5әyμ7s݋=&I4#!MKM{XZxm~BivEUlL D\d(EEt%*-PkCx]~F'#̐9bG̝…W7&ߑK jvcH2̻yr/1x8J<3;tq'eeK %CF,h9P~p8!̓B ¤{'D4@0?-Pc\xcBN` LpAH}7GT|Δrr X-%?'=!jWzQ3@R]'Ǹ?&Ϲ%).QԽ7_J#ɑAA3!*=ASƏ玿 Glv $TPhRp:([,L9fR1xSnNW;'4TZ0t10}e.sr|6-6;#b}kxyzvJ-.,Uu}d96b O*T*E9|aZDukj (G2yFש]׺ONVCC.$xfVsm'yh}XC{~UlbC* n"&n#ZK`tUkTau#f۠7Chi`0?s@&IL^L .*Zxb9$ P\gv]yXq,5ř3wZႫ| s"P>w4wb*YwćU4wZڷqpIJ/>9s4#!C> %^>~? M=T(%3kpBmRVj&=pAp~.GewFıI"D#èN&SeŸ">uSs GqsbBPWiA<3IB)0P+F]U ɴVQu4q(!(ke:CE (?o%E=Z4-r@k&K x5]js;|,i𓢒,dhn@"x&QR & b4NY6 , [EK8!)D|5 F6`A%*ƲRK7VfaETXqxY>翴`1<n3"> w?Gc6LF=^ 3(Nk6PxGvc+;Z*ڛjO;ڦ/H;V(U͸m.]7M%lĿYkmYprڊ7qyiݢ$[9<%|dgNQB &pi/f(dZHUG^8j>NOݟs)g95Osق[_ݴXȲ@K͋5O5WI3$3ZRVWh[UpA[ނkӞb(ƛpsd́Ly9/dd`EZSzl^k%col2 %g%c Sk#(۩7l+kpղ١ۿ\{](x/Aʣ1n؆EĂML w8)fW]$9Ə6Y UZ3 .Z\%} \alias{\%>\%} \title{Pipe operator} \usage{ lhs \%>\% rhs } \description{ See \code{\link[magrittr]{\%>\%}} for more details. } \keyword{internal} forcats/man/fct_count.Rd0000644000176200001440000000104313240326422014735 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/count.R \name{fct_count} \alias{fct_count} \title{Count entries in a factor} \usage{ fct_count(f, sort = FALSE) } \arguments{ \item{f}{A factor (or character vector).} \item{sort}{If \code{TRUE}, sort the result so that the most common values float to the top.} } \value{ A tibble with columns \code{f} and \code{n}. } \description{ Count entries in a factor } \examples{ f <- factor(sample(letters)[rpois(1000, 10)]) table(f) fct_count(f) fct_count(f, sort = TRUE) } forcats/man/fct_relevel.Rd0000644000176200001440000000231313240326422015244 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/relevel.R \name{fct_relevel} \alias{fct_relevel} \title{Reorder factor levels by hand} \usage{ fct_relevel(.f, ..., after = 0L) } \arguments{ \item{.f}{A factor (or character vector).} \item{...}{Character vector of levels. Any levels not mentioned will be left in existing order, after the explicitly mentioned levels. Supports tidy dots.} \item{after}{Where should the new values be placed?} } \description{ This is a generalisaton of \code{\link[stats:relevel]{stats::relevel()}} that allows you to move any number of levels to any location. } \examples{ f <- factor(c("a", "b", "c", "d")) fct_relevel(f) fct_relevel(f, "c") fct_relevel(f, "b", "a") # Move to the third position fct_relevel(f, "a", after = 2) # Relevel to the end fct_relevel(f, "a", after = Inf) fct_relevel(f, "a", after = 3) # Using 'Inf' allows you to relevel to the end when the number # of levels is unknown or variable (e.g. vectorised operations) df <- forcats::gss_cat[, c("rincome", "denom")] lapply(df, levels) df2 <- lapply(df, fct_relevel, "Don't know", after = Inf) lapply(df2, levels) # You'll get a warning if the levels don't exist fct_relevel(f, "e") } forcats/man/fct_other.Rd0000644000176200001440000000156313240326422014735 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/other.R \name{fct_other} \alias{fct_other} \title{Replace levels with "other"} \usage{ fct_other(f, keep, drop, other_level = "Other") } \arguments{ \item{f}{A factor (or character vector).} \item{keep, drop}{\code{keep} will preserve listed levels, replacing all others with \code{other_level}. \code{drop} will replace listed levels with \code{other_level}, keeping all others as they are.} \item{other_level}{Value of level used for "other" values. Always placed at end of levels.} } \description{ Replace levels with "other" } \examples{ x <- factor(rep(LETTERS[1:9], times = c(40, 10, 5, 27, 1, 1, 1, 1, 1))) fct_other(x, keep = c("A", "B")) fct_other(x, drop = c("A", "B")) } \seealso{ \code{\link[=fct_lump]{fct_lump()}} to automatically convert the rarest (or most common) levels to "other". } forcats/man/fct_collapse.Rd0000644000176200001440000000142413240326422015412 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/collapse.R \name{fct_collapse} \alias{fct_collapse} \title{Collapse factor levels into manually defined groups} \usage{ fct_collapse(.f, ...) } \arguments{ \item{.f}{A factor (or character vector).} \item{...}{A series of named character vectors. The levels in each vector will be replaced with the name.} } \description{ Collapse factor levels into manually defined groups } \examples{ fct_count(gss_cat$partyid) partyid2 <- fct_collapse(gss_cat$partyid, missing = c("No answer", "Don't know"), other = "Other party", rep = c("Strong republican", "Not str republican"), ind = c("Ind,near rep", "Independent", "Ind,near dem"), dem = c("Not str democrat", "Strong democrat") ) fct_count(partyid2) } forcats/man/fct_recode.Rd0000644000176200001440000000150613240326422015052 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/recode.R \name{fct_recode} \alias{fct_recode} \title{Change factor levels by hand} \usage{ fct_recode(.f, ...) } \arguments{ \item{.f}{A factor (or character vector).} \item{...}{A sequence of named character vectors where the name gives the new level, and the value gives the old level. Levels not otherwise mentioned will be left as is. Levels can be removed by naming them \code{NULL}. Uses tidy dots.} } \description{ Change factor levels by hand } \examples{ x <- factor(c("apple", "bear", "banana", "dear")) fct_recode(x, fruit = "apple", fruit = "banana") # If you make a mistake you'll get a warning fct_recode(x, fruit = "apple", fruit = "bananana") # If you name the level NULL it will be removed fct_recode(x, NULL = "apple", fruit = "banana") } forcats/man/gss_cat.Rd0000644000176200001440000000142313031476321014400 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/data.R \docType{data} \name{gss_cat} \alias{gss_cat} \title{A sample of categorical variables from the General Social survey} \format{\describe{ \item{year}{year of survey, 2000--2014} \item{age}{age. Maximum age truncated to 89.} \item{marital}{marital status} \item{race}{race} \item{rincome}{reported income} \item{partyid}{party affiliation} \item{relig}{religion} \item{denom}{denomination} \item{tvhours}{hours per day watching tv} }} \source{ Downloaded from \url{https://gssdataexplorer.norc.org/}. } \usage{ gss_cat } \description{ A sample of categorical variables from the General Social survey } \examples{ gss_cat fct_count(gss_cat$relig) fct_count(fct_lump(gss_cat$relig)) } \keyword{datasets} forcats/man/lvls.Rd0000644000176200001440000000246013240326450013736 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/lvls.R \name{lvls} \alias{lvls} \alias{lvls_reorder} \alias{lvls_revalue} \alias{lvls_expand} \title{Low-level functions for manipulating levels} \usage{ lvls_reorder(f, idx, ordered = NA) lvls_revalue(f, new_levels) lvls_expand(f, new_levels) } \arguments{ \item{f}{A factor (or character vector).} \item{idx}{A integer index, with one integer for each existing level.} \item{ordered}{A logical which determines the "ordered" status of the output factor. \code{NA} preserves the existing status of the factor.} \item{new_levels}{A character vector of new levels.} } \description{ \code{lvls_reorder} leaves values as they are, but changes the order. \code{lvls_revalue} changes the values of existing levels; there must be one new level for each old level. \code{lvls_expand} expands the set of levels; the new levels must include the old levels. } \details{ These functions are less helpful than the higher-level \code{fct_} functions, but are safer than the very low-level manipulation of levels directly, because they are more specific, and hence can more carefully check their arguments. } \examples{ f <- factor(c("a", "b", "c")) lvls_reorder(f, 3:1) lvls_revalue(f, c("apple", "banana", "carrot")) lvls_expand(f, c("a", "b", "c", "d")) } forcats/man/fct_drop.Rd0000644000176200001440000000124013240326422014550 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/drop.R \name{fct_drop} \alias{fct_drop} \title{Drop unused levels} \usage{ fct_drop(f, only) } \arguments{ \item{f}{A factor (or character vector).} \item{only}{A character vector restricting the set of levels to be dropped. If supplied, only levels that have no entries and appear in this vector will be removed.} } \description{ Compared to \code{base::droplevels()}, does not drop \code{NA} levels that have values. } \examples{ f <- factor(c("a", "b"), levels = c("a", "b", "c")) f fct_drop(f) # Set only to restrict which levels to drop fct_drop(f, only = "a") fct_drop(f, only = "c") } forcats/man/fct_reorder.Rd0000644000176200001440000000362513240326450015260 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/reorder.R \name{fct_reorder} \alias{fct_reorder} \alias{fct_reorder2} \alias{last2} \title{Reorder factor levels by sorting along another variable} \usage{ fct_reorder(.f, .x, .fun = median, ..., .desc = FALSE) fct_reorder2(.f, .x, .y, .fun = last2, ..., .desc = TRUE) last2(.x, .y) } \arguments{ \item{.f}{A factor (or character vector).} \item{.x, .y}{The levels of \code{f} are reordered so that the values of \code{.fun(.x)} (for \code{fct_reorder()}) and \code{fun(.x, .y)} (for \code{fct_reorder2()}) are in ascending order.} \item{.fun}{n summary function. It should take one vector for \code{fct_reorder}, and two vectors for \code{fct_reorder2}.} \item{...}{Other arguments passed on to \code{.fun}. A common argument is \code{na.rm = TRUE}.} \item{.desc}{Order in descending order? Note the default is different between \code{fct_reorder} and \code{fct_reorder2}, in order to match the default ordering of factors in the legend.} } \description{ \code{fct_reorder()} is useful for 1d displays where the factor is mapped to position; \code{fct_reorder2()} for 2d displays where the factor is mapped to a non-position aesthetic. \code{last2()} is a helper for \code{fct_reorder2()}; it finds the last value of \code{y} when sorted by \code{x}. } \examples{ boxplot(Sepal.Width ~ Species, data = iris) boxplot(Sepal.Width ~ fct_reorder(Species, Sepal.Width), data = iris) boxplot(Sepal.Width ~ fct_reorder(Species, Sepal.Width, .desc = TRUE), data = iris) chks <- subset(ChickWeight, as.integer(Chick) < 10) chks <- transform(chks, Chick = fct_shuffle(Chick)) if (require("ggplot2")) { ggplot(chks, aes(Time, weight, colour = Chick)) + geom_point() + geom_line() # Note that lines match order in legend ggplot(chks, aes(Time, weight, colour = fct_reorder2(Chick, Time, weight))) + geom_point() + geom_line() + labs(colour = "Chick") } } forcats/man/forcats-package.Rd0000644000176200001440000000162213241142777016020 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/forcats-package.R \docType{package} \name{forcats-package} \alias{forcats} \alias{forcats-package} \title{forcats: Tools for Working with Categorical Variables (Factors)} \description{ Helpers for reordering factor levels (including moving specified levels to front, ordering by first appearance, reversing, and randomly shuffling), and tools for modifying factor levels (including collapsing rare levels into other, 'anonymising', and manually 'recoding'). } \seealso{ Useful links: \itemize{ \item \url{http://forcats.tidyverse.org} \item \url{https://github.com/tidyverse/forcats} \item Report bugs at \url{https://github.com/tidyverse/forcats/issues} } } \author{ \strong{Maintainer}: Hadley Wickham \email{hadley@rstudio.com} Other contributors: \itemize{ \item RStudio [copyright holder, funder] } } \keyword{internal} forcats/man/lvls_union.Rd0000644000176200001440000000056713031476321015155 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/lvls.R \name{lvls_union} \alias{lvls_union} \title{Find all levels in a list of factors} \usage{ lvls_union(fs) } \arguments{ \item{fs}{A list of factors.} } \description{ Find all levels in a list of factors } \examples{ fs <- list(factor("a"), factor("b"), factor(c("a", "b"))) lvls_union(fs) } forcats/man/fct_unify.Rd0000644000176200001440000000075013031476321014745 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/c.R \name{fct_unify} \alias{fct_unify} \title{Unify the levels in a list of factors} \usage{ fct_unify(fs, levels = lvls_union(fs)) } \arguments{ \item{fs}{A list of factors} \item{levels}{Set of levels to apply to every factor. Default to union of all factor levels} } \description{ Unify the levels in a list of factors } \examples{ fs <- list(factor("a"), factor("b"), factor(c("a", "b"))) fct_unify(fs) } forcats/man/as_factor.Rd0000644000176200001440000000134213237652277014734 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/as_factor.R \name{as_factor} \alias{as_factor} \alias{as_factor.factor} \alias{as_factor.character} \title{Convert input to a factor.} \usage{ as_factor(x, ...) \method{as_factor}{factor}(x, ...) \method{as_factor}{character}(x, ...) } \arguments{ \item{x}{Object to coerce to a factor.} \item{...}{Other arguments passed down to method.} } \description{ Compared to base R, this function creates levels in the order in which they appear, which will be the same on every platform. (Base R sorts in the current locale which can vary from place to place.) } \details{ This is a generic function. } \examples{ x <- c("a", "z", "g") as_factor(x) as.factor(x) } forcats/man/fct_rev.Rd0000644000176200001440000000053613240326422014407 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/rev.R \name{fct_rev} \alias{fct_rev} \title{Reverse order of factor levels} \usage{ fct_rev(f) } \arguments{ \item{f}{A factor (or character vector).} } \description{ This is sometimes useful when plotting a factor. } \examples{ f <- factor(c("a", "b", "c")) fct_rev(f) } forcats/man/fct_expand.Rd0000644000176200001440000000102513240326422015064 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/expand.R \name{fct_expand} \alias{fct_expand} \title{Add additional levels to a factor} \usage{ fct_expand(f, ...) } \arguments{ \item{f}{A factor (or character vector).} \item{...}{Additional levels to add to the factor. Levels that already exist will be silently ignored.} } \description{ Add additional levels to a factor } \examples{ f <- factor(sample(letters[1:3], 20, replace = TRUE)) f fct_expand(f, "d", "e", "f") fct_expand(f, letters[1:6]) } forcats/man/fct_anon.Rd0000644000176200001440000000116213237652277014562 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/anon.R \name{fct_anon} \alias{fct_anon} \title{Anonymise factor levels} \usage{ fct_anon(f, prefix = "") } \arguments{ \item{f}{A factor.} \item{prefix}{A character prefix to insert in front of the random labels.} } \description{ Replaces factor levels with arbitary numeric identifiers. Neither the values nor the order of the levels are preserved. } \examples{ gss_cat$relig \%>\% fct_count() gss_cat$relig \%>\% fct_anon() \%>\% fct_count() gss_cat$relig \%>\% fct_anon() \%>\% fct_count() gss_cat$relig \%>\% fct_anon("X") \%>\% fct_count() } forcats/man/fct_unique.Rd0000644000176200001440000000057713237652277015146 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/unique.R \name{fct_unique} \alias{fct_unique} \title{Unique values of a factor} \usage{ fct_unique(f) } \arguments{ \item{f}{A factor.} } \description{ Unique values of a factor } \examples{ f <- factor(letters[rpois(100, 10)]) unique(f) # in order of appearance fct_unique(f) # in order of levels } forcats/man/fct_shuffle.Rd0000644000176200001440000000055713240326422015252 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/shuffle.R \name{fct_shuffle} \alias{fct_shuffle} \title{Randomly permute factor levels} \usage{ fct_shuffle(f) } \arguments{ \item{f}{A factor (or character vector).} } \description{ Randomly permute factor levels } \examples{ f <- factor(c("a", "b", "c")) fct_shuffle(f) fct_shuffle(f) } forcats/man/fct_relabel.Rd0000644000176200001440000000230013241143262015210 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/relabel.R \name{fct_relabel} \alias{fct_relabel} \title{Automatically relabel factor levels, collapse as necessary} \usage{ fct_relabel(.f, .fun, ...) } \arguments{ \item{.f}{A factor.} \item{.fun}{A function to be applied to each level. Must accept one character argument and return a character vector of the same length as its input. You can also use \code{~} to create as shorthand (in the style of purrr). \code{~ paste(., "x")} is equivalent to \code{function(.) paste(., "x")}} \item{...}{Additional arguments to \code{fun}.} } \description{ Automatically relabel factor levels, collapse as necessary } \examples{ gss_cat$partyid \%>\% fct_count() gss_cat$partyid \%>\% fct_relabel(~ gsub(",", ", ", .x)) \%>\% fct_count() convert_income <- function(x) { regex <- "^(?:Lt |)[$]([0-9]+).*$" is_range <- grepl(regex, x) num_income <- as.numeric(gsub(regex, "\\\\1", x[is_range])) num_income <- trunc(num_income / 5000) * 5000 x[is_range] <- paste0("Gt $", num_income) x } fct_count(gss_cat$rincome) convert_income(levels(gss_cat$rincome)) rincome2 <- fct_relabel(gss_cat$rincome, convert_income) fct_count(rincome2) } forcats/man/fct_shift.Rd0000644000176200001440000000122413031476321014725 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/shift.R \name{fct_shift} \alias{fct_shift} \title{Shift factor levels to left or right, wrapping around at end} \usage{ fct_shift(f, n = 1L) } \arguments{ \item{f}{A factor.} \item{n}{Positive values shift to the left; negative values shift to the right.} } \description{ This is useful when the levels of an ordered factor are actually cyclical, with different conventions on the starting point. } \examples{ x <- factor( c("Mon", "Tue", "Wed"), levels = c("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"), ordered = TRUE ) x fct_shift(x) fct_shift(x, 2) fct_shift(x, -1) } forcats/man/fct_inorder.Rd0000644000176200001440000000120613031477325015257 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/reorder.R \name{fct_inorder} \alias{fct_inorder} \alias{fct_infreq} \title{Reorder factors levels by first appearance or frequency} \usage{ fct_inorder(f, ordered = NA) fct_infreq(f, ordered = NA) } \arguments{ \item{f}{A factor} \item{ordered}{A logical which determines the "ordered" status of the output factor. \code{NA} preserves the existing status of the factor.} } \description{ Reorder factors levels by first appearance or frequency } \examples{ f <- factor(c("b", "b", "a", "c", "c", "c")) f fct_inorder(f) fct_infreq(f) fct_inorder(f, ordered = TRUE) } forcats/man/fct_c.Rd0000644000176200001440000000116513240323566014042 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/c.R \name{fct_c} \alias{fct_c} \title{Concatenate factors, combining levels} \usage{ fct_c(...) } \arguments{ \item{...}{Individual factors. Uses tidy dots, so you can splice in a list of factors with \code{!!!}.} } \description{ This is a useful way of patching together factors from multiple sources that really should have the same levels but don't. } \examples{ fa <- factor("a") fb <- factor("b") fab <- factor(c("a", "b")) c(fa, fb, fab) fct_c(fa, fb, fab) # You can also pass a list of factors with !!! fs <- list(fa, fb, fab) fct_c(!!!fs) } forcats/man/fct_explicit_na.Rd0000644000176200001440000000111013240326422016077 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/explicit_na.R \name{fct_explicit_na} \alias{fct_explicit_na} \title{Make missing values explicit} \usage{ fct_explicit_na(f, na_level = "(Missing)") } \arguments{ \item{f}{A factor (or character vector).} \item{na_level}{Level to use for missing values.} } \description{ This gives missing value an explicit factor level, ensuring that they appear in summaries and on plots. } \examples{ f1 <- factor(c("a", "a", NA, NA, "a", "b", NA, "c", "a", "c", "b")) table(f1) f2 <- fct_explicit_na(f1) table(f2) } forcats/man/fct_lump.Rd0000644000176200001440000000410413240326422014563 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/lump.R \name{fct_lump} \alias{fct_lump} \title{Lump together least/most common factor levels into "other"} \usage{ fct_lump(f, n, prop, w = NULL, other_level = "Other", ties.method = c("min", "average", "first", "last", "random", "max")) } \arguments{ \item{f}{A factor (or character vector).} \item{n, prop}{If both \code{n} and \code{prop} are missing, \code{fct_lump} lumps together the least frequent levels into "other", while ensuring that "other" is still the smallest level. It's particularly useful in conjunction with \code{\link{fct_inorder}()}. Positive \code{n} preserves the most common \code{n} values. Negative \code{n} preserves the least common \code{-n} values. It there are ties, you will get at least \code{abs(n)} values. Positive \code{prop} preserves values that appear at least \code{prop} of the time. Negative \code{prop} preserves values that appear at most \code{-prop} of the time.} \item{w}{An optional numeric vector giving weights for frequency of each value (not level) in f.} \item{other_level}{Value of level used for "other" values. Always placed at end of levels.} \item{ties.method}{A character string specifying how ties are treated. See \code{\link[=rank]{rank()}} for details.} } \description{ Lump together least/most common factor levels into "other" } \examples{ x <- factor(rep(LETTERS[1:9], times = c(40, 10, 5, 27, 1, 1, 1, 1, 1))) x \%>\% table() x \%>\% fct_lump() \%>\% table() x \%>\% fct_lump() \%>\% fct_inorder() \%>\% table() x <- factor(letters[rpois(100, 5)]) x table(x) table(fct_lump(x)) # Use positive values to collapse the rarest fct_lump(x, n = 3) fct_lump(x, prop = 0.1) # Use negative values to collapse the most common fct_lump(x, n = -3) fct_lump(x, prop = -0.1) # Use weighted frequencies w <- c(rep(2, 50), rep(1, 50)) fct_lump(x, n = 5, w = w) # Use ties.method to control how tied factors are collapsed fct_lump(x, n = 6) fct_lump(x, n = 6, ties.method = "max") } \seealso{ \code{\link[=fct_other]{fct_other()}} to convert specified levels to other. }