forcats/0000755000176200001440000000000013432271102011706 5ustar liggesusersforcats/inst/0000755000176200001440000000000013432266204012672 5ustar liggesusersforcats/inst/doc/0000755000176200001440000000000013432266204013437 5ustar liggesusersforcats/inst/doc/forcats.Rmd0000644000176200001440000001214413432022227015541 0ustar liggesusers--- title: "Introduction to forcats" author: "Emily Robinson" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Introduction to forcats} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) ``` The goal of the __forcats__ package is to provide a suite of useful tools that solve common problems with factors. Factors are useful when you have categorical data, variables that have a fixed and known set of values, and when you want to display character vectors in non-alphabetical order. If you want to learn more, the best place to start is the [chapter on factors](http://r4ds.had.co.nz/factors.html) in R for Data Science. ## Ordering by frequency ```{r message = FALSE} library(dplyr) library(ggplot2) library(forcats) ``` Let's try answering the question, "what are the most common hair colors of star wars characters?" Let's start off by making a bar plot: ```{r initial-plot} ggplot(starwars, aes(x = hair_color)) + geom_bar() + coord_flip() ``` That's okay, but it would be more helpful the graph was ordered by count. This is a case of an **unordered** categorical variable where we want it ordered by its frequency. To do so, we can use the function `fct_infreq()`: ```{r fct-infreq-hair} ggplot(starwars, aes(x = fct_infreq(hair_color))) + geom_bar() + coord_flip() ``` Note that `fct_infreq()` it automatically puts NA at the top, even though that doesn't have the smallest number of entries. ## Combining levels Let's take a look at skin color now: ```{r} starwars %>% count(skin_color, sort = TRUE) ``` We see that there's 31 different skin colors - if we want to make a plot this would be way too many to display! Let's reduce it to only be the top 5. We can use `fct_lump()` to "lump" all the infrequent colors into one factor, "other." The argument `n` is the number of levels we want to keep. ```{r} starwars %>% mutate(skin_color = fct_lump(skin_color, n = 5)) %>% count(skin_color, sort = TRUE) ``` We could also have used `prop` instead, which keeps all the levels that appear at least `prop` of the time. For example, let's keep skin colors that at least 10% of the characters have: ```{r} starwars %>% mutate(skin_color = fct_lump(skin_color, prop = .1)) %>% count(skin_color, sort = TRUE) ``` Only light and fair remain; everything else is other. If you wanted to call it something than "other", you can change it with the argument `other_level`: ```{r} starwars %>% mutate(skin_color = fct_lump(skin_color, prop = .1, other_level = "extra")) %>% count(skin_color, sort = TRUE) ``` What if we wanted to see if the average mass differed by eye color? We'll only look at the 6 most popular eye colors and remove `NA`s. ```{r fct-lump-mean} avg_mass_eye_color <- starwars %>% mutate(eye_color = fct_lump(eye_color, n = 6)) %>% group_by(eye_color) %>% summarise(mean_mass = mean(mass, na.rm = TRUE)) avg_mass_eye_color ``` ## Ordering by another variable It looks like people (or at least one person) with orange eyes are definitely heavier! If we wanted to make a graph, it would be nice if it was ordered by `mean_mass`. We can do this with `fct_reorder()`, which reorders one variable by another. ```{r fct-reorder} avg_mass_eye_color %>% mutate(eye_color = fct_reorder(eye_color, mean_mass)) %>% ggplot(aes(x = eye_color, y = mean_mass)) + geom_col() ``` ## Manually reordering Let's switch to using another dataset, `gss_cat`, the general social survey. What is the income distribution among the respondents? ```{r} gss_cat %>% count(rincome) ``` Notice that the income levels are in the correct order - they start with the non-answers and then go from highest to lowest. This is the same order you'd see if you plotted it as a bar chart. This is not a coincidence. When you're working with ordinal data, where there is an order, you can have an ordered factor. You can examine them with the base function `levels()`, which prints them in order: ```{r} levels(gss_cat$rincome) ``` But what if your factor came in the wrong order? Let's simulate that by reordering the levels of `rincome` randomly with `fct_shuffle()`: ```{r} reshuffled_income <- gss_cat$rincome %>% fct_shuffle() levels(reshuffled_income) ``` Now if we plotted it, it would show in this order, which is all over the place! How can we fix this and put it in the right order? We can use the function `fct_relevel()` when we need to manually reorder our factor levels. In addition to the factor, you give it a character vector of level names, and specify where you want to move them. It defaults to moving them to the front, but you can move them after another level with the argument `after`. If you want to move it to the end, you set `after` equal to `Inf`. For example, let's say we wanted to move `Lt $1000` and `$1000 to 2999` to the front. We would write: ```{r} fct_relevel(reshuffled_income, c("Lt $1000", "$1000 to 2999")) %>% levels() ``` What if we want to move them to the second and third place? ```{r} fct_relevel(reshuffled_income, c("Lt $1000", "$1000 to 2999"), after = 1) %>% levels() ``` forcats/inst/doc/forcats.R0000644000176200001440000000460013432266204015223 0ustar liggesusers## ----setup, include = FALSE---------------------------------------------- knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) ## ----message = FALSE----------------------------------------------------- library(dplyr) library(ggplot2) library(forcats) ## ----initial-plot-------------------------------------------------------- ggplot(starwars, aes(x = hair_color)) + geom_bar() + coord_flip() ## ----fct-infreq-hair----------------------------------------------------- ggplot(starwars, aes(x = fct_infreq(hair_color))) + geom_bar() + coord_flip() ## ------------------------------------------------------------------------ starwars %>% count(skin_color, sort = TRUE) ## ------------------------------------------------------------------------ starwars %>% mutate(skin_color = fct_lump(skin_color, n = 5)) %>% count(skin_color, sort = TRUE) ## ------------------------------------------------------------------------ starwars %>% mutate(skin_color = fct_lump(skin_color, prop = .1)) %>% count(skin_color, sort = TRUE) ## ------------------------------------------------------------------------ starwars %>% mutate(skin_color = fct_lump(skin_color, prop = .1, other_level = "extra")) %>% count(skin_color, sort = TRUE) ## ----fct-lump-mean------------------------------------------------------- avg_mass_eye_color <- starwars %>% mutate(eye_color = fct_lump(eye_color, n = 6)) %>% group_by(eye_color) %>% summarise(mean_mass = mean(mass, na.rm = TRUE)) avg_mass_eye_color ## ----fct-reorder--------------------------------------------------------- avg_mass_eye_color %>% mutate(eye_color = fct_reorder(eye_color, mean_mass)) %>% ggplot(aes(x = eye_color, y = mean_mass)) + geom_col() ## ------------------------------------------------------------------------ gss_cat %>% count(rincome) ## ------------------------------------------------------------------------ levels(gss_cat$rincome) ## ------------------------------------------------------------------------ reshuffled_income <- gss_cat$rincome %>% fct_shuffle() levels(reshuffled_income) ## ------------------------------------------------------------------------ fct_relevel(reshuffled_income, c("Lt $1000", "$1000 to 2999")) %>% levels() ## ------------------------------------------------------------------------ fct_relevel(reshuffled_income, c("Lt $1000", "$1000 to 2999"), after = 1) %>% levels() forcats/inst/doc/forcats.html0000644000176200001440000026210413432266204015773 0ustar liggesusers Introduction to forcats

Introduction to forcats

Emily Robinson

The goal of the forcats package is to provide a suite of useful tools that solve common problems with factors. Factors are useful when you have categorical data, variables that have a fixed and known set of values, and when you want to display character vectors in non-alphabetical order. If you want to learn more, the best place to start is the chapter on factors in R for Data Science.

Ordering by frequency

library(dplyr)
library(ggplot2)
library(forcats)

Let’s try answering the question, “what are the most common hair colors of star wars characters?” Let’s start off by making a bar plot:

ggplot(starwars, aes(x = hair_color)) + 
  geom_bar() + 
  coord_flip()

That’s okay, but it would be more helpful the graph was ordered by count. This is a case of an unordered categorical variable where we want it ordered by its frequency. To do so, we can use the function fct_infreq():

ggplot(starwars, aes(x = fct_infreq(hair_color))) + 
  geom_bar() + 
  coord_flip()

Note that fct_infreq() it automatically puts NA at the top, even though that doesn’t have the smallest number of entries.

Combining levels

Let’s take a look at skin color now:

starwars %>%
  count(skin_color, sort = TRUE)
#> # A tibble: 31 x 2
#>    skin_color     n
#>    <chr>      <int>
#>  1 fair          17
#>  2 light         11
#>  3 dark           6
#>  4 green          6
#>  5 grey           6
#>  6 pale           5
#>  7 brown          4
#>  8 blue           2
#>  9 blue, grey     2
#> 10 orange         2
#> # … with 21 more rows

We see that there’s 31 different skin colors - if we want to make a plot this would be way too many to display! Let’s reduce it to only be the top 5. We can use fct_lump() to “lump” all the infrequent colors into one factor, “other.” The argument n is the number of levels we want to keep.

starwars %>%
  mutate(skin_color = fct_lump(skin_color, n = 5)) %>%
  count(skin_color, sort = TRUE)
#> # A tibble: 6 x 2
#>   skin_color     n
#>   <fct>      <int>
#> 1 Other         41
#> 2 fair          17
#> 3 light         11
#> 4 dark           6
#> 5 green          6
#> 6 grey           6

We could also have used prop instead, which keeps all the levels that appear at least prop of the time. For example, let’s keep skin colors that at least 10% of the characters have:

starwars %>%
  mutate(skin_color = fct_lump(skin_color, prop = .1)) %>%
  count(skin_color, sort = TRUE)
#> # A tibble: 3 x 2
#>   skin_color     n
#>   <fct>      <int>
#> 1 Other         59
#> 2 fair          17
#> 3 light         11

Only light and fair remain; everything else is other.

If you wanted to call it something than “other”, you can change it with the argument other_level:

starwars %>%
  mutate(skin_color = fct_lump(skin_color, prop = .1, other_level = "extra")) %>%
  count(skin_color, sort = TRUE)
#> # A tibble: 3 x 2
#>   skin_color     n
#>   <fct>      <int>
#> 1 extra         59
#> 2 fair          17
#> 3 light         11

What if we wanted to see if the average mass differed by eye color? We’ll only look at the 6 most popular eye colors and remove NAs.

avg_mass_eye_color <- starwars %>%
  mutate(eye_color = fct_lump(eye_color, n = 6)) %>%
  group_by(eye_color) %>%
  summarise(mean_mass = mean(mass, na.rm = TRUE))

avg_mass_eye_color
#> # A tibble: 7 x 2
#>   eye_color mean_mass
#>   <fct>         <dbl>
#> 1 black          76.3
#> 2 blue           86.5
#> 3 brown          66.1
#> 4 orange        282. 
#> 5 red            81.4
#> 6 yellow         81.1
#> 7 Other          68.4

Ordering by another variable

It looks like people (or at least one person) with orange eyes are definitely heavier! If we wanted to make a graph, it would be nice if it was ordered by mean_mass. We can do this with fct_reorder(), which reorders one variable by another.

avg_mass_eye_color %>%
  mutate(eye_color = fct_reorder(eye_color, mean_mass)) %>%
  ggplot(aes(x = eye_color, y = mean_mass)) + 
  geom_col()

Manually reordering

Let’s switch to using another dataset, gss_cat, the general social survey. What is the income distribution among the respondents?

gss_cat %>%
  count(rincome)
#> # A tibble: 16 x 2
#>    rincome            n
#>    <fct>          <int>
#>  1 No answer        183
#>  2 Don't know       267
#>  3 Refused          975
#>  4 $25000 or more  7363
#>  5 $20000 - 24999  1283
#>  6 $15000 - 19999  1048
#>  7 $10000 - 14999  1168
#>  8 $8000 to 9999    340
#>  9 $7000 to 7999    188
#> 10 $6000 to 6999    215
#> 11 $5000 to 5999    227
#> 12 $4000 to 4999    226
#> 13 $3000 to 3999    276
#> 14 $1000 to 2999    395
#> 15 Lt $1000         286
#> 16 Not applicable  7043

Notice that the income levels are in the correct order - they start with the non-answers and then go from highest to lowest. This is the same order you’d see if you plotted it as a bar chart. This is not a coincidence. When you’re working with ordinal data, where there is an order, you can have an ordered factor. You can examine them with the base function levels(), which prints them in order:

levels(gss_cat$rincome)
#>  [1] "No answer"      "Don't know"     "Refused"        "$25000 or more"
#>  [5] "$20000 - 24999" "$15000 - 19999" "$10000 - 14999" "$8000 to 9999" 
#>  [9] "$7000 to 7999"  "$6000 to 6999"  "$5000 to 5999"  "$4000 to 4999" 
#> [13] "$3000 to 3999"  "$1000 to 2999"  "Lt $1000"       "Not applicable"

But what if your factor came in the wrong order? Let’s simulate that by reordering the levels of rincome randomly with fct_shuffle():

reshuffled_income <- gss_cat$rincome %>%
  fct_shuffle()

levels(reshuffled_income)
#>  [1] "Lt $1000"       "$10000 - 14999" "$3000 to 3999"  "$8000 to 9999" 
#>  [5] "Not applicable" "$1000 to 2999"  "$5000 to 5999"  "$4000 to 4999" 
#>  [9] "$20000 - 24999" "$7000 to 7999"  "$6000 to 6999"  "$25000 or more"
#> [13] "Refused"        "No answer"      "$15000 - 19999" "Don't know"

Now if we plotted it, it would show in this order, which is all over the place! How can we fix this and put it in the right order?

We can use the function fct_relevel() when we need to manually reorder our factor levels. In addition to the factor, you give it a character vector of level names, and specify where you want to move them. It defaults to moving them to the front, but you can move them after another level with the argument after. If you want to move it to the end, you set after equal to Inf.

For example, let’s say we wanted to move Lt $1000 and $1000 to 2999 to the front. We would write:

fct_relevel(reshuffled_income, c("Lt $1000", "$1000 to 2999")) %>%
  levels()
#>  [1] "Lt $1000"       "$1000 to 2999"  "$10000 - 14999" "$3000 to 3999" 
#>  [5] "$8000 to 9999"  "Not applicable" "$5000 to 5999"  "$4000 to 4999" 
#>  [9] "$20000 - 24999" "$7000 to 7999"  "$6000 to 6999"  "$25000 or more"
#> [13] "Refused"        "No answer"      "$15000 - 19999" "Don't know"

What if we want to move them to the second and third place?

fct_relevel(reshuffled_income, c("Lt $1000", "$1000 to 2999"), after = 1) %>%
  levels()
#>  [1] "$10000 - 14999" "Lt $1000"       "$1000 to 2999"  "$3000 to 3999" 
#>  [5] "$8000 to 9999"  "Not applicable" "$5000 to 5999"  "$4000 to 4999" 
#>  [9] "$20000 - 24999" "$7000 to 7999"  "$6000 to 6999"  "$25000 or more"
#> [13] "Refused"        "No answer"      "$15000 - 19999" "Don't know"
forcats/tests/0000755000176200001440000000000012752645041013063 5ustar liggesusersforcats/tests/testthat.R0000644000176200001440000000007212752645041015045 0ustar liggesuserslibrary(testthat) library(forcats) test_check("forcats") forcats/tests/testthat/0000755000176200001440000000000013432271102014710 5ustar liggesusersforcats/tests/testthat/test-utils.R0000644000176200001440000000042213432022227017150 0ustar liggesuserscontext("test-utils.R") test_that("check_factor() fails when needed", { expect_error(check_factor(NA), "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.R0000644000176200001440000000124013432022227017137 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("returns marginal table", { f <- factor(c("a", "a", "b")) out <- fct_count(f, prop = TRUE) expect_equal(out$n, c(2, 1)) expect_equal(out$p, c(2, 1) / 3) }) 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-relevel.R0000644000176200001440000000200313432022227017443 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")) }) test_that("can relevel with function ", { f1 <- fct_rev(factor(c("a", "b"))) f2a <- fct_relevel(f1, rev) f2b <- fct_relevel(f1, ~ rev(.)) expect_equal(levels(f2a), c("a", "b")) expect_equal(levels(f2b), c("a", "b")) }) test_that("function must return character vector", { f <- factor(c("a", "b")) expect_error(fct_relevel(f, ~ 1), "character vector") }) forcats/tests/testthat/test-fct_lump.R0000644000176200001440000001173513432022227017632 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", "d") 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", "c", rep(NA, 7))) o1 <- fct_lump(f, prop = 0.10) expect_equal(levels(o1), c("a", "Other")) o2 <- fct_lump(f, w = rep(1, 11), 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")) ) }) test_that("do not change the label when no lumping occurs", { f <- c("a", "a", "a", "a", "b", "b", "b", "c", "c", "d") expect_equal(levels(fct_lump(f, n = 3)), c("a", "b", "c", "d")) expect_equal(levels(fct_lump(f, prop = 0.1)), c("a", "b", "c", "d")) }) test_that("fct_lump_min works when not weighted", { f <- c("a", "a", "a", "b", "b", "c", "d", "e", "f", "g") expect_equal(levels(fct_lump_min(f, min = 3)), c("a", "Other")) expect_equal(levels(fct_lump_min(f, min = 2)), c("a", "b", "Other")) }) test_that("fct_lump_min works when weighted", { f <- c("a", "b", "c", "d", "e") w <- c( 0.2, 2, 6, 4, 1) expect_equal(levels(fct_lump_min(f, min = 6, w = w)), c("c", "Other")) expect_equal(levels(fct_lump_min(f, min = 1.5, w = w)), c("b", "c", "d", "Other")) }) # 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.R0000644000176200001440000000302513432022227017454 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 value", { fun1 <- function(x, y) c(1, 2) fun2 <- function(x, y) integer() expect_error(fct_reorder("a", 1, fun1), "single value per group") expect_error(fct_reorder("a", 1, fun2), "single value per group") expect_error(fct_reorder2("a", 1, 2, fun1), "single value per group") expect_error(fct_reorder2("a", 1, 2, fun2), "single value 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")) }) test_that("fct_inseq sorts in numeric order", { f <- factor(c("3", "1", "1", "2")) expect_equal(levels(fct_inseq(f)), c("1", "2", "3")) }) test_that("fct_inseq gives error for non-numeric levels", { f <- factor(c("c", "a", "a", "b")) expect_error(levels(fct_inseq(f)), "level must be coercible to numeric") }) 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.R0000644000176200001440000000223213413770514020263 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, ".")) ) }) test_that("string input is coerced to a factor", { expect_identical( fct_relabel(LETTERS[1:2], .fun=function(x) x), factor(LETTERS[1:2]) ) })forcats/tests/testthat/test-collapse.R0000644000176200001440000000167713432022227017627 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"))) }) test_that("can collapse un-named levels to Other", { f1 <- factor(letters[1:3]) f2 <- fct_collapse(f1, xy = c("a", "b"), group_other = TRUE) expect_equal(f2, factor(c("xy", "xy", "Other"), levels = c("xy", "Other"))) }) test_that("does not automatically collapse unnamed levels to Other", { f1 <- factor(letters[1:3]) f2 <- fct_collapse(f1, xy = c("a", "b")) expect_equal(f2, factor(c("xy", "xy", "c"), levels = c("xy", "c"))) }) 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-match.R0000644000176200001440000000052613432024645017117 0ustar liggesuserscontext("test-fct_match.R") test_that("equivalent to %in% when levels present", { f <- factor(c("a", "b", "c", NA)) expect_equal(fct_match(f, "a"), f %in% "a") expect_equal(fct_match(f, NA), f %in% NA) }) test_that("error when levels are missing", { f <- factor(c("a", "b", "c")) expect_error(fct_match(f, "d"), "not present") }) forcats/tests/testthat/test-fct_cross.R0000644000176200001440000000215613432022227020003 0ustar liggesuserscontext("fct_cross") test_that("gives correct levels", { fruit <- as_factor(c("apple", "kiwi", "apple", "apple")) colour <- as_factor(c("green", "green", "red", "green")) f2 <- fct_cross(fruit, colour) expect_setequal(levels(f2), c("apple:green", "kiwi:green", "apple:red")) }) test_that("keeps empty levels when requested", { fruit <- as_factor(c("apple", "kiwi", "apple", "apple")) colour <- as_factor(c("green", "green", "red", "green")) f2 <- fct_cross(fruit, colour, keep_empty = TRUE) expect_setequal(levels(f2), c("apple:green", "kiwi:green", "apple:red", "kiwi:red")) }) test_that("gives NA output on NA input", { fruit <- as_factor(c("apple", "kiwi", "apple", "apple")) colour <- as_factor(c("green", "green", "red", "green")) fruit[1] <- NA f2 <- fct_cross(fruit, colour) expect_true(is.na(f2[1])) }) test_that("gives NA output on NA input, when keeping empty levels", { fruit <- as_factor(c("apple", "kiwi", "apple", "apple")) colour <- as_factor(c("green", "green", "red", "green")) fruit[1] <- NA f2 <- fct_cross(fruit, colour, keep_empty = TRUE) expect_true(is.na(f2[1])) }) 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-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/NAMESPACE0000644000176200001440000000141413432024645013135 0ustar liggesusers# Generated by roxygen2: do not edit by hand S3method(as_factor,character) S3method(as_factor,factor) S3method(as_factor,numeric) export("%>%") export(as_factor) export(fct_anon) export(fct_c) export(fct_collapse) export(fct_count) export(fct_cross) export(fct_drop) export(fct_expand) export(fct_explicit_na) export(fct_infreq) export(fct_inorder) export(fct_inseq) export(fct_lump) export(fct_lump_min) export(fct_match) 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.md0000644000176200001440000000760713432266135013030 0ustar liggesusers# forcats 0.4.0 ## New features * `fct_collapse()` gains a `group_other` argument to allow you to group all un-named levels into `"Other"`. (#100, @AmeliaMN) * `fct_cross()` creates a new factor containing the combined levels from two or more input factors, similar to `base::interaction` (@tslumley, #136) * `fct_inseq()` reorders labels in numeric order, if possible (#145, @kbodwin). * `fct_lump_min()` preserves levels that appear at least `min` times (can also be used with the `w` weighted argument) (@robinsones, #142). * `fct_match()` performs validated matching, providing a safer alternative to `f %in% c("x", "y")` which silently returns `FALSE` if `"x"` or `"y"` are not levels of `f` (e.g. because of a typo) (#126, @jonocarroll). * `fct_relevel()` can now level factors using a function that is passed the current levels (#117). * `as_factor()` now has a numeric method. By default, orders factors in numeric order, unlike the other methods which default to order of appearance. (#145, @kbodwin) ## Minor bug fixes and improvements * `fct_count()` gains a parameter to also compute the proportion (@zhiiiyang, #146). * `fct_lump()` now does not change the label if no lumping occurs (@zhiiiyang, #130). * `fct_relabel()` now accepts character input. * `fct_reorder()` and `fct_reorder2()` no longer require that the summary function return a numeric vector of length 1; instead it can return any orderable vector of length 1 (#147). * `fct_reorder()`, `fct_reorder2()` and `as_factor()` now use the ellipsis package to warn if you pass in named components to `...` (#174). # 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/0000755000176200001440000000000013432024645012117 5ustar liggesusersforcats/R/relevel.R0000644000176200001440000000424113432022227013673 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 ... Either a function (or formula), or character levels. #' #' A function will be called with the current levels, and the return #' value (which must be a character vector) will be used to relevel the #' function. #' #' 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"), levels = c("b", "c", "d", "a")) #' fct_relevel(f) #' fct_relevel(f, "a") #' 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) #' #' # Revel with a function #' fct_relevel(f, sort) #' fct_relevel(f, sample) #' fct_relevel(f, rev) #' #' # 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) old_levels <- levels(f) if (rlang::dots_n(...) == 1L && (is.function(..1) || rlang::is_formula(..1))) { fun <- rlang::as_function(..1) first_levels <- fun(old_levels) if (!is.character(first_levels)) { stop("Re-leveling function must return character vector", call. = FALSE) } } else { first_levels <- rlang::chr(...) } 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.R0000644000176200001440000000730513432022227013703 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`, and return a single #' value. #' @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)) ellipsis::check_dots_used() summary <- tapply(.x, .f, .fun, ...) # This is a bit of a weak test, but should detect the most common case # where `.fun` returns multiple values. if (is.list(summary)) { stop("`fun` must return a single value 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)) ellipsis::check_dots_used() summary <- tapply(seq_along(.x), f, function(i) .fun(.x[i], .y[i], ...)) if (is.list(summary)) { stop("`fun` must return a single value 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, frequency, or numeric order. #' #' @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) #' #' f <- factor(sample(1:10)) #' fct_inseq(f) 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) } #' @export #' @rdname fct_inorder fct_inseq <- function(f, ordered = NA) { f <- check_factor(f) num_levels <- suppressWarnings(as.numeric(levels(f))) new_levels <- sort(num_levels) if (length(new_levels) == 0) { stop("At least one existing level must be coercible to numeric.", call. = FALSE) } refactor(f, new_levels, ordered = ordered) } forcats/R/utils.R0000644000176200001440000000127313432022227013377 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 or numeric 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.R0000644000176200001440000000152613413770514013214 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 #' @seealso [fct_expand()] to add additional levels to a factor. #' @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.R0000644000176200001440000000143213432022227013364 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. #' @param prop If `TRUE`, compute the fraction of marginal table. #' @return A tibble with columns `f`, `n` and `p`, if prop is `TRUE`. #' @export #' @examples #' f <- factor(sample(letters)[rpois(1000, 10)]) #' table(f) #' fct_count(f) #' fct_count(f, sort = TRUE) #' fct_count(f, sort = TRUE, prop = TRUE) fct_count <- function(f, sort = FALSE, prop = 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), ] } if (prop) { df$p <- prop.table(df$n) } df } forcats/R/relabel.R0000644000176200001440000000232213413770514013651 0ustar liggesusers#' Automatically relabel factor levels, collapse as necessary #' #' @param .f A factor (or character vector). #' @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, ...) { f <- check_factor(.f) .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.R0000644000176200001440000000004113432016717015270 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.R0000644000176200001440000000172713432022227014204 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) #' y <- c("1.1", "11", "2.2", "22") #' as_factor(y) #' as.factor(y) as_factor <- function(x, ...) { ellipsis::check_dots_used() 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) ) } #' @rdname as_factor #' @export as_factor.numeric <- function(x, ...) { factor(x) } 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.R0000644000176200001440000001157113432022227013216 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) } if (sum(rank > n) <= 1) { # No lumping needed return(f) } 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 { if (sum(prop_n <= prop) <= 1) { # No lumping needed return(f) } 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 } } #' @param min Preserves values that appear at least `min` number of times. #' #' @export #' @rdname fct_lump #' @examples #' x <- factor(letters[rpois(100, 5)]) #' fct_lump_min(x, min = 10) fct_lump_min <- function(f, min, w = NULL, other_level = "Other") { f <- check_factor(f) w <- check_weights(w, length(f)) 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) } new_levels <- ifelse(count >= min, 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.R0000644000176200001440000000372713432022227013506 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") #' #' # When passing a named vector to rename levels use !!! to splice #' x <- factor(c("apple", "bear", "banana", "dear")) #' levels <- c(fruit = "apple", fruit = "banana") #' fct_recode(x, !!!levels) 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/fct_cross.R0000644000176200001440000000240413432022227014221 0ustar liggesusers#' Combine levels from two or more factors to create a new factor #' #' Computes a factor whose levels are all the combinations of the levels of the input factors. #' #' @param .f A factor or character vector #' @param ... Additional factors or character vectors #' @param sep A character string to separate the levels #' @param keep_empty If TRUE, keep combinations with no observations as levels #' @return The new factor #' #' @export #' @examples #' fruit <- factor(c("apple", "kiwi", "apple", "apple")) #' colour <- factor(c("green", "green", "red", "green")) #' eaten <- c("yes", "no", "yes", "no") #' fct_cross(fruit, colour) #' fct_cross(fruit, colour, eaten) #' fct_cross(fruit, colour, keep_empty = TRUE) fct_cross <- function(.f, ..., sep = ":", keep_empty = FALSE) { .f <- check_factor(.f) flist <- rlang::list2(...) if (length(flist) == 0) { return(.f) } .data <- lapply(tibble::tibble(.f, !!!flist), check_factor) newf <- rlang::invoke(paste, .data, sep = sep) if (keep_empty) { all_levels <- lapply(.data, levels) factor(newf, levels = rlang::invoke(paste, rlang::invoke(expand.grid, all_levels), sep = sep )) } else { anyNA <- Reduce("|", lapply(.data, is.na), FALSE) newf[anyNA] <- NA as.factor(newf) } } 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.R0000644000176200001440000000103313413770514013520 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 #' @seealso [fct_drop()] to drop unused factor levels. #' @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.R0000644000176200001440000000203713432022227014040 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. #' @param group_other Replace all levels not named in `...` with "Other"? #' @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, ..., group_other = FALSE) { new <- rlang::dots_list(...) levs <- as.list(unlist(new, use.names = FALSE)) if (group_other){ f <- check_factor(.f) levels <- levels(f) new[["Other"]] <- levels[!levels %in% levs] levs <- levels } 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/R/match.R0000644000176200001440000000210313432024645013332 0ustar liggesusers#' Test for presence of levels in a factor #' #' Do any of `lvls` occur in `f`? Compared to [%in%], this function validates #' `lvls` to ensure that they're actually present in `f`. In other words, #' `x %in% "not present"` will return `FALSE`, but `fct_match(x, "not present")` #' will throw an error. #' #' @rdname fct_match #' @param f A factor (or character vector). #' @param lvls A character vector specifying levels to look for. #' @details #' @return A logical vector #' @export #' @examples #' table(fct_match(gss_cat$marital, c("Married", "Divorced"))) #' #' # Compare to %in%, misspelled levels throw an error #' table(gss_cat$marital %in% c("Maried", "Davorced")) #' \dontrun{ #' table(fct_match(gss_cat$marital, c("Maried", "Davorced"))) #' } #' fct_match <- function(f, lvls) { f <- check_factor(f) bad_lvls <- setdiff(lvls, levels(f)) bad_lvls <- bad_lvls[!is.na(bad_lvls)] if (length(bad_lvls) > 0) { stop( "Levels not present in factor: ", paste0(encodeString(bad_lvls, quote = '"'), collapse = ", "), call. = FALSE ) } f %in% lvls } forcats/vignettes/0000755000176200001440000000000013432266206013727 5ustar liggesusersforcats/vignettes/forcats.Rmd0000644000176200001440000001214413432022227016027 0ustar liggesusers--- title: "Introduction to forcats" author: "Emily Robinson" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Introduction to forcats} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) ``` The goal of the __forcats__ package is to provide a suite of useful tools that solve common problems with factors. Factors are useful when you have categorical data, variables that have a fixed and known set of values, and when you want to display character vectors in non-alphabetical order. If you want to learn more, the best place to start is the [chapter on factors](http://r4ds.had.co.nz/factors.html) in R for Data Science. ## Ordering by frequency ```{r message = FALSE} library(dplyr) library(ggplot2) library(forcats) ``` Let's try answering the question, "what are the most common hair colors of star wars characters?" Let's start off by making a bar plot: ```{r initial-plot} ggplot(starwars, aes(x = hair_color)) + geom_bar() + coord_flip() ``` That's okay, but it would be more helpful the graph was ordered by count. This is a case of an **unordered** categorical variable where we want it ordered by its frequency. To do so, we can use the function `fct_infreq()`: ```{r fct-infreq-hair} ggplot(starwars, aes(x = fct_infreq(hair_color))) + geom_bar() + coord_flip() ``` Note that `fct_infreq()` it automatically puts NA at the top, even though that doesn't have the smallest number of entries. ## Combining levels Let's take a look at skin color now: ```{r} starwars %>% count(skin_color, sort = TRUE) ``` We see that there's 31 different skin colors - if we want to make a plot this would be way too many to display! Let's reduce it to only be the top 5. We can use `fct_lump()` to "lump" all the infrequent colors into one factor, "other." The argument `n` is the number of levels we want to keep. ```{r} starwars %>% mutate(skin_color = fct_lump(skin_color, n = 5)) %>% count(skin_color, sort = TRUE) ``` We could also have used `prop` instead, which keeps all the levels that appear at least `prop` of the time. For example, let's keep skin colors that at least 10% of the characters have: ```{r} starwars %>% mutate(skin_color = fct_lump(skin_color, prop = .1)) %>% count(skin_color, sort = TRUE) ``` Only light and fair remain; everything else is other. If you wanted to call it something than "other", you can change it with the argument `other_level`: ```{r} starwars %>% mutate(skin_color = fct_lump(skin_color, prop = .1, other_level = "extra")) %>% count(skin_color, sort = TRUE) ``` What if we wanted to see if the average mass differed by eye color? We'll only look at the 6 most popular eye colors and remove `NA`s. ```{r fct-lump-mean} avg_mass_eye_color <- starwars %>% mutate(eye_color = fct_lump(eye_color, n = 6)) %>% group_by(eye_color) %>% summarise(mean_mass = mean(mass, na.rm = TRUE)) avg_mass_eye_color ``` ## Ordering by another variable It looks like people (or at least one person) with orange eyes are definitely heavier! If we wanted to make a graph, it would be nice if it was ordered by `mean_mass`. We can do this with `fct_reorder()`, which reorders one variable by another. ```{r fct-reorder} avg_mass_eye_color %>% mutate(eye_color = fct_reorder(eye_color, mean_mass)) %>% ggplot(aes(x = eye_color, y = mean_mass)) + geom_col() ``` ## Manually reordering Let's switch to using another dataset, `gss_cat`, the general social survey. What is the income distribution among the respondents? ```{r} gss_cat %>% count(rincome) ``` Notice that the income levels are in the correct order - they start with the non-answers and then go from highest to lowest. This is the same order you'd see if you plotted it as a bar chart. This is not a coincidence. When you're working with ordinal data, where there is an order, you can have an ordered factor. You can examine them with the base function `levels()`, which prints them in order: ```{r} levels(gss_cat$rincome) ``` But what if your factor came in the wrong order? Let's simulate that by reordering the levels of `rincome` randomly with `fct_shuffle()`: ```{r} reshuffled_income <- gss_cat$rincome %>% fct_shuffle() levels(reshuffled_income) ``` Now if we plotted it, it would show in this order, which is all over the place! How can we fix this and put it in the right order? We can use the function `fct_relevel()` when we need to manually reorder our factor levels. In addition to the factor, you give it a character vector of level names, and specify where you want to move them. It defaults to moving them to the front, but you can move them after another level with the argument `after`. If you want to move it to the end, you set `after` equal to `Inf`. For example, let's say we wanted to move `Lt $1000` and `$1000 to 2999` to the front. We would write: ```{r} fct_relevel(reshuffled_income, c("Lt $1000", "$1000 to 2999")) %>% levels() ``` What if we want to move them to the second and third place? ```{r} fct_relevel(reshuffled_income, c("Lt $1000", "$1000 to 2999"), after = 1) %>% levels() ``` forcats/README.md0000644000176200001440000000773413432022227013202 0ustar liggesusers forcats ===================================================================== [![CRAN status](https://www.r-pkg.org/badges/version/forcats)](https://cran.r-project.org/package=forcats) [![Travis build status](https://travis-ci.org/tidyverse/forcats.svg?branch=master)](https://travis-ci.org/tidyverse/forcats) [![Codecov test coverage](https://codecov.io/gh/tidyverse/forcats/branch/master/graph/badge.svg)](https://codecov.io/gh/tidyverse/forcats?branch=master) Overview -------- R uses **factors** to handle categorical variables, variables that have a fixed and known set of possible values. Factors are also helpful for reordering character vectors to improve display. The goal of the **forcats** package is to provide a suite of tools that solve common problems with factors, including changing the order of levels or the values. Some examples include: - `fct_reorder()`: Reordering a factor by another variable. - `fct_infreq()`: Reordering a factor by the frequency of values. - `fct_relevel()`: Changing the order of a factor by hand. - `fct_lump()`: Collapsing the least/most frequent values of a factor into "other". You can learn more about each of these in `vignette("forcats")`. If you're new to factors, the best place to start is the [chapter on factors](http://r4ds.had.co.nz/factors.html) in R for Data Science. Installation ------------ # 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 part of the core tidyverse, so you can load it with `library(tidyverse)` or `library(forcats)`. ``` r library(forcats) library(dplyr) library(ggplot2) ``` ``` r starwars %>% filter(!is.na(species)) %>% count(species, sort = TRUE) #> # A tibble: 37 x 2 #> species n #> #> 1 Human 35 #> 2 Droid 5 #> 3 Gungan 3 #> 4 Kaminoan 2 #> 5 Mirialan 2 #> 6 Twi'lek 2 #> 7 Wookiee 2 #> 8 Zabrak 2 #> 9 Aleena 1 #> 10 Besalisk 1 #> # … with 27 more rows ``` ``` r starwars %>% filter(!is.na(species)) %>% mutate(species = fct_lump(species, n = 3)) %>% count(species) #> # A tibble: 4 x 2 #> species n #> #> 1 Droid 5 #> 2 Gungan 3 #> 3 Human 35 #> 4 Other 39 ``` ``` r ggplot(starwars, aes(x = eye_color)) + geom_bar() + coord_flip() ``` ![](man/figures/README-unordered-plot-1.png) ``` r starwars %>% mutate(eye_color = fct_infreq(eye_color)) %>% ggplot(aes(x = eye_color)) + geom_bar() + coord_flip() ``` ![](man/figures/README-ordered-plot-1.png) More resources -------------- For a history of factors, I recommend [*stringsAsFactors: An unauthorized biography*](http://simplystatistics.org/2015/07/24/stringsasfactors-an-unauthorized-biography/) by Roger Peng and [*stringsAsFactors = <sigh>*](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. Getting help ------------ If you encounter a clear bug, please file a minimal reproducible example on [github](https://github.com/tidyverse/forcats/issues). For questions and other discussion, please use [community.rstudio.com](https://community.rstudio.com/). Code of Conduct --------------- Please note that the 'forcats' project is released with a [Contributor Code of Conduct](.github/CODE_OF_CONDUCT.md). By contributing to this project, you agree to abide by its terms. forcats/MD50000644000176200001440000001103013432271102012211 0ustar liggesusersbb1dfedf714761f4407903297271c289 *DESCRIPTION d5f6ca573834110aff26e8713779a1c8 *NAMESPACE 87f7d199a4c2b313fd6570a20a99fe39 *NEWS.md 6fcf996d59a9dbf6ee3ffa63a42399da *R/anon.R 95d924a7544fc262fa1824dabf23f9bb *R/as_factor.R bd533a096f73a7ea37ab20ab77103866 *R/c.R de304ed76e5e80be5fbafd0ed39679fc *R/collapse.R 965c6d1b298f0637e9bf74c36e142492 *R/count.R 9b8c9f934b7a5c9193cc8f197bbe9b2e *R/data.R 83518de9a1dfb35452653ef137eed507 *R/drop.R dab168976912525c303a74f0e8f3f922 *R/expand.R 97fe369834ad78ad7bbf2735c8d05a24 *R/explicit_na.R c7adc7a2d5f63d731f42dac098bc3e89 *R/fct_cross.R b4fe12876c37f8a22cde06e9701eecf0 *R/forcats-package.R 6d2ad336445f71e0d91765ee7677ad1d *R/lump.R cd0818ab06b278ddc2a38b5a3eaab4d9 *R/lvls.R 369d91ffd9355c01688efffaa3f37c6d *R/match.R b1e7b497cdbc10912b5b10d0990a0922 *R/other.R d302ac409149ee978698d90d3ba09b61 *R/recode.R f0171a28a2f28ec2c6f070f495d2e66f *R/relabel.R 6df20d5949dfbd517039bb17e48443df *R/relevel.R 225cb500c141712d5e0bea8022b76ce7 *R/reorder.R 2513b5d4ddb3af53f57f9ef368200112 *R/rev.R 6a741a6fb62aa246f865f06dd172de1c *R/shift.R 9aebfd5ecc427de639e076a022cb0a53 *R/shuffle.R ee5201d1d40e6b81689639f92ae9fa2d *R/unique.R 7f77f9a81739e08008f5efd356ecd655 *R/utils.R c64a489a6e0fbfd1fd528b6723192f4b *README.md 41d9530244f3959018e95f6601eea721 *build/vignette.rds a6984b4f6c2e70deebeca86c7b3d76ea *data/gss_cat.rda f9f507819092a0e98254af7616c785a1 *inst/doc/forcats.R ead0f2b9d582e9cb3cd6d06847688c5f *inst/doc/forcats.Rmd b670a96f4dfda1fce7b535a85f47e463 *inst/doc/forcats.html 557543f361e2e571ea7c1a353a3b1356 *man/as_factor.Rd ae74738c8d74947e1d021899c62e89cc *man/fct_anon.Rd 80cdf4a28ef28084e8ec111b152d4ffb *man/fct_c.Rd 734c140ae2f33b6c9f1882b7444c2a1e *man/fct_collapse.Rd f060da2e6dff2914fb1bc54504ca4a67 *man/fct_count.Rd e1e5d7b389f46446ae3438c3fdde95f3 *man/fct_cross.Rd c42f9c956059fefbefe126474e29a233 *man/fct_drop.Rd 0a40a6cf33b7d3b10c10ec0ec75a8ac1 *man/fct_expand.Rd 2e44ae3588cff7f8dadb95641c78cd5b *man/fct_explicit_na.Rd 823833c3b1fab7d1fb6268b1daaa8045 *man/fct_inorder.Rd 6ac48373205b2a6acd02112a9a137cea *man/fct_lump.Rd 4ef733cedba6eda64440603d8ee6d8c9 *man/fct_match.Rd 7c8ed498e688709605b46ca0d6cd0553 *man/fct_other.Rd bee36c4bd2f72aaec83299e3130d9b1b *man/fct_recode.Rd a8e656d7bb297da6570fc4e71d0ed371 *man/fct_relabel.Rd b2959ffbd127440ad38412ab4acaa12a *man/fct_relevel.Rd fd8078b559b76f32663aff3377b2c8ec *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 1e64288740b04988f0f7b312121328fa *man/figures/README-ordered-plot-1.png a59cd623b54459510a0897b3350a65d9 *man/figures/README-unordered-plot-1.png 3252fda93a16a69b6deb795c4866b7cb *man/figures/logo.png b28d6b67ae4113a432e0590f7ae64a09 *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 ae0ca28f0eccc8a8c60aba83f71e6aff *tests/testthat/test-collapse.R bd84b13a113067bcdd3908ff588dac6e *tests/testthat/test-count.R 94ced03ac637bcd6e4da7ed74a6db9cc *tests/testthat/test-explicit_na.R abc6b12c9ac566a532b368df371303cb *tests/testthat/test-fct_c.R b5821b09822718a6ad2c3fd6bd3de5da *tests/testthat/test-fct_cross.R 2da1b3ace9cf79139782fb3cb5fcf737 *tests/testthat/test-fct_drop.R 2c5d336fd53f55840db8417dc6a5fd79 *tests/testthat/test-fct_lump.R d2ce880df1564300a215fb5bd839d19e *tests/testthat/test-fct_other.R 73c6685513fd25b80919c7211a0bee93 *tests/testthat/test-fct_recode.R 6e116836c37935c9daf6fc4ca778c93e *tests/testthat/test-fct_relabel.R 8bf75dec2477f0bcb482f57cdbcb1c71 *tests/testthat/test-lvls.R e8e369f72b8bd87b6c53c3a881e79e04 *tests/testthat/test-lvls_reorder.R 52c2da070828a4ba816de925327a66ec *tests/testthat/test-match.R 7d92bdc6e200eb78789528d9c695e93e *tests/testthat/test-relevel.R a0b5bccd7d73dfacb937d62cd42945cd *tests/testthat/test-reorder.R 371dc92dbf14f009077b997f00b297cb *tests/testthat/test-rev.R a0df68c919a132b10db11d2d2a37fa9c *tests/testthat/test-shift.R 9804486a2ed35c047035d010ea9b99cc *tests/testthat/test-shuffle.R ace13f92d674afbc6a66b69ab55e2db8 *tests/testthat/test-utils.R ead0f2b9d582e9cb3cd6d06847688c5f *vignettes/forcats.Rmd forcats/build/0000755000176200001440000000000013432266204013014 5ustar liggesusersforcats/build/vignette.rds0000644000176200001440000000032313432266204015351 0ustar liggesusersb```b`feb`b2 1# 'N/JN,) MA+)O)M.S(W*ES3!$7Mn:%`  `aBRȚn2KjAj^ HvѴpxVaaqIY0AAn0Ez0?½Ht&${+%$Q/n,forcats/DESCRIPTION0000644000176200001440000000225213432271102013415 0ustar liggesusersPackage: forcats Title: Tools for Working with Categorical Variables (Factors) Version: 0.4.0 Authors@R: c(person(given = "Hadley", family = "Wickham", role = c("aut", "cre"), email = "hadley@rstudio.com"), person(given = "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: ellipsis, magrittr, rlang, tibble Suggests: covr, ggplot2, testthat, readr, knitr, rmarkdown, dplyr Encoding: UTF-8 LazyData: true RoxygenNote: 6.1.1 VignetteBuilder: knitr NeedsCompilation: no Packaged: 2019-02-17 14:15:34 UTC; hadley Author: Hadley Wickham [aut, cre], RStudio [cph, fnd] Maintainer: Hadley Wickham Repository: CRAN Date/Publication: 2019-02-17 14:40:02 UTC forcats/man/0000755000176200001440000000000013432266205012471 5ustar liggesusersforcats/man/figures/0000755000176200001440000000000013432022227014127 5ustar liggesusersforcats/man/figures/README-ordered-plot-1.png0000644000176200001440000006647013432022227020343 0ustar liggesusersPNG  IHDRz4iCCPkCGColorSpaceGenericRGB8U]hU>sg#$Sl4t? % V46nI6"dΘ83OEP|1Ŀ (>/ % (>P苦;3ie|{g蹪X-2s=+WQ+]L6O w[C{_F qb Uvz?Zb1@/zcs>~if,ӈUSjF 1_Mjbuݠpamhmçϙ>a\+5%QKFkm}ۖ?ޚD\!~6,-7SثŜvķ5Z;[rmS5{yDyH}r9|-ăFAJjI.[/]mK 7KRDrYQO-Q||6 (0 MXd(@h2_f<:”_δ*d>e\c?~,7?& ك^2Iq2"y@g|U\ @IDATx xTE7H!a "(*,+EQTGT2zqኊEQd˾N@񖞞@Nӧ_}:U]U眨SIH  HLa@@0@@B*@Rn  @{@@ !`  @@B*P6G`A ۷/NweJtt;vt~111ɲNG==Or-I ^L:%QQQkmzmg}W/_|xMv+V̷/ @m6 Mo̰`vX\\KBRCrp8:{VI<:d/oIIIeiYP&''ngn X&@jYS]@@l   eꦦ:O]{?~ky1 xWP%G@<)@f  w@v@'B#  nQr@@l6  xWԻmG@@O 's)toV>lE[ `!  hPَ;/t3gĉһwBa!  ,ܿ䘵r!EM6ѣG}˞}YR~;w :wƍR   p+?/m۶ɠA$--Mw.F-ZɓҶm[aGyDʕ+'k֬W^yE7o.}7xl+Æ #Fȯ*C 'Vwҥ^*\pҕǘW͟i|||EguTT-[V©Lnc8lS4::ڪv8[m\E*T0hпUbccwkY̫ŋKeɒ%&塇2_]jԨ!ziӦyhpkfM0A{9iٲ ^5ԩ8o2 l׿:}']vﵗ$$$]m)6+Vt5򷱝mv^OG X?x֭+cuVYpKC]tXBj׮mOݭaÆlٲ"u^O>]f̘aӀS5ks3ük.7QޒUbbS;3)))PlC{J%==7ml'TǶZjw^ia$Y{SRRt>i~^lon ԯUtzj2d{2k,+}= $y]أ~it .] mY  IH~觟~*7cӦMwޑvm3K/&M(}_5Ç'O΄  @ 5z-Og9 kM|Cz"џg3{cw-O<Ü-_d@@"\ YJ6Թ˗Qjh0)s@,.9n¥r6g̙Wp.XDmݳgs@#՘!=EɜrS 6<ò;  aD@,jOj h7D@"K4ړ  a/@MD@@ 6  @ p+ΰo"w 8uTshwr'W@@hz@a   .%  @ mkRSS]_8݊r@ZР@@4@KC<@@ @@JC4@@ hР@@4@KC<@@ @@JCtѢE}˗/fϞ=2wY  X?UVdٺu|@@ 'NÇ~_mMDO<=z4 322-ʒcǎ?~Zmܸєӷ'  ʕ+eԨQ&,[|G2f6mԩSGv-#Gzɾ}_~ {rf͒)SHttTRE^}޹64mդ촹YUtw#Z˵wq&8ԞoV>S`~_ȣ>*omV~acڭ[J_'N4W_Ծ&L{NZl ;udHj w՗W߾}e^~RZ+~ ®Ln(ہ:x-NJJvTYG@yAԡv%߿y4hHLL/8o/֭[| @u~ٲe2}t1cb ߱V*&MF'8ޗ('k|VMVXS!DG8sfKґc#<6v6,RﶵmzYc S+B3Cfe͚5I&'}fȻyg뗴/ K'Vz2o\U!!  DD{U\Yz!={u뚉6<wazI6lU^L0O`s=&pꪫD[tooQx իho+?fWf\-O@@zSy:Shɟt~X||9Y;rg.y*iwWT9EM.~nI_?< u.Ϋ%)<37[Rll$''KZZUC𶵳NҿO:zْ|6mkgR+"Km廉q=NEZX [ERQh]| D@pW!xw}6TNt@4h*6D@( P$@@@bC@@ - E@@Z4h*6D@( P$@@@bC@@ =+VȺu搑!s +@@@ϠW\Ylcyw( DwB =8 *U۷Krrřn&2uDIKK3SRR RlYPBY Dh-|=H%''G6o,wur-??&0ݻ6\r @5رj(Vo]sξw}<þnh@tΤ$iذ^+x֦Mf͚+G5u/(wyg?+V4Nf-ZÇ;/]y,W+z?^%>vX"j]LL/_Si^͍DGGiAYYY{Ǎccs2e$>>^􏺎ْlkg[q:q℧Y@4N @?SBBoj| U#^Au3:tK6 2UMuV& msll @Mm8hvvi|#xsYhh?CZ%΂Nojڸqyƍ~C&}'Çe-  X4oeeСr:]v5'N@@6l3޵k^ׯo?\̞=ۼnҤ9H_~oY  %h,Al X!|͢{  ^Qb@@n>  xO{mF@@O z(<  =P%F@<-@  @f@#  ͖-[&6l0[O>]9l  /@̙3eѢEfѣGKfffY  P@HЭ[JVV=,kZxT^,z~z;ѣAqEVz?^ZgNe TX紳MuvlSW=݆:g۾Ǵmmjg g: I=z9FZSf͚`ܹW_55[r_f͚e 6<ٳcǎRF |ꊺuҥK6E(7x|7ҨQ#=_X^ZgyƬ޵:}gM/N9XpC{qw)]t/; 0a>mL :I{w%iol'+NCRR-)66VhzlkgSZ5SlI)))f@^N($  *:S{uhkӦM}4|+U[ @']vkժe?UV/UYM `:dyL}W`;^F@lIH::䜵kʯZ YFj֬)M4AMvWPu&MUVP; Kzs9GƌczCu@/,-K{dl4թ78;&-,/! o6]weuea'=z={t6չ4؛3g =kkԩY d~Y{>7@T^vefW=)jׅ2@@S޿_{х%Q 6WQ: ^[jt>SO=UaL丹4t6 t|gG۩gzB1Ty>D<SЍ m314Dopg^}Y(JHiٙ#aO/*T=]w_^43ыJA+,D`^3n*VOJ_`S *ka۲ @] $M\H=;]P >< KuDu^IB@@HP^IKy$@@ ,W#" h B@"T4Bj! *@-C@@IHjM:U=[~  ԻmG@@O z(4  ]vgT3?Vm@@ 4ƙ  !@[@@ !`  @@B*@Rn  @{@@ !`  .-[&6l(snnL2E *@BϜ9S-ZT 眜yW @ Ȱ@l n*YYYr9volټy8q·,Ǐ˖-[<@V4}_~ w*UƲK.2zh;wT\٬ ~#Fȹ+'O̳N_>|X &Mm} \xB+,-)S-[V©LnS+W¦:kjg}_kPU?rmkgT|y w9Y϶v2ⱱYnOZ o)۷|ݺu3{h`9k,ɓO>~ڗK2j( eڴib z}ry|+İ+~mKnuT۬a\bŰk dc;GBǁJtNӀ[o5[KVs]ަM|ꂫZz- 0~M4iܸYOjՒիW믟;w^D{sCܮGI꠿233K/0vhRRdddPaq INN4y$Y{U&{eK3%%|=zͬMiӼ::t__:Sw0;4_ZN石G@@ R@iY~סsJ^vf?O`_O0Y^=yx7落sXV# +|1M{7˪U䮻2:C!UV5'#~$3lذ&w4U>䓾\O? x'  ż뮻N֯_o.Ҽys^:3Kb|x  h׮ԯ__.]jP >F/  @8Ϊu#! g!9  @Xl  pgnH  % -" '!'s:u{@-@ۏ#  \Q`@@ {No;?>M@,ԢƦ  @8C+P@@"P"  @@@@@-jl h8e@@, *  %h۷ˢEJHFF̙3D1  %hݕ+W_|Q=Dv!nac@@ Ro>)#GL(UV5O8!ǎ}-lٲRBX  @ZL+1 ʼns)SȄ A=۷AF@sȐ!#|2n8y}7om$Ѿnۥ=Llkgskzbw GB;;u)FZ̩?,[L>#gڳsA5ЬUܹSz! 07n('O*UȪU̲Yf]VYKN|+ի]Gm)6Ώcm)9999 $eud)+++`@hf˖-%&&lպukxjTSO4\nn6iPd<_|QtvDa[;;Stz׿NJ58 >Yf`48gϞm޽{#.],?yd鯙ƍuVz-  `=_Ю]J޽E#s=l]n]С (u~f.m&&3gĉ-+@@H:uBMkEjmO^ u>\ú=sjw^bx{%޹wv7٥ufsot"p+I lI,iiiV :ٳǪ!xYSRRwNrr=E-׹@k ۞e  "]  RАrs0@@P  ! )7C@ =  RАrs0@@.d{`ԩni6 Mz@Ϧ>F@, ѩ2  p6?gة=nze9 -@hTl  PH  A Mņ  !@Z  hTl  PH  A Mņ  !@Z  @hNNNЙ}~(0ӧO#G  g_ /)S*m/,GBױ@@ j $zAi&ĉrAbþ׹}vIKK-+IFF?ޱco7iϞ=eZlk}_.  u/ *Ȉ#䩧2A[Æ E9jժr:/CAw-ɲuVyWߖ1cƘ̙3Gf͚%Ç7Ly!9򨨨ee/+WfԨQһwoիo&&L ʕ+}2h ;v$&&o4i1yZ[nw^zI߾}}xRX=8Nz/_ڎN;[;XLj6%[9))ɦf[YJ*y=AСCE{W [oU&O\` k'|"o[A 5@e_clԶm[9ryeVZsNѣh۩S'y}3dذaN'ݺu֩na-Wxn>q%)c111$/mun&#/p+'::thudǖd[;k /;vnlkgX[^NōpuQ_n:i4]uU&,fSiO&'!ٳgˮ]D{45h[6.ӟ$_~>5YfGT_hj n:c3:_ {?!!A|Ik}INS bSncMuVS>:"#+~ EW?YYYyulöv8APin E׮]+5jԐ͛KǎM nFr"ԞGeN{77UVҴiSg u(_5鯮*UFi&L |WwܑgX]{A[So? #  .[L:s2Υ^*w6=u7p|![yfC٤I9st!Oi =kQ5Ο?߷ꫯ mfzK?ټMlXvmpYkzQ-tz_k:̮ 50#  `@P:s-ԩc3Q>>!W9qHWOBOz2ko:\F5iݻw7'5\㿻y={{LxNEȟ֭k`ծs=^pD)=I9=5  `@P" &=Cu_T{`=;I_}T^x3LʵgI$CzY&]^< 6?|?ivՓ9sAu>kz[uaaM7G@@ZGetnhAl%!  LzBΟN-2rۻw5s9^K|ziW_}w|Ig[@@ JEݻv*zxj%?Ν;]FSA3O7՟ݝ@@: /YĜq^Q=GIB@@ XާLφwҼy-J:4#  ]P/ފt6nY\X  П9[-I  #0 pg0cN*Eo@@%1Ve9  w@V!ϒg¨TǏP@"G ;6lX#G  *TηtU@@J] [q6" HP:8̭8SRR$99Y:u$-[[qA@(]OBV On  A kz=3ߦVD  @C;w>}{gr?|{ˉ'?"[" X-tOo&mڴ1`*TooȔ)SF   5q1cXBjժerK3S<(&MnݺԳeFF]:tpK@@{lپ}{Lٷo_`ǎk(  A111rWe֭>ŋ97poY(IPǎRjoGt+*i#GD}qӦMkպ14i@:)YoV['@@Hj^װsR^=T ֎=*wq۶m{JӦM} /`Bڿ_qf͚%ǏQFIjr-~(A۷,\PJy饗_͛VO ƫVjڵki׿L>͓vUX9?'O-[՞S'p-,'αK9ۈvpigףNN`wI촹Wۮ$嶭HT͛\rҬY3D.Pu~жm[s9&?޽[4ݻ^+qqqf'OmO'ͤI )/'}iQ6HJJY%@lSϘm#WYӺt -ɶv8K ,^mkn (?ֹ?rK]o|gqF.:I ꗺ;j/.ZH.2Ou_{TT9<" 6 x: 4i/ &ioAƍÇz‘:U{v5i5j$\pT[li.嗛b'@@-P!nFsO^D/`]v3gĉAjNXnԝ ٰapg-\̏  QΚ,&1T><S9ݻwwIj^NPOfdۜ1g^PKiǶvvٳ9f 9oDPq.*yzީT(O=VԋG@@ ""ĆN  @ FjR/@@ LJt^/4gzzs뮻\K3LJ@@@ tժUgڵLt; 2\WYF R  a*^3Snk吏NB@@ P%G ]c=&ӦM Xl  5ӞÇ [boh,[S-`),::Z%33s&;@(@P=ʕ='0=׃hIp %=.# X*Tڌ;V֕Z(ر.>|T@@A+Vܹseբ͚53JzP?ga^ߊ3y) A\po^3uN @@ 5T3O={:uȠADO@"!  Pvɸq̅_u _verѣKr`E@S PG=8yꩧv2p@sb-  (Q~zyaÆҦM䣏> 3g|f}@@G 蓐j5k\xҷo_뮻f͚N>f8^/Ӵ|r2   _ E/W\?kh\\5O@@/k&^zr{رC/^,999<֭+UT]nE>}9rp@@ \ճoFs;w!C?3QF1r}linW h޼\$@@F{@[tўNM)SF>È;tl޼9OϮVN{-7l {533Ӝ'a9\پ}   HP=YYYpByy}x gg6zI)Sd„ ҠAYr#^ȑo>SSir рΓÇKTTYN6ͷQF߷-TQ{cbb Qwޥͦ:;˛ﭒzyu{ٹ`ll8mն+Imkg'N۝;KNW"}kOÇ M"!i7ݻ,[.ZHF%jՒ;wJ=L9tPSC=$?IHH/ k.L-+ TIg_rgPHGI(lsbbbI"b[Yؖllx7vJA]wu_eӌ'Md6 "!5kLNk~:'O6'*ihvv/Ǐ3<#_t04 6<ٳT/ew亙l;OtT}x%ndĔt?nC:]8SZ۶vֿ ժU3-ɶv=]ָѣnfn teP;vu>[je2 CwE/EBR,'iױW]uw!rL륩.Pz]TNM6-**4\  X+t'zj^Q1vmG̼3fк:T'hΙ>:޾}{Wf  `e Nu@@-@z[#  ZT@8g8>  `aN:UӝAd}mIkDOz@ó](  ۴T @Oó]\/UjjxE`^)*D"BЈhF* xG;mEI@@ f  w@V@ЈhF* xG;mEI@@ f  w@V@ЈhF* xG;mEI@@.ݺu>|xYYYrqٱc8q,?yl۶Ml[+8`֧˟4oȑ#r1j}q<   `5e̘1RreYv<ҵkW;vl޼,o!CHe޽&m*U$s\r%&cǎcɾ}_~ w*UkK.d:t4h@֬Ycswv={4-pI2pA,#IZjNTT)~ؔ{vmlJSx9wV+P|饗_͛Ν;%77W 妛n2t; "5T~}ydΝb7ߔۛV{Wuf&L =lvI?*TkƷ/GvIrȖ<۟97aEG^lI˗w2,5+[ ZY1+V(yF`]Ev)ާVéAWf sJJԭ[W/^l^7mj_ Gmڴ1ԬY|+VȭjKV YlL>]f̘a>>-S#zDqhu͟   =F魌RSSU`JE L>u@Qplʄ Dh7.UC@Q4[2! ,@K@@p VL  @ FpR5@@ @ñU(  ܸT @GPVo$++oO#s-<2gΜ`6e@@ Pf~뭷d~K~uV ,f;w fSA@ -5\|f7jQ=>7e *@g̘az֭[g Bun0?W6usҘ1c3&''KƍÇ Td @@5͛;LynfN oѢanݺf͚RF ߿w2ڵ̜9S&Nw "uj2=M٪:|g5_'Yzissv)s@w~c?3ӧKZZs@ì]J8P1 s@KS6rH#E%z@ )$}|jVzVgf"@@PB@@@ݒ%_@@B@ ea!  [nɒ/  @@@-Pd@@P.T(K/:uG~EattǛ Ri"ʆm.~>Pz@y  T4 @@!xK֜j#?tvc@Pz@ ea!  [nɒ/  @@@-Pd@@PBYX  [  Ph,,D@pK4He˖Ɇ ӧO#G'!  kx>sLYhbVS< @@ X;vL>kkM6ɉ'lSԋ IKK=42;;[:@N[qXBF)'N4 e8p|o˴iӤN:{n]z }cٳG. 24h #F/Rm& 2ieԨQҢE &&&\ԥ D7o.ǏիWKƍeƌrכ oO?TC__|!>h~:_W[˒%Km۶2`ŋzf?󩽩Nze]foٲ̟?LY D@ԩn߯=-z:TOrq:h, s;ufiDLZ/=3+0~`7 vzRiK9ժUԯHmt>466V|Zơ7O^y8A6ԝKm@LTvy!xv' @@ tV{7N#! = '@@ ! @@hH9  '!SNtk񒙙iMue Զ:KKKpkʃ*@h,,D@pK-YE@(T!BY"ajjjW" Pv[R^Ȳ4d@@@@y  T4 @@  @H@C@@@y  T4 @@eڳg̝;r   #},XV[n>r   [!۷o%ǎ-:|?~ZmܸQt9 @][q5kL2EJ*ꫯߖZjn6L:v(^{,YD* 45kH~6999o>_~*T2e];O@@ x7F;_[$ Vĉ'7ã>*_}A)2aye˖&SNveU'}<" @ ^ʕ+~ Áh ?ֵmVʖuֲrʠP_lL>]f̘ar;xXB.b:99YF+~n&e%! @S|:tHK^0CWd@ npYNɓ'}ˎ9{kΝ}l.]vھ˗nZܹ3~SY V=zԵz:nǵ eSw'<'̛7O/XҾ}ʓu  @ 04Z  a.@ D@@H >  @ yQ<@@ @#E  a@@4.i-d}N*An͢5\333_ k՛(}] gnޫ9d @z;^ZZEy~3Yo\Z5ٳg^7m\oK[#  XQ\@@ {O'! ܼh.+v  "@Z*d  hRl  P*H&   +v  "@Z*d  hRl  P*H&   X۷O~`@@ @m&~)1   @eӦMN:p8qBv,2[nÇrA,9vsKSZZg^  `߳g}ݒ,\+rJ޽ΓիWˈ#$33Sƌ#+Wkʃ>([_L"eʔ'xB6l(;w?.s=r%Ў;c={˥mzyʣ v TZwv0н{ʄ ~'țo)oqj۶9R=*]v_~Y7onI <;w,ڀ֮][tN/y]v>o^0iϞ=&h bcc/m[N<$&&s#+@@qai%'''`6V?MW]u >f͚ITTl޼Yʕ+'ZSJJԭ[W/^,.\P9pΟ?_v-j/ڴic֬YSrssMPg%&&СCM̞ͣ@@ tdlP߬UgB M{95(fn{Itj됼 ͜RvwA- @Yɀڻb 3gΔ:x/hZ^=駟̺7kԨ\pfH~ѢEfxe˖{!u@,@@,TÇM*֓ K}5ƍ3g?fn{WȆ D[ha悶o߾lX  pJ Ԝ\%Iz{q)##Cׇbhϸd ?~֎=PQ!x%S E锉G@@ R@#e  a0 @THmY h6 B@"U4R[z! a*@ C@@H:aزjTo!jKۨK(.zsDq.uʡKkڒkjRoڹlٲRZ5ٳg3zŔvQOWn*%r@@W@]a%S@@/J,.߽{G?|h~*U\=N8e%:!j]@^|EYf ,w?,gϖ5kFpMڊ+[nGIƈ۷OZn-t)k*|D7/C@O4ڄ! -5rt>diӦֱ ruH/JQzݪU+9WsBB\qRbȬ$2zsrrrD04! '| %B@"ZlD׎8v,^Xt8GfmG^eٱc:D۰aCkx_o;!Iz%KHSSl5j,СC|<5+慷֯_/[nmGK"P-x uߢE _ʕ+}yz ~mrIqy44`vvzSRRdoߞg;^xCvkgO4I-Z$ި, pEرc}fz;[>'v2rj[~"K`Æ s}!SFV%-^E{}*EzzNh~XJjZ) @ϟonˠA<]W Ps|gX{B{m!xzh H7G 輿?\Le?|ywpkG m@I%eKΝSNdUԢlڴI~isoRDPUV#ôjղH߿_222|y[ƓЫɅ$>ߎD<?~\6olOo^b?F+BHh Ċ44AV<,x4ltAĆ6MmM3/Iݫl̝9sޟt "LMijj)++3fTl1sLPY\Ghz ͵[sjS&''M\s6 k4xiTiiiΪ(~?}TZ[[guW< ɺ]mmmr:|SSS#UUUh844$fFvttHTT \bRԤ=ce>t7v:}^uёYh,=Z+n7=~&ueo~^\pssst]oZ(;:C-#և+3{ni  H:P)@@ @p#/ B@+@kK@@G :P)@@ /_R."w@si) pei)..r9  _~Df@^"NgHwvvJyyV:99~ p}lo߾I}}Y۷f>qEW^rQ޿oؘ}ϟr@ G 5 JII߿g~ԬIIIaUvv&?~݊?}_~ ^xiiɣ˗/䏊8 L}] ? +088h];rvvVdxxX&&<O u_^^ޥ*_]]-&orr^TSJB4P9CA`eeEScB=&vʹ4::Z}ЀJfS{^I  S>{ߤ8#"" :u+pkkn59eD45AIuwuu%11 ϯuښ۽7oۗЀ\UE:YXXns;$ 6;::̂# ---cV?{ȝ;w""GoVkO-J^@ )@/=HHfESSS;III1=f%{LLi\__y}=>yįFk *8iyyٯsɌX!2 Џn 4cccװO~ 4/S\k<{m7]>#@}@@ h @@| Ra  @@FK  @}@@ hA`@@_T؇  4РR0  /P_*C@OFIvavIENDB`forcats/man/figures/logo.png0000644000176200001440000013154013413770514015611 0ustar liggesusersPNG  IHDRX?gAMA a cHRMz&u0`:pQ<bKGD pHYs!7!73XztIME 7xWIDATxgG}5l{̹:ՅvI#ʍ A }Yi ֌ F{sۑ&tU4ES2GӇ +Ev=2YQ}yvϿ< (v>+oRwMb{ 7wp%b ū]0?- Зn%.w>%;]w:?;%]B(o8>=7P]%;-ĕρ3@{ɗ4;]"K%;}@j~D\|p;x]k ߁wsK- 1 ?u%N.wWNsO7>pػDa%C8~w[5:%.2"n?9ou$?6:%."W/NmquMe]E-` q>忏ߐy7#<~c.v PK7]ju7ŗ.;HOO] `cd~#m7 .wHaW%cgnxؕ->'v { }C?dWXRaW +oؕ->_-E2 -W,{߰+[WD]6e;p[ᅤ_}mτˬN !*:z@~-Cw$@D^oy["-"@u,穭۾]׋-~=ލK2?I5N k*9\z#"FPW._Q]Y^!wpS?=-W!y}]-)сG( z˗/8]}CȪU|a JCnݺw} RQTYU+훶!#߻[]7Z7~HoQwh RuΝZ(?4؍ʛA$DKtsUΜ9C<\edxbV6^m?Row}";>QB5*m./_&J1<4X47_C(`z\ի:tq"쓘| elϿ<^Y?twx/d~(!H2JQ$3;;ӧQUa3g0??twIN 0;$m񮞏)d~g}4B{XZ`uu'Ow~FqhZ4 x[ޑ~jd~>%I4R??|79rH$B>gssZF¶m\k'(Ȳ-2Z>3t]￧ZQA<E5vF?z5$K`s'yxWx>AϚ[w}W_}W_}ŷ~O?9088eY *xR$IȲLn;8dlϿ}姾ߕDi}R;J'6.Z4 w^666( VB!"8Z$}<ϢŲh j$!ia$EEDOlx׶I$ヴ@#udEr]^S_qjqrT AXZZΝ;O eYF$TU\.G(buu~gP(8nը>us# ;U'}F EY?t-wi6qqd,"+xgT0ؔ[X^Dr9 a:BLFvF0" lݍ}]~(;"j$xJ%l&l6Y[{5ݥyZ-J β뺄h-B#xk<yb@%Q[ԱDID33?5סfil"GF^C k(Mz*]=j뺻D~uH∴o/e5 ε+++O:feeZm?ϲ,"sssT8!MES~m0G&2Ze e")~c;Aۣ(H,+ױ]4,buvA$>L_\^C:IY'lWHLjg\ͦ{KWHSw.$=3˂@ZܹsDQz{{4myG^޽{,,,`xp,Nr}#|-*8~h,)~,)B{ 8˲XHUQ@R \ϽNp퐴;XRRb7\VP4sx={p&&&X[[{RekX9‡~. (`^"5yK[HM ޞlYRo]",wfXQR0M7oRVQU$Ibvv:TURlRJQF$ןKйW%DIĵE^UEHO3p>޽{4pd2?ܾ}VVH gFضiOxOGm1`6h20l7u9KD~a;C`E yGww7xD"iξdu󬮮Q"IQ"&Y~ɖTg$!h*e1؉N-K(ȲDĮPh4V_0442ΝcyyUU?$͢( ru}6KKKut]gxx zzzP4eY棏>b1 >ۿ7Q%̥ T-; `E4 "ȝ;whҧ^H$&Ȑw BdONmI^9ew v]~-"rN4͏49p?2== ~!VL裏gjj uh}i_N$2>>(T >ˡCw7s_z줺~IS7qvNϋw.".]T*Q(XZZ ܽ{k¯ ˲X^^&If(*i{Al۶?Mkے$RGeJbp5 àEQ󬬬p<ׯ_4M`jjsαNOO{eppA8ViZ\z7n,A=22qf4-,uDZo햝wl1ݴ,27eaayn߾%۶Y]]%ɠF4,z(Q3 C-?nۖ( lfig8weuu`fѕ+W8}4zA8x dgrlۦ^@@u0m/۷l6yhF<0 DQB¡-M ea`&A4j9e DP0 ܼyN0~Ԏ(aBm mINIt?<{2=7E"ׯ_dccAt]woe}}FAoݺƲ,VWWsnb~~qh6K__]]]066Fwww0P4$I-s_CSvjI-s(8冉eY$~; 2vd{a$l6K<G~Y:$$Ezٯ'p\~~ EQ/HR>}bssreYO{8Aw޽{pyTUEQΝ;Ǚ3gexxqJ2q]vj1$zzz%m(P#IXFΙ3g^kE!"l1z.E!B hA6d I!m8CRHjfݥ rYDQO?3gpu<ϣZ駟_s9nݺ\a~9:?#BK&&&XXXR)LA{]~XmU DeNf 0uo|ac|ƎށEI%5\|7oKRJoo/'N>?31 MUIub^wKr-)R w2ԝ˲HY sNL>0 ǙիAx\.3x6˾}r,p_{e||SNVX0$b?{~~O?q tLA%5}v1P~m4]ZUyXdXy[k$) EQT*ܼy7o2uwwDڋ@ӑC!As=&aDVw0&yW677V5=Q^s_옱X MEqO}NpuuP(mYBE~&W/j*'icL-XY_Uw&;_#B\fvv\F"ɓi0r֭`GڊA4M >. JXz Y70`_w; h4sN֘QU#;EUUdYy3LqaЏ)(Ԫ;2a8ΎR^= 4 ,Q( ݕf7H8ե=Si:Jw;c6pd2an"EOOM:&,˔J%6K%fzepmj8{,˾A;bu?8ofKC{4J/; |=p #C, m~-w D蚦f%?h4$Illlv6sVK5 qb,Q<}6oH 5v*:=ϣ*4uG."!LE>%`u9˛f CO0)1yHL.eo.Fծ3&޽{Xr9r$hx"pu1MfeY1J/ 8p!֪ "K\|9贊D"@^߱ X[[g+ 5h ¦a^$Fnw{ 蔝*% ƙ#S:H2bPzx#*w@n6KKKeB(ٳGDizR mted2El… ܻw}144LKOx[&.,HF㍻k :rJ"IM4`gt|"4I])LA-'x zPupKM;xd[|q|rj5Y]'aE!Յ X8h@ n`O+yf:2̚DDAGJH-=Zue2MO\ob;d8rxt1&/%l  Nܻw">5r8qMdjj|>8B!طoH~0ry[[.# k2d20at]~(1[U1mfL.˜={qu=ST*yjPa6W\ٶ~cI O ] 0 & t|dyyyG;z*100Eܫr7_[RY QfڵkLMMQ$N{N zfRTw{=L[P,57BNC#[9sx_h4z }蝫غ4ړ)Уdr&LRyem%_gC~Ѣku2պC ճH uJ{oky駟 VΌ޷a#28qH$70[Z.ƐD"d2Ǟ={( 377(^'EԩS %{rܓr&!>ZHSPi: Q!hBaR*YY^fqqB\NΣR<ťq=s7&-ac=(}{2-Zvm!Eߕh>W/l\|r0.6S$< Sp3x؞H,܈NcӧX󿪪tww399do޼ə3g^{q666`zzL& R)r`ee%z]h4(J8`6( !6"Ҳ,*B ju,p8DC$Ro($`ǣ)3Td%vW"$QuM: u\,qT!BldMX1PѱMplV$3boplnnIww7CCC Μ9\õW($ &͢*J)xj/_'8/w˥R9޽ƶ&:S u]<($II< woR(jjeUM:?T*hUU X"hk}u7(|֓b.9ĵu-/M`]ӛb_ B Mݔ:*#+r0˱D8fhUkӪ5p,%+/Ǔ=lŬ(N%/E;wO\~WE( Li׮] &3mun߾ݻwI$ 2<[)=7cKl,KTl.ΖdQUb6%PdIPí<,FE{I"k(nڵkX _5044===hFzyȑ#;v R?[n?F#镚m9 P-}o۶-KZq۷1M3pXZ$II( 'pW"T*r9Ñ#GH$eYp5~\"Zm[ LNjޱY\\dnn.irGfh4J. vṹWDQdbbl6ŋ}eBQbxxfwbQޖn?MA%/%X,9V4RTNNn3@R}ӳ ICGs QU@;e`4H;ݺ{I.)~ؽ]$Ӥi"Paٳg#w/Z-HbtT*E<GUU333\r/r5W_}ʼn'@HӄB zp]wKRV+hDu2 d2677_^344RX;ܱ1N8W^}VGU, tww#I.]ݻD( aD\vţӎ %)meE!RCdiZբ)Qj!1`7ySP 0/u1MO33s[fT 4XB)-zC""{-ہ0c9#qD>>$")nu$}[˪"M3TXDe lۦX,,hqY]:NEcL&ٷosss|7Ɲ;wXXXT*8a;c===B`hvm<Բ4_\.ׇa5n-LNN266ٳg~hvv7oRTPUx׮_T|29(r֘0 &&&Nq_h?}(D"(hp˛'VEQ@D򰑸65ٳgOV>}]70{ۥ1ܟ³w}Du=\IBJТ)pV ha EUMeZk tW#$?D򰎬A:Fpxl$۶) OC7|0 q)ϝ;w{ /1qf裏ؿ?ܹs@9.w^>R?Ӷ%LٳˡCi4M9>X~'xGWWT~aG4 666BUՠu(~)TeEQ'Lo>Vpc+"\}Vw02/@4fgg%N.ZRDXZ>X9{,x<(MOO?)iy'3qMϋt:M"Zyu"'+(EX@oWwۮv b$V!O}m)8vA$%(5DA4dYV+Xq^KSYQ;mrGR@q ^駟r Nxxs WWWr 'OСC`;VT*44MVWWY]]}{l4A3 `:B:uIOZ7H{5t+(-z46K؍s6Gn r&C<\_!#Mý~BvCNZ$tNcZ l ;mr̥Kq7npE>\ejj9hZ`ϳĈƍ ޽{矟[8d 9vj#4?SVE|^i4u¸ѶlaT2hpUd]b J4{eñL*-*57p(֣$l7zLX]]err?? vVS<`z=s->|UUσ]޽{4D"AOOr9;wHYl255E.c||7o>5[!@&g>cָtRP=~8\vUgdm,C&pAUUt]hyB^~ۿA<'UILden-< 2M3+HR 2448cccyn߾Yv2r…'Np8L.CUUjФ<B>|RğeZV<4xi42Ǐguut:CwO7(2֛b4@tgCHhDj϶o$Z4bgD$eHou&({PSUzHCמ*$ 5u,ˁ& D"Au=̙3E"b;Y\\KKKضAvV%:77fggQU>O>ZH"ɲW^1O8x DV }}}pڵaAx.www駟ҥKAifq~7nCN<'3{ynn.(qp!&&&XXXޅBT*Eww7w>_Г*}pӧOS.d2LNN_sܹg QpzG]:>|Bи#ys308D6fKd Ϭ3`H $,x4M\ǥ^*z< ߢDTI\NO$>fccˈDI74k <̆z ۶;d2d2RH$dZE٤T*QשVTՠ3S$I&''T*ܹsδD"G :qX__g}} =660~$188c eY&wԩS|J6x$I|gAHUU駟k\(iR)%J54rQ*{Ud[^0|\@KZ,uudAТQDI^,6f8sO'pmm!)jj"@m#븴SGlEv Dꢷ7P _mFA([VoT7Y9z(hϿM˲8wtJ•+Wa``IH$ȠP{V=<<w &Ug߾}8e*B4iZ 0H$ e9H&)J_ĥO C2B4B,vl RȺ H†Oju %S c5[.# ˤaȪNxt?ZjͅX*դ[(P裏D"A產([OOOԱ,jʽ{Wygyy7i]T8Koo/DGҙ= ./_&N_i$^[[_EX|ƞNʕ+( {uV%"^nd`WjM<ˣJdi 5Em#O(B P pNUSsB4":Lzl>nc ױ!A@n։8A z;Ff1pŠ~&iV!V9::7e}A\&0<>8;]aq)\r婝\.===Q)˩i>#J(BXaGˠj"zp%d' Nk7xxȚ_uA;$6MFVeUn޼]eYȑ#=zVŏ?Wy011ׯ_eYa<Ⱦ}hZ۷_d'cjfn4,lRg}}bHV{yB/{PExLoo/W\AeD"M .NP =Algy}EPuE D+lT &j{הϱF<?6jkNE7;g62h?"(q<ˁ0@u9B.*I;vH4,@XH.)ԊÆY._LVHDQIJ,666}6w}v\O>$HBW6k4AIJ]d3L3nnnR((__ST?30nݢ^4?~:p, (QP1d*T c*-D42Z]UKAln>2)d F&LjK`srgΜ6 Cecc#>YӰ5xk?& ,zUUI&R۷oS# |8~Usc7}<ӧOsG0UUd20<<̉'ػw/sssܾ}|>eYȲ8p۶9k F]Ndr zTT_(d4x?رcz>p@гƾ}VLMMr*L266S5ʝpa~)esƍfǡRp=i4@Q smhǡ^3f-sUr Udɗ#[Hxv[8&R+/tdU(BҗNͮrB<D˯hMf/"UPCDؓ ;)̫ b8rv#s癞ۏ ]m(dp|>Ͼ}4ׯoˀ"N=x<_ڊNdY~iZƵk׸yf࿝d"F~Ll\__f:yϺojA};綪A]X,}ײԊ\!;O $qQ2 W\y, "iسg!MJkÃ{ $r!PDcX7f8H r4 a}}=8`ϵ099*/^|}i|^M(bݫV=Yӳy$9뺁1vrE";7n`zzG{ɤ_xY0sqUk8ܾ}u/9bsCI(DA [l+V'I.^VJ0;;GHѰ k%+@w7Eí[+ԩSsi:{exxsqڵ M+iΟ?ii,]g\Š<9o Bi_(:(j6\~EQ$ǏtݣT*=I&FtejjQ*p\I}y. {χ~ӧ2Mp/#fx8Ӏĺn:ȑ#4M\lzcVx޽O?h 矓f|w  !K-za Hjz\YI淿-7nڵkA9aȲLOOO0 EQm;05w]7366~ &&&8~8xΜ9RPgR}ww7׮]od.T*(8ֳWv qiQΝ;v:4 R 122 EQ}L( hP(DTҥKukm .pG[ 000LU\[[˻I+da<0fǟ!mhj5էe!2ݸc6vXo r!Ȃ$ɽ{Yw98> ,BO-|_'}y7?}ۿmMs7YXDDF{S(ڒ8fjMHv<<4GM67KD.C5I $aIc&^1vhY-\A]GU$bpd"\'0z2IÑX.lKӆ٤ZP((llP*YzZtv` B]@5TU;$YQ$MJFRõZ8v nc#xN@dCwIV7jKc$B(mV+,l6Z [rVqii5*#I8|0ǎX̡rkEħ$W z]NrblmDOE1eS`&а}Qp=߸u=t% !y : d"2IТQ,`wUY Ȫy˫%6mMRK戴hYQSרUj5:f4ùV6[Ň#;VHMӂ0cTUCS$YnPeU0]t&a%x$!Ud=O7)]((0Ij?tGAUDz3wIQf: FrFKb!j*l Ӧ^oP,Y_[#SuQFF+|UwtLBhvTănNr>j{x?z-.Fǻ\t7"GeUn | -f~!+].1PJD(.*`*PLt"!$Z+P%jr04cZ.x`bwnn?GBQE)aEm'$3dCWe U,.l8VC1N% .fĪ7<,q{ƿyb$B*G3ЍjrsWJI.u`LFZ6PAdHRH`Ȣԕv{Zec$2 /tҚpޮ'lFztvn/spxX+ n t=\4][@W& UȐV_JX@N7Ň% $ĖeuT*IR0ػsBQjN1e\nޤՖGⰔRC.d1> < 9*CeIx!]R|됺sjݦ6(("zJt@ِ$'iLЕx J0(() y 7~h>c8FL#i$C@RdY3lmS/i(IPV,6zLĈ'D<F{2vD~1wlzauB$IH$%Jw7VY۬# pdja^n6oE\{6nN|#-֞ sR q'$ TԟT/N)OKL?Uy륚Ȑ%,U/HFCNN2ޟf?M"SoZ145\_Ȅ<[vTVQ؛nOU1tYeg q5㲮Vyw[j:x>mV@rEBQU$YD3 D\MkȲk(е9i H(ئ?[m(U\/'OO5[\|`wQQuK%^<T $E7]d6%QUFF,AF{.=m#i? {gFz |.^AU$ M:uu#~;c+)Hg$7<(Q]m8~˒s$UERAueAl?p=Aܲ({2[[DY8E`ͅ$) g۔kM7]ABvs_#~wiLͮ/ysl|:x*u;N(gS_8:n KSOX)΃9n ) X$DQj'4Ã,xXKaZ1BZ"1ƦKDI" IzcjI
mS{yp=#C)/ ]uY\ldEIf2Ȫmz~x[Drsre[ ;KrIԛc%ڰx*qJ|Ƈ7f=ʫvcوŹ5ܚFV.ٛyԋ|OH8 Y_S_Ip[껮xOA|.P3m!Ο ]Y޿6ݢG\G cU^u$j"Q <L.2G2BNgx ~um|C72, pxG8ՔcS/[mKeE!Cqvj, @P'Ȋu=ߦUї.%'D{$11c~!yzaY ϗwyqPuµܟ]n yi_w_f$ "rq0%|/7*@*YQ.xC7B7ޛvі%L``CYm_1u$'GJ"uBl./KcTY©TcsFAFysP]Q]s;Lw]ݛk g@FD2 C#5Us=Q]F'$HȵUwnz$By2"2CIDATZ!9uY,Lqs,ZҼqz*>FHsl:TJL8!h3%M#r©4,w{DzHԕRm_Ark 'G6}e)Wҽͮa;.r>Gò9rdŒjE2}&tjvXl~jܵ/K0L}hz4*LO/eA>qTh'ZFuC'5]ouW$,J$4\dywi:Ns9FlPMT~ LjPɶjO\WHQT@*(=2TA` |Xh\$`73͗5rNTYc$"F$r%!A ^ܵNÙ8(keꦍ,I!$Xn@`Vh3̬Ux8H|a z[ #y o__Pj'6chx-.t<>;G#EMGO8AUmJ}sJ.a*(/{/# 2Q!}vI m ? $LVi,skz,:of%tetI>džGw)TL.O %FM (h]әRRR x}}Yi#Ziy %8=6oNMGcʜ-K,j]6!(ld](\ӤiDK I}urAD H4JYoTJS[!Ȳ fsYqV!mXcv7kl+u?敊+Em6st(w/ WS4L{Ò$J&&b!pP @A#>dERIp]G JI\,Z Op&J\[L-[ ӑ4}CDNs9ܚUfVBXo'Mg %ihȡK?4Ï~}ZltC$eQ<|xH_v#\9i)I^(N }Rt=8jMgQCVT"}}Σf|bmMı30)JqkJsh? k%>3,IL.6r! wԵ,liFU !BB`ՒY)P k2qIz.Ux԰eTYŮ(4JEV5>2b* ܞZ zQASū繭\$,M"ŚLz..aނ߭Dx"w=D,n2~6l3e6bjyzZzI`h*.  z;K*YQ&d>xeOF7$$AjR48GS ]sj,D=J@d^&$}LNqmre 5͒ ٽOu g2B2PtGط^8tZ6OŹ6/.?)^={w.?`VTi(Tlk&+mbP2mȚTbvׁ0^IE  mgURf\KbIԒ0pyK:ް!*RB2?q(@:#Rаl$0m4Ua|x=%?+JgkI0"B@ hr.j66.OpDZjDWFz(*G|! d5M/M+j6,q|0_pU71J^$:^ j 6Ba |C Qc:R!zu"m++JzPࢢi݅⁩]Zbr1j=X$ÃP&’$1Te[jhf[$U~/*ܟϒ/7a;($P8H0-szov+1m7xp7q~5p@, 9qh,zU~W'D㍳B2mX&w [PplC#4dME7B<\̳-7:9?N L6G6zvM#';e_t7fV`2&PnP2DdcRJ"svaCԑ ]e1[fXE$L!3ڟо*VܚZq<*eH;X8$4!XݖN q],Jbn( 99a(@\8u(C*fZnvo._\a>_$ƇyH+lt|Mh}!r,nSH5 lh$'yFSGGMgnAm#hD6&ΓLEfRT3ǧFG ƇSdj# spNf2>W#o%_aPABq=NE yֹ 4R ^`\2/ ISO'Dik7%n/޵YLCBB`Y~Ӽzz3Mjj6(2c# &WMTYձ4?xqL%iTC!< Mf1m^#cMHs_99±AHq{SȠf#efm9^6%yEClL:-Z=Bυ)$96&50ދ̯?}Lۡ/P_beܝiKb;G4w]frkrɲ da\ϧP+-ױlETyÏ%eYUW|GY&4sz7 r?N$mAG@a%7BT V|q:ݫoP_t:4X,D_HI`L+ 3E\' k'JStM|ءĶ!I|kj)&{O2X*;XQd>1ͽ5, d¨R3[-r.Kj2:@S4)sU03e޼>̡d;LN9AC:lMJmXx|ǡǷyI&V8>;8ʹl@$A4, 2"Pg,|  S6XΕ}\Α񰱭RB7V6XS 9QR7iTn;.Ūٱ"a#q5QJ: '>d.HB|ӣi1y@wevIQzĸ"]u}4E3 EUqu<`\E޹2hrѾѾ(E#[ 48 50K&C?jJyiZܚ\H Zb;{4п l03J%5!Xdg$Y/afHaѰJ*DD}RD8ٱ}>mӺ~P6k¤/bR$μ,K\|̇7fZk^KuMllqaK2]bv(&aD u b2afK,CI.|14cv. -$ V":/q0F2d¼ʹ]_'4z`j-y4 foƐ!L)2xHD YnT]%޽2Cf$ i'IAiEY&2jŢ\dȪR a.#I2)* [Y޻ĕU)|S| dUjt)B!|J5N#7B̕ҍuiyjAq,w9r{z+\@lͿqPwFA,L * baXX.N8ڟ@UeʸGBJ$dhښ7\[|pck]c#iNu]{}>$!~c6!4 Ѱ.$HFũ3e>1# |0'Ro`E&YS L:wfڽ\x0Ɲ><Hw^N(&`>$?Dۜ`Dk@o8`'cv.OI^ 97׹=B.灟ׁCavq>|b ! ҟq3 q<%ͮ1X`f5>3|nCy-INʎ6$0> .I0N~$`sxvPPsfS]L>ɝ2 dEQY)T9Ѷv)TtwnW$j||Z0z|륱.Zf;HGvn) ""r,QOYy q=02fJAe7?}̊@b:N ky>,zeY~[g99Hy%ܩB:=[9rzq5 YBHڽH;P3]C]D3tL%޺8͝"{Egۍk;U$}Ϗ֏5ffJBHWID炖8q(C4i \m"$zf3Gֽk>D(C6+u>b9$YSṳP_k6(,>@t3#IJFh4BJܾ/`".oc?={ɏݒm1(ح]ǁufrv͙M! Fm;ܝ]͋||crM?k ]3%rqxH"Ѱr`rHh"yjMHp|$)T6 $ >? $jB7>0>әB6dV\ζ*lh|1$лd\?Z=.̪[b(m-cqd8/+-ʱ֩2at] H*j8<ڪX?S?〢EBawPG{ڦyZ(Z_\/ﮰRS[?A$یmձ#M?AׇQe ^jrqIB;HHgl(ũ>642q^?;7^0:" '(Y ܱa^}a;WN2 #{6뀄jH ¼I%ى{{gm #eR|>9;ZN\xIf ڱ 8 v,neVKL2j<Űq/Ω#}ŀ|q0GRs7$J]$әIGvqwz{skPe^ZΕa88}d@OPnB8 ΕFZ@/Y ,d{!ȽNC,"!eQ71㧟Ormbe; wFQm}*v) ZF$hՆJH,uU!di4&wgW\aPes1Brجd [=ޑT<ՇmbhN) bdMHYl76r6u/,"]UCGbzۗl"GngD"rh[rV.Wπ~`lnϩlq'$$na yf-pGpTH()7ޞk#&@@oMBn&Sm z0wrfjk"1n `WX*Z.B OfVHd@nNe-6J`#jKyrZ[g$p:,Υs.sqlKk# p~I?^ཷv+ʹQEA `T,o_|n+Wmk66;vc3?J-VE]}L%t(E2KgLtkwxEIj6 ys_Yt<||N|h8)bWoҤ7n6¼"{8ĭѦnq|u&si_]"_? {rx"pD^B$C<b9-JDaq}b ' ^.]4p}[y>+LO=r Y3,f>C)~QaҾ̯ljB-ey鍢 wYmF"ǁN &a$XdEAY-T%~yklm!x?CPH6k:#ՏQs'[lN[W(T JX]5;3mpI&S9nNqcEa&x~P)qݗK`7-/[Γ6YGoܮ{d`ouEwxI/Fl3>mƾ4\;vNb=ϥlQʐ&Ω(oa*uNM:FN"3Cq*4banďɻ8JN{zf, q=ƛOٝyͶ~2y*1CsdȌ}U GvJ)*}IWdÆKc| g`[Hs/|s[Gg'; jV.1@߼M|ϯуUJ[+CS@#†Pttg|FYzH4ء~:rZ,|r~,>?N2m0?/+ޔigܳ-l>yX``JFY8V;mަ,k3sqlu/NL'n30:m@Y;P`jg[؍xOrd(E*H_t GS|>uuVڎ@~so\]9ຬM>{XX@V8?fl1gl٦sMLey$7&W1mw_d~_ӽlF$R"5؍:1:ǩ`>C" GڣAzK$UüvrْrJRn8Si1f;;T!p[4[7pDZc~S=-&[,/NwI 0Y޺4ͭ"-x˻,:e~K~So"[9ma]ᕲ(H#Fleڜ[@^ u|tZ7NQ68[Tipn(@Bmj6-.y$\T3rmړoMfKl1-sgm9(?ʂYRoHR"R7m>(1`827)[E4q# mf9Kk%~ug_\d1Wi2%xO}7c 0=f^ĵ,1iz@ { ֖s ^).eCɱ2[%N鋡xNNU}iz7oIfeLˎ[ET``SفǓ-$+[z ߱iǒh~VaPn|>Up IQ4+SoX|s,BGQ|xo]fz}26lqq>޽l1WfvESSw>&RjtM״Mƒt}gBq}(2j e\0 AYuЍ o_bko{S#ۯx*7'e5iEk>,s?΅#LOI]>LL0%GcidUw]f $˄Sixf$vGYŘ,zkS9das!]}Zz.:|瓇kL,p]o;.uCD_mӶm9;Wf4j~ŗ2\5[Xm[ԆI|HVg[dK 8p e"jspJHץް:!W,Ұdg33$ۯR'0<DzŦ]%]Ǝqន]'[\WL>,k 0Ʉ?$`'bUUt 9޽(T4 p}0>‰aȁqF{.VdxRcfJ.W&,ܢ?|u#h "f}$5__*'cq3rŃ}t$#u`܌(Gy X|1 jH (ݨlkJ(L8:[+&TCJ P#-\!JF@TL%* k/ vڿ[p;zlqi-m$;$ ,]J:,&VKGSMT>n_.TJ9,W9Wue1_vMZH&΅Ì P=2%D?7 G8"HpyR0Z/3IDP$HxNȓjx$} A6x$eN 3[٢$LgglI %0s6@z(hALͭDe̽_*~A OB"HchH IrHDH W|p{w2e m%W1֕\ a^9>ĩ> ]vYDjZ.'(h oeJ#W` @<-6PH:#G@XY>}tsd~O{$DVo!ǿvs=5^9>D2X"?DTO\nYـdX-)?\n@)Y~qOû ]P_-8lŃ ![٢Ϟ6e~| q8H0lqq {F X[D C9 y8HHdM?B̂Y~bs : h ?@A?gn/$?Y%tEXtdate:create2018-06-06T08:50:26-05:00QE%tEXtdate:modify2017-11-21T00:25:55-06:00IENDB`forcats/man/figures/README-unordered-plot-1.png0000644000176200001440000006645013432022227020704 0ustar liggesusersPNG  IHDRz4iCCPkCGColorSpaceGenericRGB8U]hU>sg#$Sl4t? % V46nI6"dΘ83OEP|1Ŀ (>/ % (>P苦;3ie|{g蹪X-2s=+WQ+]L6O w[C{_F qb Uvz?Zb1@/zcs>~if,ӈUSjF 1_Mjbuݠpamhmçϙ>a\+5%QKFkm}ۖ?ޚD\!~6,-7SثŜvķ5Z;[rmS5{yDyH}r9|-ăFAJjI.[/]mK 7KRDrYQO-Q||6 (0 MXd(@h2_f<:”_δ*d>e\c?~,7?& ك^2Iq2"y@g|U\ @IDATx xTE7$BYEQ6qYDAqEqEE@ UA/ WT\uP.*; [C[z@:s_ϓtW]U眈ߒ@@(!2%t   兀  P%@@@y  hrs0@@P^  %*PDؿPJe˖H9q•EEEIff+~::2&::Z222\fL2e*#""$&&|ntD,W r׋4Wn*TkZͳPC¦̡Έc·w./_%K%-ÇKXp}];evVQ<2e7 r1~HV2))u,PK8>  `eNq@@ -  evy# Pĉ ]@`h V@@EX   @J  @ #;A@V4X)C@(bad'   +z  "@$eƍf3gǃܒ@@@5<={,^ج1f9tPY  P'ѣ9L$;;7o'OXHJJocD$_VV̔#G8xD@V+W#GɓMoݺU $~;Vf̘!5k֔={j׮ c޽2|p9xhYn]1b|}v V`ĉZ"66W_a hJ P1III:Z̟?_^~<8F6ԍn1@LTuy.xv' @@ @o.9e  ,xO@@JTD9  (@@ -Qn  `IHW%55A\\:tȚ2=x$ו 7Pۮ[kHVVVUA4_f" J4T@@ _e̎;v뾐  @PJ  %@Z\@@ (РX @@@K  %@+! hqI@@@bb%@@ -e޼yn_ѣGͲ'N3@@D@*عsn1{l[mդԹ[)KAmSQp49[duYtRO7prg|ƌ&u5i$ygE&xCKRWسgt\' MIժU.aPg(2x-NLLzXY{%?tjժ%QQQm6YhS+]^x\RjԨaOݬ^z|}^Ϝ9Sf͚eӖTE]dT"SLC۽{C|m}y`,WU *T){,7R9x)T{cJ{glj3LOma`$Y[ C$##լ@_j+… e͚5O;#s̑+bۢe]Q;ukJܹ b%\LG xCJKJK2u8)6JMejMevZhK꽭Υlg]O^߶ճ~>u)KA%3| @?cS 4i"oi&:c6B6jHvme/,  `_ktZ$u}~T7n,r{drwˀ[ny@@oNWh1xNuѳC$pI ..Ό <::&!!\, 2hᔷPE%%%wo[=kcmꂷZ{K3R>ϦC hA2g8?]|a@{а"2 xK[Ii@@ *"  @U@{а"2 xK[Ii@@Va_E%5554;g  @Z@@@@ߔ="  >u+ӭD@@04L*l  RӔ@0 "@jKMSN@@ L@ä"  `-5M9@@0   -yR@;Н;wovA@@[\;vLN8᫫GJFF>xyLII+(>|X?./V7o,'O̳ɶmD)33St['KZZYl> x]շ;vT^]wniذaҾ}{kwrSP裏oV&L F?Pve *t'?7N*U$֭_Zl){L6Mʔ)# zɠA~{1`#SL  puZXԩSGyCdΜ9=zTZ߾}!EW\!/KҬY3j٩S'R HkԨ!?f?ϗ6m_>4hմ{n/g[|Ag2$Z>RɅ5R`m[ ZIIIn"zNHHss@hVL٫U&ْnu / wygmmt3 *[}˖--M65[Zdɒ%Һuks9&\`ٳG4ի=|/_,Vm%uR}μ~ p[fx%ʕ )JevᖷP'22RD?sΖd[=kzVV-l>lz?k q/o(*#NGh;>>޷ ,u~piM|ݺuz+V̳r]^0Kjjq]cHIC rV5: ??<}WA}E m*sLL @Mm\lY_5$Yhh\Aol \}6Oki߾};< @k׮-?|ӦMח .t/^tϷhByK͸Px<" )oќӳgO.ϒK.2{lzҋ'&&K8%ߵkא{zvk/A_Of^%i7>lꂷ ^O4ۻw -oY\ B|\K"cqr xQ+2! ^ jR.@@ L@ôb  UP,B@T4L+l! ^ jR.@@ L\}!05uEOnn!C&6zC -gǶ  E -2  ]gm;vܻV! X*@ O@@ --y X*@jiSl@@@KK"  ZZ@(-Ғ  V߼yIܳN8pcǎɉ'|k~222|ӺlӦM&qɌ3f͚g9rԮ][/?˾}$:::j3gL6M"##r+nرRzu޽?l0i߾\{tR:tԭ[W֮]kvӳ>۟nLTRJ%q!ZpSP?ɦ2ky*s2#$$$HvvXlg Ӥ_YYYVԱҶzv*6..Nʕ+L1@L$<ũSP[>kM_g}&<ҺukyM魷Tn>ydz_|!~PN4IyiѢ/С8&r-JP8cƦE$(JfNy*JOg]m*dS:qG6y?9ukS=;e/Գuʔ>VZՔMO Җ.R:m%߿y|XV\;jv?YtI$m СCᒥ|p$&&lI111d~2f[=w~gXff-/ol'''ˑ#G7QFf]ߌ< ^e /_>\|EFFMe MVȵ˔\rbgmqq?ӬM6ԩSr_Hzd&2dXB6l(/ V3dʕ9?o^~L0P !! m,sŊWQgcB gmg/>vXh@V^]VjV3gy6lyT ԯp+vbb{Ж1IIIf3%Vҭ9{L[YlgmLNN6a鮮gl HfjwˤI&YPv/Fпԝ&wZ@Wg@p#  u_c@@>2 O}uF@@W <  >P9F@\-@zշrJY~}=8p@͛p" 6 AmZtΝoQ@wB ><(+V;vHRR/_luM7IDDy$$$HJJNNNwχeJlll˙ x]4ݻԩSGd˖-r]wm&k^zsTˣ>c~L0AF @OjݻM7dzDjN:ˮ]Gҿyץm۶&[oլ&M$lӚ-ޢ]S럶hҠR[>5'=zR9j(?xsZ1СC*_N7& pkԨ,@N TE[4h =̙3G^{5 (]ڵkˏ?h*XOҿp-vk٢d͚5@53f_:_~1KtNFdQ[^^ :@@/׿UZli;֬Yt?f>a'8 &n{NwȘ1c䣏>2͛77 '.^Z.y=K[[n$@c  eu:j]ǜY:xpgca82 ;PEF2-ZdZXuXO#W\qo`\c@vG8qk tURR9R?lI9$mԨZݻת1ճR}m{a ~6jUS5͝o7UX|:tȐ!qtm9};c2}Q9seԨQrR/@@p@_VZ?ydڴi(-D@(u322d֬YrJ^ɴ^Gra2ez뭥^3+4sLi׮hOB@lT/:);vc޿n_paȳ=fGrP *Z "۶mRc@~^IG-[HVVV"?~\6n({9M"! )ToKNvRbEnt;Doߛۊ:uJ4|7B fInݺj*i۶ ܾ4zS'ot(˖ CqxRJk~4^h`:JSBB deճDj@z])\\Mܜ ;A=HD/<ڵkл /l߾]'M4sӓhy7Mz%˗/-[ŋef^ [nC5q<̇.:TT fXǘW˷nꛝ&NYO/bޭvz5Sn/GQڦ2;SEr6׳Sn۶zvl~&P :՝(HÆ _~;oqkڴ)fTH Oȼydԩ~zʠcbMzKMs1N˦rΝ;7J*ff?iʤI h9/_޴ED3,۹u}q,Eɷm=WUVm[mqmRI?"veXxj7+W^y\~fmf_z%Qu]9-}9x@@: bٳgCe˖mZ?~]IOұחFT^#  ZHתU\S[A:u꘱zM{tPm O˾k׮dc5\SȑX !@G=?#9j\O(rSO=%z{=^Ǽ y]/(h# VYzBGQ^F  S19=B@h=  @N"u("֭{Wv)͛7];3g<S  )tebz[N=[/'g-+W6g   ^/CLMM4&?^ϹW@@(@ T/Ah"ybŊ]}Q1coO@@$T^R[:^]%0}tӚ\~nzYCN@E 1::Zŋ́Utʔ)o 7P,a'  T]t.L"""})ݻww>%D@8]P Do?fVѦM=8ە@ǎC~'@'tzH۶mwޢg:  Ej >2gCj֬)=  @Q@۴i#&L05j/Ke̘1E90" )tƚys;ΟYx Q 4Ȝ#  nذA{9WjJ~W2o<a@@G 蓐j3g4lP'wuTVُ4X7'  :m޼KrއoZZ|y4O@@-t*76]zO;wʒ%K$++˷ZjIʕ}^z|rٸq)̙3^*eA@JL P=o4gk٩S'y|}%8ٳzry癳5k&zB @@hA[l)-~m)SAu۶m'Nm<('O4-Ndf3Oeǎ⛭9rDN:eN:zoYAOعc5t'aIٟR/@@[jՀjѢE;;X裏0qK||ٳt ;w,z2z{#Feƌbȑ#vra8p J5ӖÇۂ7CtMCZh' wf֭[%>C;vlwܻwɃ֭[ה?۷k`ڵkW=z8کSfWjuR}3˖ B?ᔧ3.dQQQf ʬֻTf\\9ߏB^Xl[=;w1e a[=GDDݹ<\~n5k0_S.ǭޚc֭[PZ>cs/\IOnoL9dsƽpʹkiӦ @<## 4Yf_oȂ#LPkKc=&K.-˚tYgekO?<~om/ߴ^a@TR+~xۖ±B]69!!!ԬaYZlK6s\\YPį:V6O2E|M :~YEQ/7mDe+j*߿6lYsΕۛ|j˖-3 AgꫯD[Q[(?}iEkNtSO=%CgϞڊk. }KYuBJ,(ޡC+RhPNP%qp8JJJ2À>ᐯPzUP.[m zڻ1@nNHA 0~x|j~&޽h egtLmQԮI&EH~+V @%Ro1'vRJmUYM pBʪ'kW\Y]-?  X ;8I HQO@rƦi۶m8Gm5]n/9;ڂvZsFDݿiz!|m K]zf~%myiĉ>Dg hT_Ѷ1cuK604(&ׯ1:>5`^S[2D 6.{=oO](g5Co<^{\_γ<یߺC@l(Tu, T`Z0ϴruD ^IB@(9 @8zy$J%WRI  %/Y%5  EP/*eB@X4+! ^ bR&@@ J$062kӧOT+N@@th-] X'@j]S`@@t/]R;zǎC~pg @@ hZ@bE@@ -E  hT  Pš>@@ @@C8  @AS"  @qb},_\6nܘkHvvL6'|ҷGm}eҰaC1c\ҷ\W_ׯ_?4hoO:묰~.OP8CˬIR*Ul+쵭IIIzNHHp}=kqDHe0~f8sߪU+C^z}{_%&&F4h`;7vڢLܽoߡ.@A<_bWYE_{ z( *ȑ#GJPaq(C&:ܖd[=k+% 8ko[=k hbb {nNчQNrتVLw}蟂;I]Cz$o<ڵ+tqODGG.ݟX|W(jNy u̚l*W?l+S6sٲ]{`KAcJFKֲxvk׹[N~qUW… fz̙yLm`of   @.Z@s䞼er]wwN_:ū(IDATJOF޽91I csmJy>fONN6-9Vb@L ױ>}f:ѷo_33==݌rv;OQFn+@U1C 뮻N6l`q6k̷+ԿgaB,G@[@ 6mH:udٲe&೰  ATZDH  g.Ygn@@ @Z,VE@8s37d  E -" '!+0}tIMMue4 [PwG@\'@*#  wwv>N'N !? PPVYF@,@#  @]Xid@pk# . uae@@n= PԅF@@7 ;  B"Tڎ;dEB2o޼"m  @PV>[ܹS~"m  g~ʳM UT1O<)'N}γÇlٲg3@@@ #Fnˋ9idҤIRn]іѶmѣGKZZ 4~i[0a5w[Gһwot()S2 UV EOk1117j z( G}}Tf+W\as فTԊG[bŊ:Ƹ@4Ώ?(˗/>@"##oY[[6u,իW]vIndfMdԩ_W6̙#'N49jK5\/P<n3s3C,**ʴNXS z( rYUfcz]J¼4a[=gedd#WuPǴմB izRK8TȯXkf-LࢋZliOmqx'Eh_| FA};1__9N`Ӛ4 e*_U: \~II8)6b-6YMKڦ2kkzY˫cǎ$ԟYhhCxPXcņ+$$}#hE߾}eƍr˳>bs_po|'$@@fߴiSYp:t4ϝ;׬g9x:rIٹs3 jI  Vjʕ+MϞ=[ڵk絠hڵ46m$W~}r=hŦ{E;ȥ^ d  Vj`9|pӺMzR~_~2tP0a93?u/\6n(ڥ޼ys3TO$"! /ۘ3WD3 KV;%1k׮gOv 8qb3 {z]J0['@@ zf)  aZ1d @Wkr! a*@C@@ zf)  aZ1d @ Ú-F$j\\:tȖ"#$$$H_OKkڒk]$lٲRjU{xmmIճ"<99|Ϧ A hA2G@hHX)  @AV w1,[}@]b'e  @ @@@"  2@@b -vRv  H4@@]I!  @ W.r͜9S?2f" +۷˻ロޘ1cwD@X㙑!7o}̝N<)u=Ζ;vHJJo^AO8`EwL[^7n({թSG>#y7j~ԫWN!CȊ+/α3]r|A۳>+֭[ȑ#ͤAիˮ][nAnf͒aÆ9m]ԯ_?4h3İ˿M-T%m[ȶ%bŊU m+t \_cǎ,kP 3.&M8%>>tkw&m)\鬤])66Lꋤo߾&;nͷ~&}9w˅W©N^ ΣGol*SV}t6)+_nkٵ-[L eFdҮ];*3R[~ X# _}ղh"_bˌټMXF 1zֽN,wcu\JnvMN_jٌG@@Jk6'ivAIHIOntmQ˵B]޵kW]\svC}Qzz|TV-k+vo \`N+iaͽ@@[\6nwP'߅_7co !,6,֓1cAuSO=eZ[ua~fn)0@J YPK+JzGyDnW_};q)lzjO̵Au|( @]h(+P[N~msP=P/Tj"RZ袋1_2  1B*T[P۷o_Z/ր[n)x   y-# Nq@@JGt9*  `UO@@ -w X+IHVͽ-->F@R94  `N@@R K;v,sl@\)0qDW;2M hA@<.@ x  @ [@@` hA@<.@ x  @ [@@T+dÆ yڻw|y3@@ h`od…yڶm{y3@@ h`Ȏ;|O;&'N:zdddu٦MD@@g9sȴi$22R*W,JƎ+իWݻÆ ˵^+K.CJݺueڵm0dJ2];O@@ xP~G;_ЭI'O6/GyD 9RdҤI3H-Lhy޽' r&yD@0HNNyn*Uc;(cY֭lߩZl)V *n˗̙3e֬Yfo+WE]ddѾ\hKnʤ$@(@(qJ#GHfff3F[hYʗ/_`@ s3Y xv)߼ǏkکS'_۹sgQoyrnM]v.%C@ Ӊ74 qBVM}y9ϗ4~m(GBBl޼۷o[\;b@@ *Y޽{+^zl2ߖ7x 0@z)ڽt s}W4p=t d zP_W6jzɳPޫ vwzs 7sjճֹjժw^#(/>(6n_P G@\&@ #  w{ f;vx[̙3-K(@ h@" hq?@@yX  P-@@ a!  @q (C@(@  -@Zܢ@@ W_}%ǎSg~03 fUA@ 7xCt۶m{̌;wo̪ X!@O5ky|>ԩS}vٺu,Ǐs@@**eʔ͛7]w%wyg5tO?-gu۷ON8!Ǐ+/B;<9rȱ~+&LQFIllY*{wKϞ=}ӡx#!UBJ)UT)d--Tdgg{`z *3J+>}Ȟ={/\s59Xlt]n&3{KJʕEϏ>Hʕ+'̟?_jԨa֛3gL8QF-UV3&&F.Rt͚5J|ONsK6Cp̴*0PVS]kÁ~vk=geeSBY1wU{[ݜ {ݫ Q[2׮]+KI;w ?OٰaVUV@ROMw}y\r8^xBBBhڵkd?/O"@>K%c!:hbb:t(D{ݖ-[=zȶzqqqf^zzzhPKh!P/6"韴ߗZj#<"]tYxP2VTM N|lڴ  `h5kiEX~ (֭c˗.n4Y4nZtsҸqo1ج H߾}e9;g@@.\e;LΓO>kecƌ1c=#""y^oVVVM>l߿wvҥK={L}ZSHs]ע[Ć"o9 *@ (@@ -Qn  85gϞѣ\rHN;t͊belJ:رc9##C<(z;jbKiiiRR%g[=뭾g5fXAIxx*ӦMåh vZ0<,7ȃ>(sΕjժyvmʕr뭷| ͚5å߿lRF%:tpIʥp  @8 04keʔ1/21W$o 9>>^.rP7 Izq^NrR6@@ J!K  k78qB,Y"ڝ]QQQ, lݺUv+^r^zi_믿Kٲ~ݻW.]*u~bS~}Hz>r䈬X"W\c w lذAm&Z{P_U{ǥO>eΜ9rכ`#G~A~WYfCNo=w_}&^LZNw{P=tdLtu|zz5WFÖsz/n7\~&uSs||l~ndxJYt]?ZP{t $9[@g:!9WgP3@@ ,XF!  ug  @X mQ  s@{o  ay[h  \P[zD($R)G="gC nPwz$d;P!2#>> D]@!-eeeb3ZFBͳϥN׭첽mW4^0~Eeww䟞߿ez8@ D JII ,MӲdT  Oԟ @@B&@2Z*F@'@Os  ! -#  9@@ @@ S  @STIENDB`forcats/man/pipe.Rd0000644000176200001440000000036613031476322013720 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/utils.R \name{\%>\%} \alias{\%>\%} \title{Pipe operator} \usage{ lhs \%>\% rhs } \description{ See \code{\link[magrittr]{\%>\%}} for more details. } \keyword{internal} forcats/man/fct_count.Rd0000644000176200001440000000130013432022227014730 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, prop = 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.} \item{prop}{If \code{TRUE}, compute the fraction of marginal table.} } \value{ A tibble with columns \code{f}, \code{n} and \code{p}, if prop is \code{TRUE}. } \description{ Count entries in a factor } \examples{ f <- factor(sample(letters)[rpois(1000, 10)]) table(f) fct_count(f) fct_count(f, sort = TRUE) fct_count(f, sort = TRUE, prop = TRUE) } forcats/man/fct_relevel.Rd0000644000176200001440000000276013432022227015251 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{...}{Either a function (or formula), or character levels. A function will be called with the current levels, and the return value (which must be a character vector) will be used to relevel the function. 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"), levels = c("b", "c", "d", "a")) fct_relevel(f) fct_relevel(f, "a") 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) # Revel with a function fct_relevel(f, sort) fct_relevel(f, sample) fct_relevel(f, rev) # 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.Rd0000644000176200001440000000156713432022227015421 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, ..., group_other = FALSE) } \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.} \item{group_other}{Replace all levels not named in \code{...} with "Other"?} } \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.Rd0000644000176200001440000000200213432022227015041 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") # When passing a named vector to rename levels use !!! to splice x <- factor(c("apple", "bear", "banana", "dear")) levels <- c(fruit = "apple", fruit = "banana") fct_recode(x, !!!levels) } 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.Rd0000644000176200001440000000137213413770514014565 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") } \seealso{ \code{\link[=fct_expand]{fct_expand()}} to add additional levels to a factor. } forcats/man/fct_reorder.Rd0000644000176200001440000000366013432022227015255 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}, and return a single value.} \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/fct_cross.Rd0000644000176200001440000000157013432022227014742 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/fct_cross.R \name{fct_cross} \alias{fct_cross} \title{Combine levels from two or more factors to create a new factor} \usage{ fct_cross(.f, ..., sep = ":", keep_empty = FALSE) } \arguments{ \item{.f}{A factor or character vector} \item{...}{Additional factors or character vectors} \item{sep}{A character string to separate the levels} \item{keep_empty}{If TRUE, keep combinations with no observations as levels} } \value{ The new factor } \description{ Computes a factor whose levels are all the combinations of the levels of the input factors. } \examples{ fruit <- factor(c("apple", "kiwi", "apple", "apple")) colour <- factor(c("green", "green", "red", "green")) eaten <- c("yes", "no", "yes", "no") fct_cross(fruit, colour) fct_cross(fruit, colour, eaten) fct_cross(fruit, colour, keep_empty = TRUE) } forcats/man/forcats-package.Rd0000644000176200001440000000173013432022227016005 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{ \if{html}{\figure{logo.png}{options: align='right'}} 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.Rd0000644000176200001440000000153413432022227014716 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} \alias{as_factor.numeric} \title{Convert input to a factor.} \usage{ as_factor(x, ...) \method{as_factor}{factor}(x, ...) \method{as_factor}{character}(x, ...) \method{as_factor}{numeric}(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) y <- c("1.1", "11", "2.2", "22") as_factor(y) as.factor(y) } 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.Rd0000644000176200001440000000114313413770514015074 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]) } \seealso{ \code{\link[=fct_drop]{fct_drop()}} to drop unused factor levels. } 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_match.Rd0000644000176200001440000000161013432024645014706 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/match.R \name{fct_match} \alias{fct_match} \title{Test for presence of levels in a factor} \usage{ fct_match(f, lvls) } \arguments{ \item{f}{A factor (or character vector).} \item{lvls}{A character vector specifying levels to look for.} } \value{ A logical vector } \description{ Do any of \code{lvls} occur in \code{f}? Compared to \link{\%in\%}, this function validates \code{lvls} to ensure that they're actually present in \code{f}. In other words, \code{x \%in\% "not present"} will return \code{FALSE}, but \code{fct_match(x, "not present")} will throw an error. } \examples{ table(fct_match(gss_cat$marital, c("Married", "Divorced"))) # Compare to \%in\%, misspelled levels throw an error table(gss_cat$marital \%in\% c("Maried", "Davorced")) \dontrun{ table(fct_match(gss_cat$marital, c("Maried", "Davorced"))) } } 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.Rd0000644000176200001440000000232613413770514015227 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 (or character vector).} \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.Rd0000644000176200001440000000137613432022227015257 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} \alias{fct_inseq} \title{Reorder factors levels by first appearance, frequency, or numeric order.} \usage{ fct_inorder(f, ordered = NA) fct_infreq(f, ordered = NA) fct_inseq(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, frequency, or numeric order. } \examples{ f <- factor(c("b", "b", "a", "c", "c", "c")) f fct_inorder(f) fct_infreq(f) fct_inorder(f, ordered = TRUE) f <- factor(sample(1:10)) fct_inseq(f) } 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.Rd0000644000176200001440000000443513432022227014571 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/lump.R \name{fct_lump} \alias{fct_lump} \alias{fct_lump_min} \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")) fct_lump_min(f, min, w = NULL, other_level = "Other") } \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.} \item{min}{Preserves values that appear at least \code{min} number of times.} } \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") x <- factor(letters[rpois(100, 5)]) fct_lump_min(x, min = 10) } \seealso{ \code{\link[=fct_other]{fct_other()}} to convert specified levels to other. }