From 4574e25786f03a0147104381da9151a0cc17b0bd Mon Sep 17 00:00:00 2001 From: olivroy <52606734+olivroy@users.noreply.github.com> Date: Thu, 15 Jun 2023 14:09:48 -0400 Subject: [PATCH] Remove the docs/ directory (#550) * Remove the docs/ directory (already deployed via GitHub pages) last updated 3 years ago. * Update index.Rmd Change reference to man/figures * Update reference to man/figures * revert previous change --- docs/404.html | 163 ------ docs/CONTRIBUTING.html | 208 -------- docs/LICENSE-text.html | 165 ------ docs/LICENSE.html | 169 ------- docs/NEWS.html | 363 -------------- docs/README.html | 329 ------------ docs/articles/index.html | 164 ------ docs/articles/introduction.html | 262 ---------- docs/articles/introduction.md | 167 ------- docs/articles/janitor.html | 390 --------------- docs/articles/janitor.md | 172 ------- docs/articles/tabyls.html | 454 ----------------- docs/articles/tabyls.md | 289 ----------- docs/authors.html | 182 ------- docs/bootstrap-toc.css | 60 --- docs/bootstrap-toc.js | 159 ------ docs/cran-comments.html | 165 ------ docs/docsearch.css | 148 ------ docs/docsearch.js | 85 ---- docs/index.html | 383 -------------- docs/issue_template.html | 179 ------- docs/jquery.sticky-kit.min.js | 9 - docs/link.svg | 12 - docs/news/index.html | 584 ---------------------- docs/pkgdown.css | 367 -------------- docs/pkgdown.js | 108 ---- docs/pkgdown.yml | 8 - docs/planning.html | 232 --------- docs/pull_request_template.html | 185 ------- docs/reference/add_totals_col.html | 184 ------- docs/reference/add_totals_row.html | 188 ------- docs/reference/adorn_col_title.html | 160 ------ docs/reference/adorn_crosstab.html | 207 -------- docs/reference/adorn_ns.html | 201 -------- docs/reference/adorn_pct_formatting.html | 210 -------- docs/reference/adorn_percentages.html | 207 -------- docs/reference/adorn_rounding.html | 222 -------- docs/reference/adorn_title.html | 210 -------- docs/reference/adorn_totals.html | 207 -------- docs/reference/as_tabyl.html | 241 --------- docs/reference/chisq.test.html | 216 -------- docs/reference/clean_names.html | 271 ---------- docs/reference/compare_df_cols.html | 244 --------- docs/reference/compare_df_cols_same.html | 211 -------- docs/reference/convert_to_NA.html | 190 ------- docs/reference/convert_to_date.html | 244 --------- docs/reference/crosstab.html | 177 ------- docs/reference/describe_class.html | 216 -------- docs/reference/excel_numeric_to_date.html | 243 --------- docs/reference/figures/dirty_data.PNG | Bin 80566 -> 0 bytes docs/reference/figures/logo_small.png | Bin 25011 -> 0 bytes docs/reference/fisher.test.html | 208 -------- docs/reference/get_dupes.html | 264 ---------- docs/reference/index.html | 382 -------------- docs/reference/janitor.html | 189 ------- docs/reference/janitor_deprecated.html | 182 ------- docs/reference/make_clean_names.html | 333 ------------ docs/reference/pipe.html | 180 ------- docs/reference/remove_constant.html | 204 -------- docs/reference/remove_empty.html | 203 -------- docs/reference/remove_empty_cols.html | 184 ------- docs/reference/remove_empty_rows.html | 184 ------- docs/reference/round_half_up.html | 186 ------- docs/reference/round_to_fraction.html | 218 -------- docs/reference/row_to_names.html | 201 -------- docs/reference/signif_half_up.html | 198 -------- docs/reference/tabyl.html | 256 ---------- docs/reference/top_levels.html | 193 ------- docs/reference/untabyl.html | 194 ------- docs/reference/use_first_valid_of.html | 190 ------- index.Rmd | 2 +- index.md | 2 +- 72 files changed, 2 insertions(+), 14561 deletions(-) delete mode 100644 docs/404.html delete mode 100644 docs/CONTRIBUTING.html delete mode 100644 docs/LICENSE-text.html delete mode 100644 docs/LICENSE.html delete mode 100644 docs/NEWS.html delete mode 100644 docs/README.html delete mode 100644 docs/articles/index.html delete mode 100644 docs/articles/introduction.html delete mode 100644 docs/articles/introduction.md delete mode 100644 docs/articles/janitor.html delete mode 100644 docs/articles/janitor.md delete mode 100644 docs/articles/tabyls.html delete mode 100644 docs/articles/tabyls.md delete mode 100644 docs/authors.html delete mode 100644 docs/bootstrap-toc.css delete mode 100644 docs/bootstrap-toc.js delete mode 100644 docs/cran-comments.html delete mode 100644 docs/docsearch.css delete mode 100644 docs/docsearch.js delete mode 100644 docs/index.html delete mode 100644 docs/issue_template.html delete mode 100644 docs/jquery.sticky-kit.min.js delete mode 100644 docs/link.svg delete mode 100644 docs/news/index.html delete mode 100644 docs/pkgdown.css delete mode 100644 docs/pkgdown.js delete mode 100644 docs/pkgdown.yml delete mode 100644 docs/planning.html delete mode 100644 docs/pull_request_template.html delete mode 100644 docs/reference/add_totals_col.html delete mode 100644 docs/reference/add_totals_row.html delete mode 100644 docs/reference/adorn_col_title.html delete mode 100644 docs/reference/adorn_crosstab.html delete mode 100644 docs/reference/adorn_ns.html delete mode 100644 docs/reference/adorn_pct_formatting.html delete mode 100644 docs/reference/adorn_percentages.html delete mode 100644 docs/reference/adorn_rounding.html delete mode 100644 docs/reference/adorn_title.html delete mode 100644 docs/reference/adorn_totals.html delete mode 100644 docs/reference/as_tabyl.html delete mode 100644 docs/reference/chisq.test.html delete mode 100644 docs/reference/clean_names.html delete mode 100644 docs/reference/compare_df_cols.html delete mode 100644 docs/reference/compare_df_cols_same.html delete mode 100644 docs/reference/convert_to_NA.html delete mode 100644 docs/reference/convert_to_date.html delete mode 100644 docs/reference/crosstab.html delete mode 100644 docs/reference/describe_class.html delete mode 100644 docs/reference/excel_numeric_to_date.html delete mode 100644 docs/reference/figures/dirty_data.PNG delete mode 100644 docs/reference/figures/logo_small.png delete mode 100644 docs/reference/fisher.test.html delete mode 100644 docs/reference/get_dupes.html delete mode 100644 docs/reference/index.html delete mode 100644 docs/reference/janitor.html delete mode 100644 docs/reference/janitor_deprecated.html delete mode 100644 docs/reference/make_clean_names.html delete mode 100644 docs/reference/pipe.html delete mode 100644 docs/reference/remove_constant.html delete mode 100644 docs/reference/remove_empty.html delete mode 100644 docs/reference/remove_empty_cols.html delete mode 100644 docs/reference/remove_empty_rows.html delete mode 100644 docs/reference/round_half_up.html delete mode 100644 docs/reference/round_to_fraction.html delete mode 100644 docs/reference/row_to_names.html delete mode 100644 docs/reference/signif_half_up.html delete mode 100644 docs/reference/tabyl.html delete mode 100644 docs/reference/top_levels.html delete mode 100644 docs/reference/untabyl.html delete mode 100644 docs/reference/use_first_valid_of.html diff --git a/docs/404.html b/docs/404.html deleted file mode 100644 index 7f43f6e3..00000000 --- a/docs/404.html +++ /dev/null @@ -1,163 +0,0 @@ - - - - - - - - -Page not found (404) • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - -
- -
-
- - -Content not found. Please use links in the navbar. - -
- - - -
- - - - -
- - - - - - - - diff --git a/docs/CONTRIBUTING.html b/docs/CONTRIBUTING.html deleted file mode 100644 index 51416e3d..00000000 --- a/docs/CONTRIBUTING.html +++ /dev/null @@ -1,208 +0,0 @@ - - - - - - - - -CONTRIBUTING • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - -
- -
-
- - -
- -
-

-Please contribute!

-

We love collaboration.

-
-
-

-Bugs? Feature requests?

- -
-
-

-Code contributions

-

I would prefer some discussion before an unsolicited code contribution, i.e., pull request. This ensures that your effort is not wasted and that we’re aligned on how to improve the janitor package.

-

This is especially true if your proposed contribution does not match a currently open issue. If that’s the case, please open new issue(s) to have the discussion there, prior to submitting code.

-

If your proposed contribution addresses multiple issues, it should ideally be broken into multiple pull requests. This will make it easier for me to review and approve.

-
-

-The mechanics of contributing:

-
    -
  • Fork this repo to your Github account
  • -
  • Clone your version on your account down to your machine from your account, e.g,. git clone https://github.com/<yourgithubusername>/janitor.git -
  • -
  • Make sure to track progress upstream (i.e., on our version of janitor at sfirke/janitor) by doing git remote add upstream https://github.com/sfirke/janitor.git. Before making changes make sure to pull changes in from upstream by doing either git fetch upstream then merge later or git pull upstream to fetch and merge in one step
  • -
  • Make your changes (bonus points for making changes on a new feature branch)
  • -
  • Push up to your account
  • -
  • Submit a pull request to the master branch at sfirke/janitor -
  • -
-
-
-
-

-Prefer to discuss over email?

-

Email Sam. His email address is in the DESCRIPTION file of this repo.

-
-
-

-Thanks for contributing!

-
-
- -
- - - -
- - - - -
- - - - - - - - diff --git a/docs/LICENSE-text.html b/docs/LICENSE-text.html deleted file mode 100644 index 230dd27b..00000000 --- a/docs/LICENSE-text.html +++ /dev/null @@ -1,165 +0,0 @@ - - - - - - - - -License • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - -
- -
-
- - -
YEAR: 2016
-COPYRIGHT HOLDER: Sam Firke
-
- -
- - - -
- - - - -
- - - - - - - - diff --git a/docs/LICENSE.html b/docs/LICENSE.html deleted file mode 100644 index 1a852081..00000000 --- a/docs/LICENSE.html +++ /dev/null @@ -1,169 +0,0 @@ - - - - - - - - -NA • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - -
- -
-
- - - -

The MIT License (MIT)

-

Copyright (c) 2016 Sam Firke

-

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

-

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

-

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

- - -
- - - -
- - - - -
- - - - - - - - diff --git a/docs/NEWS.html b/docs/NEWS.html deleted file mode 100644 index 3da8cbe6..00000000 --- a/docs/NEWS.html +++ /dev/null @@ -1,363 +0,0 @@ - - - - - - - - -C:/Users/SFirke/Documents/Bitbucket/janitor/NEWS.md • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - -
- -
-
- - - -
-

janitor 1.0.0 (2018-03-17)

-
-

Release summary

-

A stable version 1.0.0, with a new tabyl API and with breaking changes to the output of clean_names().

-

This preserves the original functionality of janitor, but significantly changes the implementation.

-
-
-

Breaking changes

-
-

A fully-overhauled tabyl -

-

This is now a single function tabyl() to count combinations of one, two, or three variables, ala base R’s table(). This replaces the crosstab() function. The resulting tabyl data.frames can be manipulated and formatted using a family of adorn_ functions. See the tabyls vignette for more.

-

The now-redundant legacy functions crosstab() and adorn_crosstab() have been deprecated, but remain in the package for now. Existing code that relies on tabyl will break if the sort argument is used, as that argument no longer exists in tabyl (use dplyr::arrange() instead).

-
-
-

Breaking improvements to clean_names -

-

clean_names() now detects and preserves camelCase inputs, allows multiple options for case outputs of the cleaned data.frame, and preserves whether there’s space between letters and numbers. It also transliterates accented letters and turns # into "number". This may cause old code to break. E.g., variableName as a raw column name is now converted to variable_name (or variableName, VariableName, etc. depending on your preference), where it would previously have been converted to variablename. To minimize this inconvenience, there’s a quick fix for compatibility: you can find-and-replace to insert the argument case = "old_janitor", preserving the old behavior of clean_names() as of janitor version 0.3.1 (and thus not have to redo your scripts beyond that.)

-
-
-
-

Major Features

-
    -
  • clean_names() transliterates accented letters, e.g., çãüœ becomes cauoe (#120). Thanks to @fernandovmacedo.

  • -
  • -clean_names() offers multiple options for variable name styling. In addition to snake_case output you can select smallCamelCase, BigCamelCase, ALL_CAPS and others. (#131). -
      -
    • Thanks to @tazinho, who wrote the snakecase package that janitor depends on to do this, as well as the patch to incorporate it into clean_names(). Thanks also to @maelle for proposing this feature. jani
    • -
    -
  • -
  • Launched the janitor documentation website: http://sfirke.github.io/janitor. Thanks to the pkgdown package!

  • -
  • Deprecated the functions remove_empty_rows() and remove_empty_cols(), which are replaced by the single function remove_empty(). (#100) - -
  • -
  • The new adorn_title() function shows the name of the 2nd tabyl variable (column name) - this un-tidies the data.frame but makes the result clearer to readers (#77)

  • -
-
-
-

Minor Features

- -
-
-

Bug fixes

- -
-
-
-
-

janitor 0.3.1 (2018-01-04)

-
-

Release summary

-

This is a bug-fix release with no new functionality or changes. It fixes a bug where adorn_crosstab() failed if the tibble package was version > 1.4.

-

Major changes to janitor are currently in development on GitHub and will be released soon. This is not that next big release.

-
-
-
-
-

janitor 0.3.0 (2017-05-06)

-
-

Release summary

-

The primary purpose of this release is to maintain accuracy given breaking changes to the dplyr package, upon which janitor is built, in dplyr version >0.6.0. This update also contains a number of minor improvements.

-

Critical: if you update the package dplyr to version >0.6.0, you must update janitor to version 0.3.0 to ensure accurate results from janitor’s tabyl() function. This is due to a change in the behavior of dplyr’s _join functions (discussed in #111).

-

janitor 0.3.0 is compatible with this new version of dplyr as well as old versions of dplyr back to 0.5.0. That is, updating janitor to 0.3.0 does not necessitate an update to dplyr >0.6.0.

-
-
-

Breaking changes

-
    -
  • The functions add_totals_row and add_totals_col were combined into a single function, adorn_totals(). (#57). The add_totals_ functions are now deprecated and should not be used.
  • -
  • The first argument of adorn_crosstab() is now “dat” instead of “crosstab” (indicating that the function can be called on any data.frame, not just a result of crosstab())
  • -
-
-
-

Major Features

-
    -
  • Exported the %>% pipe from magrittr (#107).
  • -
-

Deprecated the following functions:

- -
-
-

Minor Features

-
    -
  • -adorn_totals() and ns_to_percents() can now be called on data.frames that have non-numeric columns beyond the first one (those columns will be ignored) (#57) -
  • -
  • -adorn_totals("col") retains factor class in 1st column if 1st column in the input data.frame was a factor
  • -
-
-
-

Bug fixes

- -
-
-
-
-

janitor 0.2.1 (2016-10-30)

-
-

Bug fixes

- -
-
-
-
-

janitor 0.2.0 (2016-10-03)

-
-

Features

-
-

Major

-

Submitted to CRAN!

-
-
-

Minor

-
    -
  • The count in tabyl() for factor levels that aren’t present is now 0 instead of NA (#48) -
  • -
-
-
-
-

Bug fixes

-
    -
  • Can call tabyl() on the result of a tabyl(), e.g., mtcars %>% tabyl(mpg) %>% tabyl(n) (#54) -
  • -
  • -get_dupes() now works on variables with spaces in column names (#62) -
  • -
-
-
-

Package management

-
    -
  • Reached 100% unit test code coverage
  • -
-
-
-
-
-

janitor 0.1.2

-
-

Features

-
-

Major

-
    -
  • Added a function adorn_crosstab() that formats the results of a crosstab() for pretty printing. Shows % and N in the same cell, with the % symbol, user-specified rounding (method and number of digits), and the option to include a totals row and/or column. E.g., mtcars %>% crosstab(cyl, gear) %>% adorn_crosstab().
  • -
  • -crosstab() can be called in a %>% pipeline, e.g., mtcars %>% crosstab(cyl, gear). Thanks to @chrishaid (#34) -
  • -
  • -tabyl() can also be called in a %>% pipeline, e.g., mtcars %>% tabyl(cyl) (#35) -
  • -
  • Added use_first_valid_of() function (#32) -
  • -
  • Added minor functions for manipulating numeric data.frames for presentation: ns_to_percents(), add_totals_row(), add_totals_col(),
  • -
-
-
-

Minor

-
    -
  • -crosstab() returns 0 instead of NA when there are no instances of a variable combination.
  • -
  • A call like tabyl(df$vecname) retains the more-descriptive $ symbol in the column name of the result - if you want a legal R name in the result, call it as df %>% tabyl(vecname) -
  • -
  • Single and double quotation marks are handled by clean_names() -
  • -
-
-
-
-

Package management

-
    -
  • Added codecov to measure test coverage
  • -
  • Added unit test coverage
  • -
  • Added Travis-CI for continuous integration
  • -
-
-
-
-
-

janitor 0.1 (2016-04-17)

-
    -
  • Initial draft of skeleton package on GitHub
  • -
-
- - -
- -
- - - -
- - - - diff --git a/docs/README.html b/docs/README.html deleted file mode 100644 index 66557795..00000000 --- a/docs/README.html +++ /dev/null @@ -1,329 +0,0 @@ - - - - - - - - -C:/Users/SFirke/Documents/Bitbucket/janitor/README.md • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - -
- -
-
- - - -
-

Data scientists, according to interviews and expert estimates, spend from 50 percent to 80 percent of their time mired in this more mundane labor of collecting and preparing unruly digital data, before it can be explored for useful nuggets.

-

For Big-Data Scientists, ‘Janitor Work’ Is Key Hurdle to Insight” - The New York Times, 2014

-
-
-

janitor -

-
-

Travis-CI Build Status Coverage Status lifecycle CRAN_Status_Badge !Monthly Downloads!Downloads

-

janitor has simple functions for examining and cleaning dirty data. It was built with beginning and intermediate R users in mind and is optimized for user-friendliness. Advanced R users can already do everything covered here, but with janitor they can do it faster and save their thinking for the fun stuff.

-

The main janitor functions:

-
    -
  • perfectly format data.frame column names;
  • -
  • create and format frequency tables of one, two, or three variables - think an improved table(); and
  • -
  • isolate partially-duplicate records.
  • -
-

The tabulate-and-report functions approximate popular features of SPSS and Microsoft Excel.

-

janitor is a #tidyverse-oriented package. Specifically, it plays nicely with the %>% pipe and is optimized for cleaning data brought in with the readr and readxl packages.

-
-

Installation

-

You can install:

- -
-
-

Using janitor

-

Below are quick examples of how janitor tools are commonly used. A full description of each function can be found in janitor’s catalog of functions vignette.

-
-

Cleaning dirty data

-

Take this roster of teachers at a fictional American high school, stored in the Microsoft Excel file dirty_data.xlsx: All kinds of dirty.

-

Dirtiness includes:

-
    -
  • Dreadful column names
  • -
  • Rows and columns containing Excel formatting but no data
  • -
  • Dates stored as numbers
  • -
  • Values spread inconsistently over the “Certification” columns
  • -
-

Here’s that data after being read in to R:

- -

Excel formatting led to an untitled empty column and 5 empty rows at the bottom of the table (only 12 records have any actual data). Bad column names are preserved.

-

Clean it with janitor functions:

- -

The core janitor cleaning function is clean_names() - call it whenever you load data into R.

-
-
-

Examining dirty data

- -
-

Tabulating tools

-

A variable (or combinations of two or three variables) can be tabulated with tabyl(). The resulting data.frame can be tweaked and formatted with the suite of adorn_ functions for quick analysis and printing of pretty results in a report. adorn_ functions can be helpful with non-tabyls, too.

-

tabyl can be called two ways:

-
    -
  • On a vector, when tabulating a single variable - e.g., tabyl(roster$subject) -
  • -
  • On a data.frame, specifying 1, 2, or 3 variable names to tabulate : roster %>% tabyl(subject, employee_status). -
      -
    • Here the data.frame is passed in with the %>% pipe; this allows for dplyr commands earlier in the pipeline
    • -
    -
  • -
-
-
-

tabyl()

-

Like table(), but pipe-able, data.frame-based, and fully featured.

-

One variable:

- -

Two variables:

- -

Three variables:

- -
-
Adorning tabyls
-

The suite of adorn_ functions dress up the results of these tabulation calls for fast, basic reporting. Here are some of the functions that augment a summary table for reporting:

- -

Pipe that right into knitr::kable() in your RMarkdown report!

-

These modular adornments can be layered to reduce R’s deficit against Excel and SPSS when it comes to quick, informative counts.

-
-
-
-
-
-

Contact me

-

You are welcome to:

- -
-
- - -
- -
- - - -
- - - - diff --git a/docs/articles/index.html b/docs/articles/index.html deleted file mode 100644 index 99b4e816..00000000 --- a/docs/articles/index.html +++ /dev/null @@ -1,164 +0,0 @@ - - - - - - - - -Articles • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - -
- -
-
- - - -
-
- - - -
- - - - - - - - diff --git a/docs/articles/introduction.html b/docs/articles/introduction.html deleted file mode 100644 index 77c99324..00000000 --- a/docs/articles/introduction.html +++ /dev/null @@ -1,262 +0,0 @@ - - - - - - - -Catalog of janitor functions • janitor - - - - - - -
-
- - - -
-
- - - - -
-

The janitor functions expedite the initial data exploration and cleaning that comes with any new data set. This catalog describes the usage for each function.

-
-

-Major functions

-

Functions for everyday use.

-
-

-Cleaning

-
-

-Clean data.frame names with clean_names() -

-

Call this function every time you read data.

-

It works in a %>% pipeline, and handles problematic variable names, especially those that are so well preserved by readxl::read_excel() and readr::read_csv().

-
    -
  • Returns names with only lowercase letters, with _ as a separator
  • -
  • Handles special characters and spaces
  • -
  • Appends numbers to duplicated names
  • -
  • Converts “%” to “percent” to retain meaning
  • -
-
# Load dplyr for the %>% pipe
-library(dplyr)
-# Create a data.frame with dirty names
-test_df <- as.data.frame(matrix(ncol = 6))
-names(test_df) <- c("hIgHlo", "REPEAT VALUE", "REPEAT VALUE",
-                    "% successful (2009)",  "abc@!*", "")
-

Clean the variable names, returning a data.frame:

-
test_df %>%
-  clean_names()
-#>   h_ig_hlo repeat_value repeat_value_2 percent_successful_2009 abc  x
-#> 1       NA           NA             NA                      NA  NA NA
-

Compare to what base R produces:

-
make.names(names(test_df))
-#> [1] "hIgHlo"               "REPEAT.VALUE"         "REPEAT.VALUE"        
-#> [4] "X..successful..2009." "abc..."               "X"
-
-
-
-

-Exploring

-
-

-tabyl() - a better version of table() -

-

tabyl() is a tidyverse-oriented replacement for table(). It counts combinations of one, two, or three variables, and then can be formatted with a suite of adorn_* functions to look just how you want. For instance:

-
mtcars %>%
-  tabyl(gear, cyl) %>%
-  adorn_totals("col") %>%
-  adorn_percentages("row") %>%
-  adorn_pct_formatting(digits = 2) %>%
-  adorn_ns()
-#>  gear          4          6           8        Total
-#>     3  6.67% (1) 13.33% (2) 80.00% (12) 100.00% (15)
-#>     4 66.67% (8) 33.33% (4)  0.00%  (0) 100.00% (12)
-#>     5 40.00% (2) 20.00% (1) 40.00%  (2) 100.00%  (5)
-

Learn more in the tabyls vignette.

-
-
-

-Explore records with duplicated values for specific combinations of variables with get_dupes() -

-

This is for hunting down and examining duplicate records during data cleaning - usually when there shouldn’t be any.

-

For example, in a tidy data frame you might expect to have a unique ID repeated for each year, and year repeated for each unique ID, but no duplicated pairs of unique ID & year. Say you want to check for their presence, and study any such duplicated records.

-

get_dupes() returns the records (and inserts a count of duplicates) so you can sleuth out the problematic cases:

-
get_dupes(mtcars, wt, cyl) # or mtcars %>% get_dupes(wt, cyl) if you prefer to pipe
-#> # A tibble: 4 x 12
-#>      wt   cyl dupe_…   mpg  disp    hp  drat  qsec    vs    am  gear  carb
-#>   <dbl> <dbl>  <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
-#> 1  3.44  6.00      2  19.2   168   123  3.92  18.3  1.00  0     4.00  4.00
-#> 2  3.44  6.00      2  17.8   168   123  3.92  18.9  1.00  0     4.00  4.00
-#> 3  3.57  8.00      2  14.3   360   245  3.21  15.8  0     0     3.00  4.00
-#> 4  3.57  8.00      2  15.0   301   335  3.54  14.6  0     1.00  5.00  8.00
-
-
-
-
-

-Minor functions

-

Smaller functions for use in particular situations. More human-readable than the equivalent code they replace.

-
-

-Cleaning

-
-

-Fix dates stored as serial numbers with excel_numeric_to_date() -

-

Ever load data from Excel and see a value like 42223 where a date should be? This function converts those serial numbers to class Date, and contains an option for specifying the alternate date system for files created with Excel for Mac 2008 and earlier versions (which count from a different starting point).

-
excel_numeric_to_date(41103)
-#> [1] "2012-07-13"
-excel_numeric_to_date(41103, date_system = "mac pre-2011")
-#> [1] "2016-07-14"
-
-
-

-remove_empty_cols() and remove_empty_rows() -

-

One-line wrapper functions that do what they say. For cases like cleaning Excel files containing empty rows and columns.

-
q <- data.frame(v1 = c(1, NA, 3),
-                v2 = c(NA, NA, NA),
-                v3 = c("a", NA, "b"))
-q %>%
-  remove_empty_cols() %>%
-  remove_empty_rows()
-#>   v1 v3
-#> 1  1  a
-#> 3  3  b
-
-
-
-

-Exploring

-
-

-Count factor levels in groups of high, medium, and low with top_levels() -

-

Originally designed for use with Likert survey data stored as factors. Returns a tbl_df frequency table with appropriately-named rows, grouped into head/middle/tail groups.

-
    -
  • Takes a user-specified size for the head/tail groups
  • -
  • Automatically calculates a percent column
  • -
  • Supports sorting
  • -
  • Can show or hide NA values.
  • -
-
f <- factor(c("strongly agree", "agree", "neutral", "neutral", "disagree", "strongly agree"),
-            levels = c("strongly agree", "agree", "neutral", "disagree", "strongly disagree"))
-top_levels(f)
-#>                            f n   percent
-#>        strongly agree, agree 3 0.5000000
-#>                      neutral 2 0.3333333
-#>  disagree, strongly disagree 1 0.1666667
-top_levels(f, n = 1)
-#>                         f n   percent
-#>            strongly agree 2 0.3333333
-#>  agree, neutral, disagree 4 0.6666667
-#>         strongly disagree 0 0.0000000
-
-
-
-
-
- - - -
- - - -
- - - diff --git a/docs/articles/introduction.md b/docs/articles/introduction.md deleted file mode 100644 index adca2506..00000000 --- a/docs/articles/introduction.md +++ /dev/null @@ -1,167 +0,0 @@ -Catalog of janitor functions -================ -2017-11-16 - -- [Major functions](#major-functions) - - [Cleaning](#cleaning) - - [Clean data.frame names with `clean_names()`](#clean-data.frame-names-with-clean_names) - - [Exploring](#exploring) - - [`tabyl()` - a better version of `table()`](#tabyl---a-better-version-of-table) - - [Explore records with duplicated values for specific combinations of variables with `get_dupes()`](#explore-records-with-duplicated-values-for-specific-combinations-of-variables-with-get_dupes) -- [Minor functions](#minor-functions) - - [Cleaning](#cleaning-1) - - [Fix dates stored as serial numbers with `excel_numeric_to_date()`](#fix-dates-stored-as-serial-numbers-with-excel_numeric_to_date) - - [`remove_empty_cols()` and `remove_empty_rows()`](#remove_empty_cols-and-remove_empty_rows) - - [Exploring](#exploring-1) - - [Count factor levels in groups of high, medium, and low with `top_levels()`](#count-factor-levels-in-groups-of-high-medium-and-low-with-top_levels) - -The janitor functions expedite the initial data exploration and cleaning that comes with any new data set. This catalog describes the usage for each function. - -Major functions -=============== - -Functions for everyday use. - -Cleaning --------- - -### Clean data.frame names with `clean_names()` - -Call this function every time you read data. - -It works in a `%>%` pipeline, and handles problematic variable names, especially those that are so well preserved by `readxl::read_excel()` and `readr::read_csv()`. - -- Returns names with only lowercase letters, with `_` as a separator -- Handles special characters and spaces -- Appends numbers to duplicated names -- Converts "%" to "percent" to retain meaning - -``` r -# Load dplyr for the %>% pipe -library(dplyr) -# Create a data.frame with dirty names -test_df <- as.data.frame(matrix(ncol = 6)) -names(test_df) <- c("hIgHlo", "REPEAT VALUE", "REPEAT VALUE", - "% successful (2009)", "abc@!*", "") -``` - -Clean the variable names, returning a data.frame: - -``` r -test_df %>% - clean_names() -#> h_ig_hlo repeat_value repeat_value_2 percent_successful_2009 abc x -#> 1 NA NA NA NA NA NA -``` - -Compare to what base R produces: - -``` r -make.names(names(test_df)) -#> [1] "hIgHlo" "REPEAT.VALUE" "REPEAT.VALUE" -#> [4] "X..successful..2009." "abc..." "X" -``` - -Exploring ---------- - -### `tabyl()` - a better version of `table()` - -`tabyl()` is a tidyverse-oriented replacement for `table()`. It counts combinations of one, two, or three variables, and then can be formatted with a suite of `adorn_*` functions to look just how you want. For instance: - -``` r -mtcars %>% - tabyl(gear, cyl) %>% - adorn_totals("col") %>% - adorn_percentages("row") %>% - adorn_pct_formatting(digits = 2) %>% - adorn_ns() -#> gear 4 6 8 Total -#> 1 3 6.67% (1) 13.33% (2) 80.00% (12) 100.00% (15) -#> 2 4 66.67% (8) 33.33% (4) 0.00% (0) 100.00% (12) -#> 3 5 40.00% (2) 20.00% (1) 40.00% (2) 100.00% (5) -``` - -Learn more in the [tabyls vignette](https://github.com/sfirke/janitor/blob/master/vignettes/tabyls.md). - -### Explore records with duplicated values for specific combinations of variables with `get_dupes()` - -This is for hunting down and examining duplicate records during data cleaning - usually when there shouldn't be any. - -For example, in a tidy data frame you might expect to have a unique ID repeated for each year, and year repeated for each unique ID, but no duplicated pairs of unique ID & year. Say you want to check for their presence, and study any such duplicated records. - -`get_dupes()` returns the records (and inserts a count of duplicates) so you can sleuth out the problematic cases: - -``` r -get_dupes(mtcars, wt, cyl) # or mtcars %>% get_dupes(wt, cyl) if you prefer to pipe -#> # A tibble: 4 x 12 -#> wt cyl dupe_count mpg disp hp drat qsec vs am gear -#> -#> 1 3.44 6 2 19.2 167.6 123 3.92 18.30 1 0 4 -#> 2 3.44 6 2 17.8 167.6 123 3.92 18.90 1 0 4 -#> 3 3.57 8 2 14.3 360.0 245 3.21 15.84 0 0 3 -#> 4 3.57 8 2 15.0 301.0 335 3.54 14.60 0 1 5 -#> # ... with 1 more variables: carb -``` - -Minor functions -=============== - -Smaller functions for use in particular situations. More human-readable than the equivalent code they replace. - -Cleaning --------- - -### Fix dates stored as serial numbers with `excel_numeric_to_date()` - -Ever load data from Excel and see a value like `42223` where a date should be? This function converts those serial numbers to class `Date`, and contains an option for specifying the alternate date system for files created with Excel for Mac 2008 and earlier versions (which count from a different starting point). - -``` r -excel_numeric_to_date(41103) -#> [1] "2012-07-13" -excel_numeric_to_date(41103, date_system = "mac pre-2011") -#> [1] "2016-07-14" -``` - -### `remove_empty_cols()` and `remove_empty_rows()` - -One-line wrapper functions that do what they say. For cases like cleaning Excel files containing empty rows and columns. - -``` r -q <- data.frame(v1 = c(1, NA, 3), - v2 = c(NA, NA, NA), - v3 = c("a", NA, "b")) -q %>% - remove_empty_cols() %>% - remove_empty_rows() -#> v1 v3 -#> 1 1 a -#> 3 3 b -``` - -Exploring ---------- - -### Count factor levels in groups of high, medium, and low with `top_levels()` - -Originally designed for use with Likert survey data stored as factors. Returns a `tbl_df` frequency table with appropriately-named rows, grouped into head/middle/tail groups. - -- Takes a user-specified size for the head/tail groups -- Automatically calculates a percent column -- Supports sorting -- Can show or hide `NA` values. - -``` r -f <- factor(c("strongly agree", "agree", "neutral", "neutral", "disagree", "strongly agree"), - levels = c("strongly agree", "agree", "neutral", "disagree", "strongly disagree")) -top_levels(f) -#> f n percent -#> 1 strongly agree, agree 3 0.5000000 -#> 2 neutral 2 0.3333333 -#> 3 disagree, strongly disagree 1 0.1666667 -top_levels(f, n = 1) -#> f n percent -#> 1 strongly agree 2 0.3333333 -#> 2 agree, neutral, disagree 4 0.6666667 -#> 3 strongly disagree 0 0.0000000 -``` diff --git a/docs/articles/janitor.html b/docs/articles/janitor.html deleted file mode 100644 index be8ea587..00000000 --- a/docs/articles/janitor.html +++ /dev/null @@ -1,390 +0,0 @@ - - - - - - - -Overview of janitor functions • janitor - - - - - - - - - - -
-
- - - - -
-
- - - - -

The janitor functions expedite the initial data exploration and cleaning that comes with any new data set. This catalog describes the usage for each function.

-
-

-Major functions

-

Functions for everyday use.

-
-

-Cleaning

-
-

-Clean data.frame names with clean_names() -

-

Call this function every time you read data.

-

It works in a %>% pipeline, and handles problematic variable names, especially those that are so well-preserved by readxl::read_excel() and readr::read_csv().

-
    -
  • Parses letter cases and separators to a consistent format. -
      -
    • Default is to snake_case, but other cases like camelCase are available
    • -
    -
  • -
  • Handles special characters and spaces, including transliterating characters like œ to oe.
  • -
  • Appends numbers to duplicated names
  • -
  • Converts “%” to “percent” and “#” to “number” to retain meaning
  • -
  • Spacing (or lack thereof) around numbers is preserved
  • -
-
# Create a data.frame with dirty names
-test_df <- as.data.frame(matrix(ncol = 6))
-names(test_df) <- c("firstName", "ábc@!*", "% successful (2009)",
-                    "REPEAT VALUE", "REPEAT VALUE", "")
-

Clean the variable names, returning a data.frame:

-
test_df %>%
-  clean_names()
-#>   first_name abc percent_successful_2009 repeat_value repeat_value_2  x
-#> 1         NA  NA                      NA           NA             NA NA
-

Compare to what base R produces:

-
make.names(names(test_df))
-#> [1] "firstName"            "ábc..."               "X..successful..2009."
-#> [4] "REPEAT.VALUE"         "REPEAT.VALUE"         "X"
-

This function is powered by the underlying exported function make_clean_names(), which accepts and returns a character vector of names (see below). This allows for cleaning the names of any object, not just a data.frame. clean_names() is retained for its convenience in piped workflows, and can be called on an sf simple features object or a tbl_graph tidygraph object in addition to a data.frame.

-
-
-

-Do those data.frames actually contain the same columns?

-
-

-Check with compare_df_cols() -

-

For cases when you are given a set of data files that should be identical, and you wish to read and combine them for analysis. But then dplyr::bind_rows() or rbind() fails, because of different columns or because the column classes don’t match across data.frames.

-

compare_df_cols() takes unquoted names of data.frames / tibbles, or a list of data.frames, and returns a summary of how they compare. See what the column types are, which are missing or present in the different inputs, and how column types differ.

-
df1 <- data.frame(a = 1:2, b = c("big", "small")) # a factor by default
-df2 <- data.frame(a = 10:12, b = c("medium", "small", "big"), c = 0, stringsAsFactors = FALSE)
-df3 <- df1 %>%
-  dplyr::mutate(b = as.character(b))
-
-compare_df_cols(df1, df2, df3)
-#>   column_name     df1       df2       df3
-#> 1           a integer   integer   integer
-#> 2           b  factor character character
-#> 3           c    <NA>   numeric      <NA>
-
-compare_df_cols(df1, df2, df3, return = "mismatch")
-#>   column_name    df1       df2       df3
-#> 1           b factor character character
-compare_df_cols(df1, df2, df3, return = "mismatch", bind_method = "rbind") # default is dplyr::bind_rows
-#>   column_name    df1       df2       df3
-#> 1           b factor character character
-#> 2           c   <NA>   numeric      <NA>
-

compare_df_cols_same() returns TRUE or FALSE indicating if the data.frames can be successfully row-bound with the given binding method:

-
compare_df_cols_same(df1, df3)
-#>   column_name    ..1       ..2
-#> 1           b factor character
-#> [1] FALSE
-compare_df_cols_same(df2, df3)
-#> [1] TRUE
-
-
-
-
-

-Exploring

-
-

-tabyl() - a better version of table() -

-

tabyl() is a tidyverse-oriented replacement for table(). It counts combinations of one, two, or three variables, and then can be formatted with a suite of adorn_* functions to look just how you want. For instance:

-
mtcars %>%
-  tabyl(gear, cyl) %>%
-  adorn_totals("col") %>%
-  adorn_percentages("row") %>%
-  adorn_pct_formatting(digits = 2) %>%
-  adorn_ns() %>%
-  adorn_title()
-#>              cyl                                    
-#>  gear          4          6           8        Total
-#>     3  6.67% (1) 13.33% (2) 80.00% (12) 100.00% (15)
-#>     4 66.67% (8) 33.33% (4)  0.00%  (0) 100.00% (12)
-#>     5 40.00% (2) 20.00% (1) 40.00%  (2) 100.00%  (5)
-

Learn more in the tabyls vignette.

-
-
-

-Explore records with duplicated values for specific combinations of variables with get_dupes() -

-

This is for hunting down and examining duplicate records during data cleaning - usually when there shouldn’t be any.

-

For example, in a tidy data.frame you might expect to have a unique ID repeated for each year, but no duplicated pairs of unique ID & year. Say you want to check for and study any such duplicated records.

-

get_dupes() returns the records (and inserts a count of duplicates) so you can examine the problematic cases:

-
get_dupes(mtcars, wt, cyl) # or mtcars %>% get_dupes(wt, cyl) if you prefer to pipe
-#>                 wt cyl dupe_count  mpg  disp  hp drat  qsec vs am gear
-#> Merc 280      3.44   6          2 19.2 167.6 123 3.92 18.30  1  0    4
-#> Merc 280C     3.44   6          2 17.8 167.6 123 3.92 18.90  1  0    4
-#> Duster 360    3.57   8          2 14.3 360.0 245 3.21 15.84  0  0    3
-#> Maserati Bora 3.57   8          2 15.0 301.0 335 3.54 14.60  0  1    5
-#>               carb
-#> Merc 280         4
-#> Merc 280C        4
-#> Duster 360       4
-#> Maserati Bora    8
-
-
-
-
-

-Minor functions

-

Smaller functions for use in particular situations. More human-readable than the equivalent code they replace.

-
-

-Cleaning

-
-

-Manipulate vectors of names with make_clean_names() -

-

Like base R’s make.names(), but with the stylings and case choice of the long-time janitor function clean_names(). While clean_names() is still offered for use in data.frame pipeline with %>%, make_clean_names() allows for more general usage, e.g., on a vector.

-

It can also be used as an argument to .name_repair in the newest version of tibble::as_tibble:

-
tibble::as_tibble(iris, .name_repair = janitor::make_clean_names)
-#> New names:
-#> * Sepal.Length -> sepal_length
-#> * Sepal.Width -> sepal_width
-#> * Petal.Length -> petal_length
-#> * Petal.Width -> petal_width
-#> * Species -> species
-#> # A tibble: 150 x 5
-#>    sepal_length sepal_width petal_length petal_width species
-#>           <dbl>       <dbl>        <dbl>       <dbl> <fct>  
-#>  1          5.1         3.5          1.4         0.2 setosa 
-#>  2          4.9         3            1.4         0.2 setosa 
-#>  3          4.7         3.2          1.3         0.2 setosa 
-#>  4          4.6         3.1          1.5         0.2 setosa 
-#>  5          5           3.6          1.4         0.2 setosa 
-#>  6          5.4         3.9          1.7         0.4 setosa 
-#>  7          4.6         3.4          1.4         0.3 setosa 
-#>  8          5           3.4          1.5         0.2 setosa 
-#>  9          4.4         2.9          1.4         0.2 setosa 
-#> 10          4.9         3.1          1.5         0.1 setosa 
-#> # … with 140 more rows
-
-
-

-remove_empty() rows and columns

-

Does what it says. For cases like cleaning Excel files that contain empty rows and columns after being read into R.

-
q <- data.frame(v1 = c(1, NA, 3),
-                v2 = c(NA, NA, NA),
-                v3 = c("a", NA, "b"))
-q %>%
-  remove_empty(c("rows", "cols"))
-#>   v1 v3
-#> 1  1  a
-#> 3  3  b
-

Just a simple wrapper for one-line functions, but it saves a little thinking for both the code writer and the reader.

-
-
-

-remove_constant() columns

-

Drops columns from a data.frame that contain only a single constant value (with an na.rm option to control whether NAs should be considered as different values from the constant).

-

remove_constant and remove_empty work on matrices as well as data.frames.

-
a <- data.frame(good = 1:3, boring = "the same")
-a %>% remove_constant()
-#>   good
-#> 1    1
-#> 2    2
-#> 3    3
-
-
-

-Directionally-consistent rounding behavior with round_half_up() -

-

R uses “banker’s rounding”, i.e., halves are rounded to the nearest even number. This function, an exact implementation of https://stackoverflow.com/questions/12688717/round-up-from-5/12688836#12688836, will round all halves up. Compare:

-
nums <- c(2.5, 3.5)
-round(nums)
-#> [1] 2 4
-round_half_up(nums)
-#> [1] 3 4
-
-
-

-Round decimals to precise fractions of a given denominator with round_to_fraction() -

-

Say your data should only have values of quarters: 0, 0.25, 0.5, 0.75, 1, etc. But there are either user-entered bad values like 0.2 or floating-point precision problems like 0.25000000001. round_to_fraction() will enforce the desired fractional distribution by rounding the values to the nearest value given the specified denominator.

-

There’s also a digits argument for optional subsequent rounding.

-
-
-

-Fix dates stored as serial numbers with excel_numeric_to_date() -

-

Ever load data from Excel and see a value like 42223 where a date should be? This function converts those serial numbers to class Date, with options for different Excel date encoding systems, preserving fractions of a date as time (in which case the returned value is of class POSIXlt), and specifying a time zone.

-
excel_numeric_to_date(41103)
-#> [1] "2012-07-13"
-excel_numeric_to_date(41103.01) # ignores decimal places, returns Date object
-#> [1] "2012-07-13"
-excel_numeric_to_date(41103.01, include_time = TRUE) # returns POSIXlt object
-#> [1] "2012-07-13 01:14:24 EDT"
-excel_numeric_to_date(41103.01, date_system = "mac pre-2011")
-#> [1] "2016-07-14"
-
-
-

-Convert a mix of date and datetime formats to date

-

Building on excel_numeric_to_date(), the new functions convert_to_date() and convert_to_datetime() are more robust to a mix of inputs. Handy when reading many spreadsheets that should have the same column formats, but don’t.

-

For instance, here a vector with a date and an Excel datetime sees both values successfully converted to Date class:

-
convert_to_date(c("2020-02-29", "40000.1"))
-#> [1] "2020-02-29" "2009-07-06"
-
-
-

-Elevate column names stored in a data.frame row

-

If a data.frame has the intended variable names stored in one of its rows, row_to_names will elevate the specified row to become the names of the data.frame and optionally (by default) remove the row in which names were stored and/or the rows above it.

-
dirt <- data.frame(X_1 = c(NA, "ID", 1:3),
-           X_2 = c(NA, "Value", 4:6))
-
-row_to_names(dirt, 2)
-#>   ID Value
-#> 3  1     4
-#> 4  2     5
-#> 5  3     6
-
-
-
-

-Exploring

-
-

-Count factor levels in groups of high, medium, and low with top_levels() -

-

Originally designed for use with Likert survey data stored as factors. Returns a tbl_df frequency table with appropriately-named rows, grouped into head/middle/tail groups.

-
    -
  • Takes a user-specified size for the head/tail groups
  • -
  • Automatically calculates a percent column
  • -
  • Supports sorting
  • -
  • Can show or hide NA values.
  • -
-
f <- factor(c("strongly agree", "agree", "neutral", "neutral", "disagree", "strongly agree"),
-            levels = c("strongly agree", "agree", "neutral", "disagree", "strongly disagree"))
-top_levels(f)
-#>                            f n   percent
-#>        strongly agree, agree 3 0.5000000
-#>                      neutral 2 0.3333333
-#>  disagree, strongly disagree 1 0.1666667
-top_levels(f, n = 1)
-#>                         f n   percent
-#>            strongly agree 2 0.3333333
-#>  agree, neutral, disagree 4 0.6666667
-#>         strongly disagree 0 0.0000000
-
-
-
-
- - - -
- - - -
- -
-

Site built with pkgdown 1.5.0.

-
- -
-
- - - - - - diff --git a/docs/articles/janitor.md b/docs/articles/janitor.md deleted file mode 100644 index 84b3079b..00000000 --- a/docs/articles/janitor.md +++ /dev/null @@ -1,172 +0,0 @@ -Overview of janitor functions -================ -2018-03-03 - -- [Major functions](#major-functions) - - [Cleaning](#cleaning) - - [Clean data.frame names with `clean_names()`](#clean-data.frame-names-with-clean_names) - - [Exploring](#exploring) - - [`tabyl()` - a better version of `table()`](#tabyl---a-better-version-of-table) - - [Explore records with duplicated values for specific combinations of variables with `get_dupes()`](#explore-records-with-duplicated-values-for-specific-combinations-of-variables-with-get_dupes) -- [Minor functions](#minor-functions) - - [Cleaning](#cleaning-1) - - [Fix dates stored as serial numbers with `excel_numeric_to_date()`](#fix-dates-stored-as-serial-numbers-with-excel_numeric_to_date) - - [`remove_empty()` rows and columns](#remove_empty-rows-and-columns) - - [Exploring](#exploring-1) - - [Count factor levels in groups of high, medium, and low with `top_levels()`](#count-factor-levels-in-groups-of-high-medium-and-low-with-top_levels) - -The janitor functions expedite the initial data exploration and cleaning that comes with any new data set. This catalog describes the usage for each function. - -Major functions -=============== - -Functions for everyday use. - -Cleaning --------- - -### Clean data.frame names with `clean_names()` - -Call this function every time you read data. - -It works in a `%>%` pipeline, and handles problematic variable names, especially those that are so well preserved by `readxl::read_excel()` and `readr::read_csv()`. - -- Parses letter cases and separators to a consistent format. - - Default is to snake\_case, but other cases like camelCase are available -- Handles special characters and spaces, including transilerating characters like `œ` to `oe`. -- Appends numbers to duplicated names -- Converts "%" to "percent" and "\#" to "number" to retain meaning -- Spacing (or lack of) around numbers is preserved - -``` r -# Load dplyr for the %>% pipe -library(dplyr) -# Create a data.frame with dirty names -test_df <- as.data.frame(matrix(ncol = 6)) -names(test_df) <- c("hIgHlo", "REPEAT VALUE", "REPEAT VALUE", - "% successful (2009)", "abc@!*", "") -``` - -Clean the variable names, returning a data.frame: - -``` r -test_df %>% - clean_names() -#> h_ig_hlo repeat_value repeat_value_2 percent_successful_2009 abc x -#> 1 NA NA NA NA NA NA -``` - -Compare to what base R produces: - -``` r -make.names(names(test_df)) -#> [1] "hIgHlo" "REPEAT.VALUE" "REPEAT.VALUE" -#> [4] "X..successful..2009." "abc..." "X" -``` - -Exploring ---------- - -### `tabyl()` - a better version of `table()` - -`tabyl()` is a tidyverse-oriented replacement for `table()`. It counts combinations of one, two, or three variables, and then can be formatted with a suite of `adorn_*` functions to look just how you want. For instance: - -``` r -mtcars %>% - tabyl(gear, cyl) %>% - adorn_totals("col") %>% - adorn_percentages("row") %>% - adorn_pct_formatting(digits = 2) %>% - adorn_ns() %>% - adorn_title() -#> cyl -#> gear 4 6 8 Total -#> 3 6.67% (1) 13.33% (2) 80.00% (12) 100.00% (15) -#> 4 66.67% (8) 33.33% (4) 0.00% (0) 100.00% (12) -#> 5 40.00% (2) 20.00% (1) 40.00% (2) 100.00% (5) -``` - -Learn more in the [tabyls vignette](https://github.com/sfirke/janitor/blob/master/vignettes/tabyls.md). - -### Explore records with duplicated values for specific combinations of variables with `get_dupes()` - -This is for hunting down and examining duplicate records during data cleaning - usually when there shouldn't be any. - -For example, in a tidy data frame you might expect to have a unique ID repeated for each year, and year repeated for each unique ID, but no duplicated pairs of unique ID & year. Say you want to check for their presence, and study any such duplicated records. - -`get_dupes()` returns the records (and inserts a count of duplicates) so you can sleuth out the problematic cases: - -``` r -get_dupes(mtcars, wt, cyl) # or mtcars %>% get_dupes(wt, cyl) if you prefer to pipe -#> # A tibble: 4 x 12 -#> wt cyl dupe_count mpg disp hp drat qsec vs am gear -#> -#> 1 3.44 6.00 2 19.2 168 123 3.92 18.3 1.00 0 4.00 -#> 2 3.44 6.00 2 17.8 168 123 3.92 18.9 1.00 0 4.00 -#> 3 3.57 8.00 2 14.3 360 245 3.21 15.8 0 0 3.00 -#> 4 3.57 8.00 2 15.0 301 335 3.54 14.6 0 1.00 5.00 -#> # ... with 1 more variable: carb -``` - -Minor functions -=============== - -Smaller functions for use in particular situations. More human-readable than the equivalent code they replace. - -Cleaning --------- - -### Fix dates stored as serial numbers with `excel_numeric_to_date()` - -Ever load data from Excel and see a value like `42223` where a date should be? This function converts those serial numbers to class `Date`, and contains an option for specifying the alternate date system for files created with Excel for Mac 2008 and earlier versions (which count from a different starting point). - -``` r -excel_numeric_to_date(41103) -#> [1] "2012-07-13" -excel_numeric_to_date(41103, date_system = "mac pre-2011") -#> [1] "2016-07-14" -``` - -### `remove_empty()` rows and columns - -Does what it says. For cases like cleaning Excel files containing empty rows and columns. - -``` r -q <- data.frame(v1 = c(1, NA, 3), - v2 = c(NA, NA, NA), - v3 = c("a", NA, "b")) -q %>% - remove_empty(c("rows", "cols")) -#> v1 v3 -#> 1 1 a -#> 3 3 b -``` - -Just a simple wrapper for one-line functions, but improves readability of the code and saves a little thinking. - -Exploring ---------- - -### Count factor levels in groups of high, medium, and low with `top_levels()` - -Originally designed for use with Likert survey data stored as factors. Returns a `tbl_df` frequency table with appropriately-named rows, grouped into head/middle/tail groups. - -- Takes a user-specified size for the head/tail groups -- Automatically calculates a percent column -- Supports sorting -- Can show or hide `NA` values. - -``` r -f <- factor(c("strongly agree", "agree", "neutral", "neutral", "disagree", "strongly agree"), - levels = c("strongly agree", "agree", "neutral", "disagree", "strongly disagree")) -top_levels(f) -#> f n percent -#> strongly agree, agree 3 0.5000000 -#> neutral 2 0.3333333 -#> disagree, strongly disagree 1 0.1666667 -top_levels(f, n = 1) -#> f n percent -#> strongly agree 2 0.3333333 -#> agree, neutral, disagree 4 0.6666667 -#> strongly disagree 0 0.0000000 -``` diff --git a/docs/articles/tabyls.html b/docs/articles/tabyls.html deleted file mode 100644 index c6782b0c..00000000 --- a/docs/articles/tabyls.html +++ /dev/null @@ -1,454 +0,0 @@ - - - - - - - -tabyls: a tidy, fully-featured approach to counting things • janitor - - - - - - - - - - -
-
- - - - -
-
- - - - -
-

-Motivation: why tabyl?

-

Analysts do a lot of counting. Indeed, it’s been said that “data science is mostly counting things.” But the base R function for counting, table(), leaves much to be desired:

-
    -
  • It doesn’t accept data.frame inputs (and thus doesn’t play nicely with the %>% pipe)
  • -
  • It doesn’t output data.frames
  • -
  • Its results are hard to format. Compare the look and formatting choices of an R table to a Microsoft Excel PivotTable or even the table formatting provided by SPSS.
  • -
-

tabyl() is an approach to tabulating variables that addresses these shortcomings. It’s part of the janitor package because counting is such a fundamental part of data cleaning and exploration.

-

tabyl() is tidyverse-aligned and is primarily built upon the dplyr and tidyr packages.

-
-
-

-How it works

-

On its surface, tabyl() produces frequency tables using 1, 2, or 3 variables. Under the hood, tabyl() also attaches a copy of these counts as an attribute of the resulting data.frame.

-

The result looks like a basic data.frame of counts, but because it’s also a tabyl containing this metadata, you can use adorn_ functions to add additional information and pretty formatting.

-

The adorn_ functions are built to work on tabyls, but have been adapted to work with similar, non-tabyl data.frames that need formatting.

-
-
-

-Examples

-

This vignette demonstrates tabyl in the context of studying humans in the starwars dataset from dplyr:

-
library(dplyr)
-humans <- starwars %>%
-  filter(species == "Human")
-
-

-One-way tabyl

-

Tabulating a single variable is the simplest kind of tabyl:

-
library(janitor)
-#> 
-#> Attaching package: 'janitor'
-#> The following objects are masked from 'package:stats':
-#> 
-#>     chisq.test, fisher.test
-
-t1 <- humans %>%
-  tabyl(eye_color)
-
-t1
-#>  eye_color  n    percent
-#>       blue 12 0.34285714
-#>  blue-gray  1 0.02857143
-#>      brown 17 0.48571429
-#>       dark  1 0.02857143
-#>      hazel  2 0.05714286
-#>     yellow  2 0.05714286
-

When NA values are present, tabyl() also displays “valid” percentages, i.e., with missing values removed from the denominator. And while tabyl() is built to take a data.frame and column names, you can also produce a one-way tabyl by calling it directly on a vector:

-
x <- c("big", "big", "small", "small", "small", NA)
-tabyl(x)
-#>      x n   percent valid_percent
-#>    big 2 0.3333333           0.4
-#>  small 3 0.5000000           0.6
-#>   <NA> 1 0.1666667            NA
-

Most adorn_ helper functions are built for 2-way tabyls, but those that make sense for a 1-way tabyl do work:

-
t1 %>%
-  adorn_totals("row") %>%
-  adorn_pct_formatting()
-#>  eye_color  n percent
-#>       blue 12   34.3%
-#>  blue-gray  1    2.9%
-#>      brown 17   48.6%
-#>       dark  1    2.9%
-#>      hazel  2    5.7%
-#>     yellow  2    5.7%
-#>      Total 35  100.0%
-
-
-

-Two-way tabyl

-

This is often called a “crosstab” or “contingency” table. Calling tabyl on two columns of a data.frame produces the same result as the common combination of dplyr::count(), followed by tidyr::pivot_wider() to wide form:

-
t2 <- humans %>%
-  tabyl(gender, eye_color)
-
-t2
-#>     gender blue blue-gray brown dark hazel yellow
-#>   feminine    3         0     5    0     1      0
-#>  masculine    9         1    12    1     1      2
-

Since it’s a tabyl, we can enhance it with adorn_ helper functions. For instance:

-
-t2 %>%
-  adorn_percentages("row") %>%
-  adorn_pct_formatting(digits = 2) %>%
-  adorn_ns()
-#>     gender       blue blue-gray       brown      dark      hazel    yellow
-#>   feminine 33.33% (3) 0.00% (0) 55.56%  (5) 0.00% (0) 11.11% (1) 0.00% (0)
-#>  masculine 34.62% (9) 3.85% (1) 46.15% (12) 3.85% (1)  3.85% (1) 7.69% (2)
-

Adornments have options to control axes, rounding, and other relevant formatting choices (more on that below).

-
-
-

-Three-way tabyl

-

Just as table() accepts three variables, so does tabyl(), producing a list of tabyls:

-
t3 <- humans %>%
-  tabyl(eye_color, skin_color, gender)
-
-# the result is a tabyl of eye color x skin color, split into a list by gender
-t3
-#> $feminine
-#>  eye_color dark fair light pale tan white
-#>       blue    0    2     1    0   0     0
-#>  blue-gray    0    0     0    0   0     0
-#>      brown    0    1     4    0   0     0
-#>       dark    0    0     0    0   0     0
-#>      hazel    0    0     1    0   0     0
-#>     yellow    0    0     0    0   0     0
-#> 
-#> $masculine
-#>  eye_color dark fair light pale tan white
-#>       blue    0    7     2    0   0     0
-#>  blue-gray    0    1     0    0   0     0
-#>      brown    3    4     3    0   2     0
-#>       dark    1    0     0    0   0     0
-#>      hazel    0    1     0    0   0     0
-#>     yellow    0    0     0    1   0     1
-

If the adorn_ helper functions are called on a list of data.frames - like the output of a three-way tabyl call - they will call purrr::map() to apply themselves to each data.frame in the list:

-
library(purrr)
-humans %>%
-  tabyl(eye_color, skin_color, gender, show_missing_levels = FALSE) %>%
-  adorn_totals("row") %>%
-  adorn_percentages("all") %>%
-  adorn_pct_formatting(digits = 1) %>%
-  adorn_ns %>%
-  adorn_title
-#> $feminine
-#>            skin_color          
-#>  eye_color       fair     light
-#>       blue  22.2% (2) 11.1% (1)
-#>      brown  11.1% (1) 44.4% (4)
-#>      hazel   0.0% (0) 11.1% (1)
-#>      Total  33.3% (3) 66.7% (6)
-#> 
-#> $masculine
-#>            skin_color                                                
-#>  eye_color       dark       fair     light     pale      tan    white
-#>       blue   0.0% (0) 26.9%  (7)  7.7% (2) 0.0% (0) 0.0% (0) 0.0% (0)
-#>  blue-gray   0.0% (0)  3.8%  (1)  0.0% (0) 0.0% (0) 0.0% (0) 0.0% (0)
-#>      brown  11.5% (3) 15.4%  (4) 11.5% (3) 0.0% (0) 7.7% (2) 0.0% (0)
-#>       dark   3.8% (1)  0.0%  (0)  0.0% (0) 0.0% (0) 0.0% (0) 0.0% (0)
-#>      hazel   0.0% (0)  3.8%  (1)  0.0% (0) 0.0% (0) 0.0% (0) 0.0% (0)
-#>     yellow   0.0% (0)  0.0%  (0)  0.0% (0) 3.8% (1) 0.0% (0) 3.8% (1)
-#>      Total  15.4% (4) 50.0% (13) 19.2% (5) 3.8% (1) 7.7% (2) 3.8% (1)
-

This automatic mapping supports interactive data analysis that switches between combinations of 2 and 3 variables. That way, if a user starts with humans %>% tabyl(eye_color, skin_color), adds some adorn_ calls, then decides to split the tabulation by gender and modifies their first line to humans %>% tabyl(eye_color, skin_color, gender), they don’t have to rewrite the subsequent adornment calls to use map().

-

However, if feels more natural to call these with map() or lapply(), that is still supported. For instance, t3 %>% lapply(adorn_percentages) would produce the same result as t3 %>% adorn_percentages.

-
-

-Other features of tabyls

-
    -
  • When called on a factor, tabyl will show missing levels (levels not present in the data) in the result -
      -
    • This can be suppressed if not desired
    • -
    -
  • -
  • -NA values can be displayed or suppressed
  • -
  • -tabyls print without displaying row numbers
  • -
-

You can call chisq.test() and fisher.test() on a two-way tabyl to perform those statistical tests, just like on a base R table() object.

-
-
-
-

-The adorn_* functions

-

These modular functions build on a tabyl to approximate the functionality of a PivotTable in Microsoft Excel. They print elegant results for interactive analysis or for sharing in a report, e.g., with knitr::kable(). For example:

-
humans %>%
-  tabyl(gender, eye_color) %>%
-  adorn_totals(c("row", "col")) %>%
-  adorn_percentages("row") %>%
-  adorn_pct_formatting(rounding = "half up", digits = 0) %>%
-  adorn_ns() %>%
-  adorn_title("combined") %>%
-  knitr::kable()
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
gender/eye_colorblueblue-graybrowndarkhazelyellowTotal
feminine33% (3)0% (0)56% (5)0% (0)11% (1)0% (0)100% (9)
masculine35% (9)4% (1)46% (12)4% (1)4% (1)8% (2)100% (26)
Total34% (12)3% (1)49% (17)3% (1)6% (2)6% (2)100% (35)
-
-

-The adorn functions are:

-
    -
  • -adorn_totals(): Add totals row, column, or both.
  • -
  • -adorn_percentages(): Calculate percentages along either axis or over the entire tabyl
  • -
  • -adorn_pct_formatting(): Format percentage columns, controlling the number of digits to display and whether to append the % symbol
  • -
  • -adorn_rounding(): Round a data.frame of numbers (usually the result of adorn_percentages), either using the base R round() function or using janitor’s round_half_up() to round all ties up (thanks, StackOverflow). -
      -
    • e.g., round 10.5 up to 11, consistent with Excel’s tie-breaking behavior.
    • -
    • This contrasts with rounding 10.5 down to 10 as in base R’s round(10.5).
    • -
    • -adorn_rounding() returns columns of class numeric, allowing for graphing, sorting, etc. It’s a less-aggressive substitute for adorn_pct_formatting(); these two functions should not be called together.
    • -
    -
  • -
  • -adorn_ns(): add Ns to a tabyl. These can be drawn from the tabyl’s underlying counts, which are attached to the tabyl as metadata, or they can be supplied by the user.
  • -
  • -adorn_title(): add a title to a tabyl (or other data.frame). Options include putting the column title in a new row on top of the data.frame or combining the row and column titles in the data.frame’s first name slot.
  • -
-

These adornments should be called in a logical order, e.g., you probably want to add totals before percentages are calculated. In general, call them in the order they appear above.

-
-
-
-

-BYOt (Bring Your Own tabyl)

-

You can also call adorn_ functions on other data.frames, not only the results of calls to tabyl(). E.g., mtcars %>% adorn_totals("col") %>% adorn_percentages("col") performs as expected, despite mtcars not being a tabyl.

-

This can be handy when you have a data.frame that is not a simple tabulation generated by tabyl but would still benefit from the adorn_ formatting functions.

-

A simple example: calculate the proportion of records meeting a certain condition, then format the results.

-
percent_above_165_cm <- humans %>%
-  group_by(gender) %>%
-  summarise(pct_above_165_cm = mean(height > 165, na.rm = TRUE))
-
-percent_above_165_cm %>%
-  adorn_pct_formatting()
-#> # A tibble: 2 x 2
-#>   gender    pct_above_165_cm
-#>   <chr>     <chr>           
-#> 1 feminine  12.5%           
-#> 2 masculine 100.0%
-

You can control which columns are adorned by using the ... argument. It accepts the tidyselect helpers. That is, you can specify columns the same way you would using dplyr::select().

-

For instance, say you have a numeric column that should not be included in percentage formatting and you wish to exempt it. Here, only the count column is adorned:

-
mtcars %>%
-  count(cyl, gear) %>%
-  rename(proportion = n) %>%
-  adorn_percentages("col", na.rm = TRUE, proportion) %>%
-  adorn_pct_formatting(,,,proportion) # the commas say to use the default values of the other arguments
-#>  cyl gear proportion
-#>    4    3       3.1%
-#>    4    4      25.0%
-#>    4    5       6.2%
-#>    6    3       6.2%
-#>    6    4      12.5%
-#>    6    5       3.1%
-#>    8    3      37.5%
-#>    8    5       6.2%
-

Here we specify that only two consecutive numeric columns should be totaled (year is numeric but should not be included):

-
cases <- data.frame(
-  region = c("East, West"),
-  year = 2015,
-  recovered = c(125, 87),
-  died = c(13, 12),
-  stringsAsFactors = FALSE
-)
-
-cases %>%
-    adorn_totals(c("col", "row"), fill = "-", na.rm = TRUE, name = "Total Cases", recovered:died)
-#>       region year recovered died Total Cases
-#>   East, West 2015       125   13         138
-#>   East, West 2015        87   12          99
-#>  Total Cases    -       212   25         237
-

Here’s a more complex example that uses a data.frame of means, not counts. We create a table containing the mean of a 3rd variable when grouped by two other variables, then use adorn_ functions to round the values and append Ns. The first part is pretty straightforward:

-
library(tidyr) # for spread()
-mpg_by_cyl_and_am <- mtcars %>%
-  group_by(cyl, am) %>%
-  summarise(mpg = mean(mpg)) %>%
-  spread(am, mpg)
-
-mpg_by_cyl_and_am
-#> # A tibble: 3 x 3
-#> # Groups:   cyl [3]
-#>     cyl   `0`   `1`
-#>   <dbl> <dbl> <dbl>
-#> 1     4  22.9  28.1
-#> 2     6  19.1  20.6
-#> 3     8  15.0  15.4
-

Now to adorn_ it. Since this is not the result of a tabyl() call, it doesn’t have the underlying Ns stored in the core attribute, so we’ll have to supply them:

-
mpg_by_cyl_and_am %>%
-  adorn_rounding() %>%
-  adorn_ns(
-    ns = mtcars %>% # calculate the Ns on the fly by calling tabyl on the original data
-      tabyl(cyl, am)
-  ) %>%
-  adorn_title("combined", row_name = "Cylinders", col_name = "Is Automatic")
-#>   Cylinders/Is Automatic         0        1
-#> 1                      4 22.9  (3) 28.1 (8)
-#> 2                      6 19.1  (4) 20.6 (3)
-#> 3                      8 15.1 (12) 15.4 (2)
-

If needed, Ns can be manipulated in their own data.frame before they are appended. E.g., if you have a tabyl with values of N in the thousands, you could divide them by 1000, round, and append “k” before inserting them with adorn_ns.

-
-

-Questions? Comments?

-

File an issue on GitHub if you have suggestions related to tabyl() and its adorn_ helpers or encounter problems while using them.

-
-
-
-
- - - -
- - - -
- -
-

Site built with pkgdown 1.5.0.

-
- -
-
- - - - - - diff --git a/docs/articles/tabyls.md b/docs/articles/tabyls.md deleted file mode 100644 index 700c51aa..00000000 --- a/docs/articles/tabyls.md +++ /dev/null @@ -1,289 +0,0 @@ -tabyls: a tidy, fully-featured approach to counting things -================ -2018-03-03 - -Motivation: why tabyl? ----------------------- - -Analysts do a lot of counting. Indeed, it's been said that "[data science is mostly counting things](https://twitter.com/joelgrus/status/833691273873600512)." But the base R function for counting, `table()`, leaves much to be desired: - -- It doesn't accept data.frame inputs (and thus doesn't play nicely with the tidyverse) -- It doesn't output data.frames -- Its results are hard to format. Compare the look and formatting choices of an R table to a Microsoft Excel PivotTable or even the table formatting provided by SPSS. - -`tabyl()` is an approach to tabulating variables that addresses these shortcomings. It's part of the janitor package because counting is such a fundamental part of data cleaning and exploration. - -`tabyl()` is tidyverse-aligned and is primarily built upon the dplyr and tidyr packages. - -How it works ------------- - -On its surface, `tabyl()` produces frequency tables using 1, 2, or 3 variables. Under the hood, `tabyl()` also attaches a copy of these counts as an attribute of the resulting data.frame. - -The result looks like a basic data.frame of counts, but because it's also a `tabyl` containing this metadata, you can use `adorn_` functions to add additional information and pretty formatting. - -Examples -======== - -This vignette demonstrates `tabyl` in the context of studying humans in the `starwars` dataset from dplyr: - -``` r -library(dplyr) -humans <- starwars %>% - filter(species == "Human") -``` - -### Installing - -The features of `tabyl()` shown here are in the development version of janitor on GitHub and are not on CRAN yet. You can install the dev version with `devtools::install_github("sfirke/janitor")`. - -One-way tabyl -------------- - -Tabulating a single variable is the simplest kind of tabyl: - -``` r -library(janitor) - -t1 <- humans %>% - tabyl(eye_color) - -t1 -#> eye_color n percent -#> blue 12 0.34285714 -#> blue-gray 1 0.02857143 -#> brown 17 0.48571429 -#> dark 1 0.02857143 -#> hazel 2 0.05714286 -#> yellow 2 0.05714286 -``` - -When `NA` values are present, `tabyl()` also displays "valid" percentages, i.e., with missing values removed from the denominator. And while `tabyl()` is built to take a data.frame and column names, you can also produce a one-way tabyl by calling it directly on a vector: - -``` r -x <- c("big", "big", "small", "small", "small", NA) -tabyl(x) -#> x n percent valid_percent -#> big 2 0.3333333 0.4 -#> small 3 0.5000000 0.6 -#> 1 0.1666667 NA -``` - -Most `adorn_` helper functions are built for 2-way tabyls, but those that make sense for a 1-way tabyl do work: - -``` r -t1 %>% - adorn_totals("row") %>% - adorn_pct_formatting() -#> eye_color n percent -#> blue 12 34.3% -#> blue-gray 1 2.9% -#> brown 17 48.6% -#> dark 1 2.9% -#> hazel 2 5.7% -#> yellow 2 5.7% -#> Total 35 100.0% -``` - -Two-way tabyl -------------- - -This is often called a "crosstab" or "contingency" table. The initial call produces the same result as the common combination of `dplyr::count()`, followed by `tidyr::spread()` to wide form: - -``` r -t2 <- humans %>% - tabyl(gender, eye_color) - -t2 -#> gender blue blue-gray brown dark hazel yellow -#> female 3 0 5 0 1 0 -#> male 9 1 12 1 1 2 -``` - -Since it's a `tabyl`, we can enhance it with `adorn_` helper functions. For instance: - -``` r - -t2 %>% - adorn_percentages("row") %>% - adorn_pct_formatting(digits = 2) %>% - adorn_ns() -#> gender blue blue-gray brown dark hazel yellow -#> female 33.33% (3) 0.00% (0) 55.56% (5) 0.00% (0) 11.11% (1) 0.00% (0) -#> male 34.62% (9) 3.85% (1) 46.15% (12) 3.85% (1) 3.85% (1) 7.69% (2) -``` - -Adornments have options to control axes, rounding, and other relevant formatting choices (more on that below). - -Three-way tabyl ---------------- - -Just as `table()` accepts three variables, so does `tabyl()`, producing a list of tabyls: - -``` r -t3 <- humans %>% - tabyl(eye_color, skin_color, gender) - -t3 # the result is a tabyl of eye color x skin color, split into a list by gender -#> $female -#> eye_color dark fair light pale tan white -#> blue 0 2 1 0 0 0 -#> blue-gray 0 0 0 0 0 0 -#> brown 0 1 4 0 0 0 -#> dark 0 0 0 0 0 0 -#> hazel 0 0 1 0 0 0 -#> yellow 0 0 0 0 0 0 -#> -#> $male -#> eye_color dark fair light pale tan white -#> blue 0 7 2 0 0 0 -#> blue-gray 0 1 0 0 0 0 -#> brown 3 4 3 0 2 0 -#> dark 1 0 0 0 0 0 -#> hazel 0 1 0 0 0 0 -#> yellow 0 0 0 1 0 1 -``` - -If called on a list of data.frames - like the output of a three-way `tabyl` call - the `adorn_` helper functions will apply themselves to each data.frame: - -``` r -library(purrr) -humans %>% - tabyl(eye_color, skin_color, gender, show_missing_levels = FALSE) %>% - adorn_totals("row") %>% - adorn_percentages("all") %>% - adorn_pct_formatting(digits = 1) %>% - adorn_ns %>% - adorn_title -#> $female -#> skin_color -#> eye_color fair light -#> blue 22.2% (2) 11.1% (1) -#> brown 11.1% (1) 44.4% (4) -#> hazel 0.0% (0) 11.1% (1) -#> Total 33.3% (3) 66.7% (6) -#> -#> $male -#> skin_color -#> eye_color dark fair light pale tan white -#> blue 0.0% (0) 26.9% (7) 7.7% (2) 0.0% (0) 0.0% (0) 0.0% (0) -#> blue-gray 0.0% (0) 3.8% (1) 0.0% (0) 0.0% (0) 0.0% (0) 0.0% (0) -#> brown 11.5% (3) 15.4% (4) 11.5% (3) 0.0% (0) 7.7% (2) 0.0% (0) -#> dark 3.8% (1) 0.0% (0) 0.0% (0) 0.0% (0) 0.0% (0) 0.0% (0) -#> hazel 0.0% (0) 3.8% (1) 0.0% (0) 0.0% (0) 0.0% (0) 0.0% (0) -#> yellow 0.0% (0) 0.0% (0) 0.0% (0) 3.8% (1) 0.0% (0) 3.8% (1) -#> Total 15.4% (4) 50.0% (13) 19.2% (5) 3.8% (1) 7.7% (2) 3.8% (1) -``` - -These functions automatically call `purrr::map()` internally to support interactive data analysis that switches between 2 and 3 variables. That way, if a user starts with `humans %>% tabyl(eye_color, skin_color)`, adds some `adorn_` calls, then decides to split the tabulation by gender and modifies their first line to `humans %>% tabyl(eye_color, skin_color, gender`), they don't have to refactor the subsequent adornment calls to use `map()`. - -However, if feels more natural to call these with `purrr::map()` or `lapply()`, that is still supported. For instance, `t3 %>% lapply(adorn_percentages)` would produce the same result as `t3 %>% adorn_percentages`. - -### Other features of tabyls - -- When called on a factor, it will include missing levels (levels not present in the data) in the result - - This can be suppressed if not desired -- `NA` values can be displayed or suppressed -- Prints without displaying row numbers - -`adorn_*` functions -------------------- - -These modular functions build on a `tabyl` to approximate the functionality of a quick PivotTable in Microsoft Excel. They print elegant results for interactive analysis or for sharing in a report, e.g., with `knitr::kable()`. For example: - -``` r -humans %>% - tabyl(gender, eye_color) %>% - adorn_totals(c("row", "col")) %>% - adorn_percentages("row") %>% - adorn_pct_formatting(rounding = "half up", digits = 0) %>% - adorn_ns() %>% - adorn_title("combined") %>% - knitr::kable() -``` - -| gender/eye\_color | blue | blue-gray | brown | dark | hazel | yellow | Total | -|:------------------|:---------|:----------|:---------|:-------|:--------|:-------|:----------| -| female | 33% (3) | 0% (0) | 56% (5) | 0% (0) | 11% (1) | 0% (0) | 100% (9) | -| male | 35% (9) | 4% (1) | 46% (12) | 4% (1) | 4% (1) | 8% (2) | 100% (26) | -| Total | 34% (12) | 3% (1) | 49% (17) | 3% (1) | 6% (2) | 6% (2) | 100% (35) | - -### The adorn functions are: - -- **`adorn_totals()`**: Add totals row, column, or both. Replaces the janitor functions `add_totals_row` and `add_totals_col` -- **`adorn_percentages()`**: Calculate percentages along either axis or over the entire tabyl -- **`adorn_pct_formatting()`**: Format percentage columns, controlling number of digits to display and whether to append the `%` symbol -- **`adorn_rounding()`**: Round a data.frame of numbers (usually the result of `adorn_percentages`), either using the base R `round()` function or rounding all ties up using a custom rounding function ([thanks, StackOverflow](http://stackoverflow.com/a/12688836/4470365)). - - e.g., round 10.5 up to 11, consistent with Excel's tie-breaking behavior. - - This contrasts with rounding 10.5 down to 10 as in base R's `round(10.5)`. - - `adorn_rounding()` outputs retain the class `numeric`, allowing for graphing, sorting, etc. It's a less-aggressive substitute for `adorn_pct_formatting()`; these two functions should not be called together. -- **`adorn_ns()`**: add Ns to a tabyl. These can be drawn from the tabyl's `core` attribute (by default), or supplied by the user. -- **`adorn_title()`**: add a title to a tabyl (or other data.frame). Options include putting the column title in a new row on top of the data.frame or combining the row and column titles in the data.frame's first name slot. - -These adornments should be called in a logical order, e.g., you probably want to add totals before percentages are calculated. In general, call them in the order they appear above. - -Users of janitor version <= 0.3.0 should replace the deprecated `adorn_crosstab()` function with combinations of the above `adorn_` functions. - -BYOt (Bring Your Own tabyl) ---------------------------- - -You can also call `adorn_` functions on other data.frames, not only the results of calls to `tabyl()`. E.g., `mtcars %>% adorn_totals("col") %>% adorn_percentages("col")` performs as expected, despite `mtcars` not being a `tabyl`. - -This can be handy when you have a data.frame that is not a simple tabulation generated by `tabyl` but would still benefit from the `adorn_` formatting functions. - -A simple example: formatting percentages in a data.frame showing the % of records meeting a certain condition: - -``` r -percent_above_165_cm <- humans %>% - group_by(gender) %>% - summarise(pct_above_165_cm = mean(height > 165, na.rm = TRUE)) - -percent_above_165_cm %>% - adorn_pct_formatting() -#> # A tibble: 2 x 2 -#> gender pct_above_165_cm -#> -#> 1 female 12.5% -#> 2 male 100.0% -``` - -Here's a more complex example. We'll create a table containing the mean of a 3rd variable when grouped by two other variables, then use `adorn_` functions to round the values and append Ns. The first part is pretty straightforward: - -``` r -library(tidyr) # for spread() -mpg_by_cyl_and_am <- mtcars %>% - group_by(cyl, am) %>% - summarise(mpg = mean(mpg)) %>% - spread(am, mpg) - -mpg_by_cyl_and_am -#> # A tibble: 3 x 3 -#> # Groups: cyl [3] -#> cyl `0` `1` -#> -#> 1 4.00 22.9 28.1 -#> 2 6.00 19.1 20.6 -#> 3 8.00 15.0 15.4 -``` - -Now to `adorn_` it. Since this is not a result of a `tabyl()` call, it doesn't have the underlying Ns stored in the `core` attribute, so we'll have to supply them: - -``` r -mpg_by_cyl_and_am %>% - adorn_rounding() %>% - adorn_ns( - ns = mtcars %>% # calculate the Ns on the fly by calling tabyl on the original data - tabyl(cyl, am) - ) %>% - adorn_title("combined", row_name = "Cylinders", col_name = "Is Automatic") -#> Cylinders/Is Automatic 0 1 -#> 1 4 22.9 (3) 28.1 (8) -#> 2 6 19.1 (4) 20.6 (3) -#> 3 8 15.1 (12) 15.4 (2) -``` - -Or you could tinker with the Ns before appending them, e.g., if you have large Ns in a tabyl, divide them by 1000, round, and append "k" before calling `adorn_ns`. - -### Questions? Comments? - -File [an issue on GitHub](https://github.com/sfirke/janitor/issues) if you have questions or ideas related to `tabyl()` and its `adorn_` helpers or encounter problems while using them. diff --git a/docs/authors.html b/docs/authors.html deleted file mode 100644 index 4d70ae9e..00000000 --- a/docs/authors.html +++ /dev/null @@ -1,182 +0,0 @@ - - - - - - - - -Authors • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - - -
- -
-
- - -
    -
  • -

    Sam Firke. Author, maintainer. -

    -
  • -
  • -

    Bill Denney. Contributor. -

    -
  • -
  • -

    Chris Haid. Contributor. -

    -
  • -
  • -

    Ryan Knight. Contributor. -

    -
  • -
  • -

    Malte Grosser. Contributor. -

    -
  • -
  • -

    Jonathan Zadra. Contributor. -

    -
  • -
- -
- -
- - - -
- - -
-

Site built with pkgdown 1.5.0.

-
- -
-
- - - - - - - - diff --git a/docs/bootstrap-toc.css b/docs/bootstrap-toc.css deleted file mode 100644 index 5a859415..00000000 --- a/docs/bootstrap-toc.css +++ /dev/null @@ -1,60 +0,0 @@ -/*! - * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/) - * Copyright 2015 Aidan Feldman - * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */ - -/* modified from https://github.com/twbs/bootstrap/blob/94b4076dd2efba9af71f0b18d4ee4b163aa9e0dd/docs/assets/css/src/docs.css#L548-L601 */ - -/* All levels of nav */ -nav[data-toggle='toc'] .nav > li > a { - display: block; - padding: 4px 20px; - font-size: 13px; - font-weight: 500; - color: #767676; -} -nav[data-toggle='toc'] .nav > li > a:hover, -nav[data-toggle='toc'] .nav > li > a:focus { - padding-left: 19px; - color: #563d7c; - text-decoration: none; - background-color: transparent; - border-left: 1px solid #563d7c; -} -nav[data-toggle='toc'] .nav > .active > a, -nav[data-toggle='toc'] .nav > .active:hover > a, -nav[data-toggle='toc'] .nav > .active:focus > a { - padding-left: 18px; - font-weight: bold; - color: #563d7c; - background-color: transparent; - border-left: 2px solid #563d7c; -} - -/* Nav: second level (shown on .active) */ -nav[data-toggle='toc'] .nav .nav { - display: none; /* Hide by default, but at >768px, show it */ - padding-bottom: 10px; -} -nav[data-toggle='toc'] .nav .nav > li > a { - padding-top: 1px; - padding-bottom: 1px; - padding-left: 30px; - font-size: 12px; - font-weight: normal; -} -nav[data-toggle='toc'] .nav .nav > li > a:hover, -nav[data-toggle='toc'] .nav .nav > li > a:focus { - padding-left: 29px; -} -nav[data-toggle='toc'] .nav .nav > .active > a, -nav[data-toggle='toc'] .nav .nav > .active:hover > a, -nav[data-toggle='toc'] .nav .nav > .active:focus > a { - padding-left: 28px; - font-weight: 500; -} - -/* from https://github.com/twbs/bootstrap/blob/e38f066d8c203c3e032da0ff23cd2d6098ee2dd6/docs/assets/css/src/docs.css#L631-L634 */ -nav[data-toggle='toc'] .nav > .active > ul { - display: block; -} diff --git a/docs/bootstrap-toc.js b/docs/bootstrap-toc.js deleted file mode 100644 index 1cdd573b..00000000 --- a/docs/bootstrap-toc.js +++ /dev/null @@ -1,159 +0,0 @@ -/*! - * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/) - * Copyright 2015 Aidan Feldman - * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */ -(function() { - 'use strict'; - - window.Toc = { - helpers: { - // return all matching elements in the set, or their descendants - findOrFilter: function($el, selector) { - // http://danielnouri.org/notes/2011/03/14/a-jquery-find-that-also-finds-the-root-element/ - // http://stackoverflow.com/a/12731439/358804 - var $descendants = $el.find(selector); - return $el.filter(selector).add($descendants).filter(':not([data-toc-skip])'); - }, - - generateUniqueIdBase: function(el) { - var text = $(el).text(); - var anchor = text.trim().toLowerCase().replace(/[^A-Za-z0-9]+/g, '-'); - return anchor || el.tagName.toLowerCase(); - }, - - generateUniqueId: function(el) { - var anchorBase = this.generateUniqueIdBase(el); - for (var i = 0; ; i++) { - var anchor = anchorBase; - if (i > 0) { - // add suffix - anchor += '-' + i; - } - // check if ID already exists - if (!document.getElementById(anchor)) { - return anchor; - } - } - }, - - generateAnchor: function(el) { - if (el.id) { - return el.id; - } else { - var anchor = this.generateUniqueId(el); - el.id = anchor; - return anchor; - } - }, - - createNavList: function() { - return $(''); - }, - - createChildNavList: function($parent) { - var $childList = this.createNavList(); - $parent.append($childList); - return $childList; - }, - - generateNavEl: function(anchor, text) { - var $a = $(''); - $a.attr('href', '#' + anchor); - $a.text(text); - var $li = $('
  • '); - $li.append($a); - return $li; - }, - - generateNavItem: function(headingEl) { - var anchor = this.generateAnchor(headingEl); - var $heading = $(headingEl); - var text = $heading.data('toc-text') || $heading.text(); - return this.generateNavEl(anchor, text); - }, - - // Find the first heading level (`

    `, then `

    `, etc.) that has more than one element. Defaults to 1 (for `

    `). - getTopLevel: function($scope) { - for (var i = 1; i <= 6; i++) { - var $headings = this.findOrFilter($scope, 'h' + i); - if ($headings.length > 1) { - return i; - } - } - - return 1; - }, - - // returns the elements for the top level, and the next below it - getHeadings: function($scope, topLevel) { - var topSelector = 'h' + topLevel; - - var secondaryLevel = topLevel + 1; - var secondarySelector = 'h' + secondaryLevel; - - return this.findOrFilter($scope, topSelector + ',' + secondarySelector); - }, - - getNavLevel: function(el) { - return parseInt(el.tagName.charAt(1), 10); - }, - - populateNav: function($topContext, topLevel, $headings) { - var $context = $topContext; - var $prevNav; - - var helpers = this; - $headings.each(function(i, el) { - var $newNav = helpers.generateNavItem(el); - var navLevel = helpers.getNavLevel(el); - - // determine the proper $context - if (navLevel === topLevel) { - // use top level - $context = $topContext; - } else if ($prevNav && $context === $topContext) { - // create a new level of the tree and switch to it - $context = helpers.createChildNavList($prevNav); - } // else use the current $context - - $context.append($newNav); - - $prevNav = $newNav; - }); - }, - - parseOps: function(arg) { - var opts; - if (arg.jquery) { - opts = { - $nav: arg - }; - } else { - opts = arg; - } - opts.$scope = opts.$scope || $(document.body); - return opts; - } - }, - - // accepts a jQuery object, or an options object - init: function(opts) { - opts = this.helpers.parseOps(opts); - - // ensure that the data attribute is in place for styling - opts.$nav.attr('data-toggle', 'toc'); - - var $topContext = this.helpers.createChildNavList(opts.$nav); - var topLevel = this.helpers.getTopLevel(opts.$scope); - var $headings = this.helpers.getHeadings(opts.$scope, topLevel); - this.helpers.populateNav($topContext, topLevel, $headings); - } - }; - - $(function() { - $('nav[data-toggle="toc"]').each(function(i, el) { - var $nav = $(el); - Toc.init($nav); - }); - }); -})(); diff --git a/docs/cran-comments.html b/docs/cran-comments.html deleted file mode 100644 index 66e329c4..00000000 --- a/docs/cran-comments.html +++ /dev/null @@ -1,165 +0,0 @@ - - - - - - - - -C:/Users/SFirke/Documents/Bitbucket/janitor/cran-comments.md • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - -
    - -
    -
    - - -
    -

    Submission

    -

    2018-03-17

    -
    -

    Test environments

    -
      -
    • local Windows 10 install, R 3.4.3
    • -
    • local Windows 10 install, R 3.4.4
    • -
    • win-builder with R-devel 2018-03-16 74418
    • -
    • ubuntu 16.04.3, R-release 3.4.3
    • -
    • ubuntu 16.04.3, R-release 3.4.4
    • -
    -

    On Travis CI:

    -
      -
    • ubuntu 14.04.5, R-oldrel 3.3.3
    • -
    • ubuntu 14.04.5 R-release 3.4.4
    • -
    • ubuntu 14.04.5 R-devel R 3.5.0 74418
    • -
    • OS X Sierra 10.12.6, R-oldrel 3.3.3
    • -
    • OS X Sierra 10.12.6, R-release 3.4.4
    • -
    -
    -
    -

    R CMD check results

    -

    0 errors | 0 warnings | 0 notes

    -
    -
    -

    Downstream dependencies

    -

    This update to janitor v1.0 involves breaking changes that affect some downstream packages. I advised all downstream package maintainers of these changes on February 21, including providing code that would keep their packages compatible with all versions of janitor.

    -

    I checked 4 reverse dependencies from CRAN.

    -
    -

    New problems

    -

    These CRAN packages depending on janitor each have 1 warning:

    -
      -
    • ballr, bomrang: failures due to change in janitor::clean_names, I proposed a fix to package maintainers on Feb 21
    • -
    -
    -
    -
    - -
    - -
    - - -
    - - -
    -

    Site built with pkgdown.

    -
    - -
    -
    - - - - diff --git a/docs/docsearch.css b/docs/docsearch.css deleted file mode 100644 index e5f1fe1d..00000000 --- a/docs/docsearch.css +++ /dev/null @@ -1,148 +0,0 @@ -/* Docsearch -------------------------------------------------------------- */ -/* - Source: https://github.com/algolia/docsearch/ - License: MIT -*/ - -.algolia-autocomplete { - display: block; - -webkit-box-flex: 1; - -ms-flex: 1; - flex: 1 -} - -.algolia-autocomplete .ds-dropdown-menu { - width: 100%; - min-width: none; - max-width: none; - padding: .75rem 0; - background-color: #fff; - background-clip: padding-box; - border: 1px solid rgba(0, 0, 0, .1); - box-shadow: 0 .5rem 1rem rgba(0, 0, 0, .175); -} - -@media (min-width:768px) { - .algolia-autocomplete .ds-dropdown-menu { - width: 175% - } -} - -.algolia-autocomplete .ds-dropdown-menu::before { - display: none -} - -.algolia-autocomplete .ds-dropdown-menu [class^=ds-dataset-] { - padding: 0; - background-color: rgb(255,255,255); - border: 0; - max-height: 80vh; -} - -.algolia-autocomplete .ds-dropdown-menu .ds-suggestions { - margin-top: 0 -} - -.algolia-autocomplete .algolia-docsearch-suggestion { - padding: 0; - overflow: visible -} - -.algolia-autocomplete .algolia-docsearch-suggestion--category-header { - padding: .125rem 1rem; - margin-top: 0; - font-size: 1.3em; - font-weight: 500; - color: #00008B; - border-bottom: 0 -} - -.algolia-autocomplete .algolia-docsearch-suggestion--wrapper { - float: none; - padding-top: 0 -} - -.algolia-autocomplete .algolia-docsearch-suggestion--subcategory-column { - float: none; - width: auto; - padding: 0; - text-align: left -} - -.algolia-autocomplete .algolia-docsearch-suggestion--content { - float: none; - width: auto; - padding: 0 -} - -.algolia-autocomplete .algolia-docsearch-suggestion--content::before { - display: none -} - -.algolia-autocomplete .ds-suggestion:not(:first-child) .algolia-docsearch-suggestion--category-header { - padding-top: .75rem; - margin-top: .75rem; - border-top: 1px solid rgba(0, 0, 0, .1) -} - -.algolia-autocomplete .ds-suggestion .algolia-docsearch-suggestion--subcategory-column { - display: block; - padding: .1rem 1rem; - margin-bottom: 0.1; - font-size: 1.0em; - font-weight: 400 - /* display: none */ -} - -.algolia-autocomplete .algolia-docsearch-suggestion--title { - display: block; - padding: .25rem 1rem; - margin-bottom: 0; - font-size: 0.9em; - font-weight: 400 -} - -.algolia-autocomplete .algolia-docsearch-suggestion--text { - padding: 0 1rem .5rem; - margin-top: -.25rem; - font-size: 0.8em; - font-weight: 400; - line-height: 1.25 -} - -.algolia-autocomplete .algolia-docsearch-footer { - width: 110px; - height: 20px; - z-index: 3; - margin-top: 10.66667px; - float: right; - font-size: 0; - line-height: 0; -} - -.algolia-autocomplete .algolia-docsearch-footer--logo { - background-image: url("data:image/svg+xml;utf8,"); - background-repeat: no-repeat; - background-position: 50%; - background-size: 100%; - overflow: hidden; - text-indent: -9000px; - width: 100%; - height: 100%; - display: block; - transform: translate(-8px); -} - -.algolia-autocomplete .algolia-docsearch-suggestion--highlight { - color: #FF8C00; - background: rgba(232, 189, 54, 0.1) -} - - -.algolia-autocomplete .algolia-docsearch-suggestion--text .algolia-docsearch-suggestion--highlight { - box-shadow: inset 0 -2px 0 0 rgba(105, 105, 105, .5) -} - -.algolia-autocomplete .ds-suggestion.ds-cursor .algolia-docsearch-suggestion--content { - background-color: rgba(192, 192, 192, .15) -} diff --git a/docs/docsearch.js b/docs/docsearch.js deleted file mode 100644 index b35504cd..00000000 --- a/docs/docsearch.js +++ /dev/null @@ -1,85 +0,0 @@ -$(function() { - - // register a handler to move the focus to the search bar - // upon pressing shift + "/" (i.e. "?") - $(document).on('keydown', function(e) { - if (e.shiftKey && e.keyCode == 191) { - e.preventDefault(); - $("#search-input").focus(); - } - }); - - $(document).ready(function() { - // do keyword highlighting - /* modified from https://jsfiddle.net/julmot/bL6bb5oo/ */ - var mark = function() { - - var referrer = document.URL ; - var paramKey = "q" ; - - if (referrer.indexOf("?") !== -1) { - var qs = referrer.substr(referrer.indexOf('?') + 1); - var qs_noanchor = qs.split('#')[0]; - var qsa = qs_noanchor.split('&'); - var keyword = ""; - - for (var i = 0; i < qsa.length; i++) { - var currentParam = qsa[i].split('='); - - if (currentParam.length !== 2) { - continue; - } - - if (currentParam[0] == paramKey) { - keyword = decodeURIComponent(currentParam[1].replace(/\+/g, "%20")); - } - } - - if (keyword !== "") { - $(".contents").unmark({ - done: function() { - $(".contents").mark(keyword); - } - }); - } - } - }; - - mark(); - }); -}); - -/* Search term highlighting ------------------------------*/ - -function matchedWords(hit) { - var words = []; - - var hierarchy = hit._highlightResult.hierarchy; - // loop to fetch from lvl0, lvl1, etc. - for (var idx in hierarchy) { - words = words.concat(hierarchy[idx].matchedWords); - } - - var content = hit._highlightResult.content; - if (content) { - words = words.concat(content.matchedWords); - } - - // return unique words - var words_uniq = [...new Set(words)]; - return words_uniq; -} - -function updateHitURL(hit) { - - var words = matchedWords(hit); - var url = ""; - - if (hit.anchor) { - url = hit.url_without_anchor + '?q=' + escape(words.join(" ")) + '#' + hit.anchor; - } else { - url = hit.url + '?q=' + escape(words.join(" ")); - } - - return url; -} diff --git a/docs/index.html b/docs/index.html deleted file mode 100644 index b750a3aa..00000000 --- a/docs/index.html +++ /dev/null @@ -1,383 +0,0 @@ - - - - - - - -Simple Tools for Examining and Cleaning Dirty Data • janitor - - - - - - - - - - -
    -
    - - - - -
    -
    -
    - -
    -

    Data scientists, according to interviews and expert estimates, spend from 50 percent to 80 percent of their time mired in this more mundane labor of collecting and preparing unruly digital data, before it can be explored for useful nuggets.

    -

    – “For Big-Data Scientists, ‘Janitor Work’ Is Key Hurdle to Insight“ - The New York Times, 2014

    -
    -
    -

    Travis-CI Build Status Coverage Status lifecycle CRAN_Status_Badge !Monthly Downloads!Downloads

    -

    janitor has simple functions for examining and cleaning dirty data. It was built with beginning and intermediate R users in mind and is optimized for user-friendliness. Advanced R users can already do everything covered here, but with janitor they can do it faster and save their thinking for the fun stuff.

    -

    The main janitor functions:

    -
      -
    • perfectly format data.frame column names;
    • -
    • create and format frequency tables of one, two, or three variables - think an improved table(); and
    • -
    • isolate partially-duplicate records.
    • -
    -

    The tabulate-and-report functions approximate popular features of SPSS and Microsoft Excel.

    -

    janitor is a #tidyverse-oriented package. Specifically, it plays nicely with the %>% pipe and is optimized for cleaning data brought in with the readr and readxl packages.

    -
    -

    - Getting Started

    -

    You can install:

    - -
    -
    -

    - janitor 2.0.0 is out!

    -

    This marks a major release for janitor, with many new functions and some breaking changes that may affect existing code. Please see the NEWS page to learn more about new capabilities.

    -
    -
    -

    -Using janitor

    -

    A full description of each function, organized by topic, can be found in janitor’s catalog of functions vignette. There you will find functions not mentioned in this README, like compare_df_cols() which provides a summary of differences in column names and types when given a set of data.frames.

    -

    Below are quick examples of how janitor tools are commonly used.

    -
    -

    -Cleaning dirty data

    -

    Take this roster of teachers at a fictional American high school, stored in the Microsoft Excel file dirty_data.xlsx: All kinds of dirty.

    -

    Dirtiness includes:

    -
      -
    • Dreadful column names
    • -
    • Rows and columns containing Excel formatting but no data
    • -
    • Dates stored as numbers
    • -
    • Values spread inconsistently over the “Certification” columns
    • -
    -

    Here’s that data after being read in to R:

    -
    library(readxl); library(janitor); library(dplyr); library(here)
    -
    -roster_raw <- read_excel(here("dirty_data.xlsx")) # available at http://github.com/sfirke/janitor
    -glimpse(roster_raw)
    -#> Rows: 13
    -#> Columns: 11
    -#> $ `First Name`        <chr> "Jason", "Jason", "Alicia", "Ada", "Desus", "Chien-Shiung", "Chien-Shiung", NA,…
    -#> $ `Last Name`         <chr> "Bourne", "Bourne", "Keys", "Lovelace", "Nice", "Wu", "Wu", NA, "Joyce", "Lamar…
    -#> $ `Employee Status`   <chr> "Teacher", "Teacher", "Teacher", "Teacher", "Administration", "Teacher", "Teach…
    -#> $ Subject             <chr> "PE", "Drafting", "Music", NA, "Dean", "Physics", "Chemistry", NA, "English", "…
    -#> $ `Hire Date`         <dbl> 39690, 39690, 37118, 27515, 41431, 11037, 11037, NA, 32994, 27919, 42221, 34700…
    -#> $ `% Allocated`       <dbl> 0.75, 0.25, 1.00, 1.00, 1.00, 0.50, 0.50, NA, 0.50, 0.50, NA, NA, 0.80
    -#> $ `Full time?`        <chr> "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", NA, "No", "No", "No", "No", "N…
    -#> $ `do not edit! --->` <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA
    -#> $ Certification...9   <chr> "Physical ed", "Physical ed", "Instr. music", "PENDING", "PENDING", "Science 6-…
    -#> $ Certification...10  <chr> "Theater", "Theater", "Vocal music", "Computers", NA, "Physics", "Physics", NA,…
    -#> $ Certification...11  <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA
    -

    Excel formatting led to an untitled empty column and 5 empty rows at the bottom of the table (only 12 records have any actual data). Bad column names are preserved.

    -

    Name cleaning comes in two flavors. make_clean_names() operates on character vectors and can be used during data import:

    -
    roster_raw_cleaner <- read_excel(here("dirty_data.xlsx"),
    -                                 .name_repair = make_clean_names)
    -# Tells read_excel() how to repair repetitive column names, overriding the
    -# default repair setting
    -glimpse(roster_raw_cleaner)
    -#> Rows: 13
    -#> Columns: 11
    -#> $ first_name        <chr> "Jason", "Jason", "Alicia", "Ada", "Desus", "Chien-Shiung", "Chien-Shiung", NA, "…
    -#> $ last_name         <chr> "Bourne", "Bourne", "Keys", "Lovelace", "Nice", "Wu", "Wu", NA, "Joyce", "Lamarr"…
    -#> $ employee_status   <chr> "Teacher", "Teacher", "Teacher", "Teacher", "Administration", "Teacher", "Teacher…
    -#> $ subject           <chr> "PE", "Drafting", "Music", NA, "Dean", "Physics", "Chemistry", NA, "English", "Sc…
    -#> $ hire_date         <dbl> 39690, 39690, 37118, 27515, 41431, 11037, 11037, NA, 32994, 27919, 42221, 34700, …
    -#> $ percent_allocated <dbl> 0.75, 0.25, 1.00, 1.00, 1.00, 0.50, 0.50, NA, 0.50, 0.50, NA, NA, 0.80
    -#> $ full_time         <chr> "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", "Yes", NA, "No", "No", "No", "No", "No"
    -#> $ do_not_edit       <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA
    -#> $ certification     <chr> "Physical ed", "Physical ed", "Instr. music", "PENDING", "PENDING", "Science 6-12…
    -#> $ certification_2   <chr> "Theater", "Theater", "Vocal music", "Computers", NA, "Physics", "Physics", NA, "…
    -#> $ certification_3   <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA
    -

    This can be further cleaned:

    -
    roster <- roster_raw_cleaner %>%
    -  remove_empty(c("rows", "cols")) %>%
    -  mutate(hire_date = excel_numeric_to_date(hire_date),
    -         cert = coalesce(certification, certification_2)) %>% # from dplyr
    -  select(-certification, -certification_2) # drop unwanted columns
    -
    -roster
    -#> # A tibble: 12 x 8
    -#>    first_name   last_name employee_status subject    hire_date  percent_allocated full_time cert          
    -#>    <chr>        <chr>     <chr>           <chr>      <date>                 <dbl> <chr>     <chr>         
    -#>  1 Jason        Bourne    Teacher         PE         2008-08-30              0.75 Yes       Physical ed   
    -#>  2 Jason        Bourne    Teacher         Drafting   2008-08-30              0.25 Yes       Physical ed   
    -#>  3 Alicia       Keys      Teacher         Music      2001-08-15              1    Yes       Instr. music  
    -#>  4 Ada          Lovelace  Teacher         <NA>       1975-05-01              1    Yes       PENDING       
    -#>  5 Desus        Nice      Administration  Dean       2013-06-06              1    Yes       PENDING       
    -#>  6 Chien-Shiung Wu        Teacher         Physics    1930-03-20              0.5  Yes       Science 6-12  
    -#>  7 Chien-Shiung Wu        Teacher         Chemistry  1930-03-20              0.5  Yes       Science 6-12  
    -#>  8 James        Joyce     Teacher         English    1990-05-01              0.5  No        English 6-12  
    -#>  9 Hedy         Lamarr    Teacher         Science    1976-06-08              0.5  No        PENDING       
    -#> 10 Carlos       Boozer    Coach           Basketball 2015-08-05             NA    No        Physical ed   
    -#> 11 Young        Boozer    Coach           <NA>       1995-01-01             NA    No        Political sci.
    -#> 12 Micheal      Larsen    Teacher         English    2009-09-15              0.8  No        Vocal music
    -

    clean_names() is a convenience version that can be used for piped data.frame workflows:

    -
    data("iris")
    -names(iris) # before cleaning:
    -#> [1] "Sepal.Length" "Sepal.Width"  "Petal.Length" "Petal.Width"  "Species"
    -
    -iris %>%
    -  clean_names() %>%
    -  names() # after cleaning:
    -#> [1] "sepal_length" "sepal_width"  "petal_length" "petal_width"  "species"
    -
    -
    -

    -Examining dirty data

    -
    -

    -Finding duplicates

    -

    Use get_dupes() to identify and examine duplicate records during data cleaning. Let’s see if any teachers are listed more than once:

    -
    roster %>% get_dupes(contains("name"))
    -#> # A tibble: 4 x 9
    -#>   first_name   last_name dupe_count employee_status subject   hire_date  percent_allocat… full_time cert      
    -#>   <chr>        <chr>          <int> <chr>           <chr>     <date>                <dbl> <chr>     <chr>     
    -#> 1 Chien-Shiung Wu                 2 Teacher         Physics   1930-03-20             0.5  Yes       Science 6…
    -#> 2 Chien-Shiung Wu                 2 Teacher         Chemistry 1930-03-20             0.5  Yes       Science 6…
    -#> 3 Jason        Bourne             2 Teacher         PE        2008-08-30             0.75 Yes       Physical …
    -#> 4 Jason        Bourne             2 Teacher         Drafting  2008-08-30             0.25 Yes       Physical …
    -

    Yes, some teachers appear twice. We ought to address this before counting employees.

    -
    -
    -

    -Tabulating tools

    -

    A variable (or combinations of two or three variables) can be tabulated with tabyl(). The resulting data.frame can be tweaked and formatted with the suite of adorn_ functions for quick analysis and printing of pretty results in a report. adorn_ functions can be helpful with non-tabyls, too.

    -

    tabyl can be called two ways:

    -
      -
    • On a vector, when tabulating a single variable - e.g., tabyl(roster$subject) -
    • -
    • On a data.frame, specifying 1, 2, or 3 variable names to tabulate : roster %>% tabyl(subject, employee_status). -
        -
      • Here the data.frame is passed in with the %>% pipe; this allows tabyl to be used in an analysis pipeline
      • -
      -
    • -
    -
    -
    -

    -tabyl()

    -

    Like table(), but pipe-able, data.frame-based, and fully featured.

    -

    One variable:

    -
    roster %>%
    -  tabyl(subject)
    -#>     subject n    percent valid_percent
    -#>  Basketball 1 0.08333333           0.1
    -#>   Chemistry 1 0.08333333           0.1
    -#>        Dean 1 0.08333333           0.1
    -#>    Drafting 1 0.08333333           0.1
    -#>     English 2 0.16666667           0.2
    -#>       Music 1 0.08333333           0.1
    -#>          PE 1 0.08333333           0.1
    -#>     Physics 1 0.08333333           0.1
    -#>     Science 1 0.08333333           0.1
    -#>        <NA> 2 0.16666667            NA
    -

    Two variables:

    -
    roster %>%
    -  filter(hire_date > as.Date("1950-01-01")) %>%
    -  tabyl(employee_status, full_time)
    -#>  employee_status No Yes
    -#>   Administration  0   1
    -#>            Coach  2   0
    -#>          Teacher  3   4
    -

    Three variables:

    -
    roster %>%
    -  tabyl(full_time, subject, employee_status, show_missing_levels = FALSE)
    -#> $Administration
    -#>  full_time Dean
    -#>        Yes    1
    -#> 
    -#> $Coach
    -#>  full_time Basketball NA_
    -#>         No          1   1
    -#> 
    -#> $Teacher
    -#>  full_time Chemistry Drafting English Music PE Physics Science NA_
    -#>         No         0        0       2     0  0       0       1   0
    -#>        Yes         1        1       0     1  1       1       0   1
    -

    Adorning tabyls

    -

    The adorn_ functions dress up the results of these tabulation calls for fast, basic reporting. Here are some of the functions that augment a summary table for reporting:

    -
    roster %>%
    -  tabyl(employee_status, full_time) %>%
    -  adorn_totals("row") %>%
    -  adorn_percentages("row") %>%
    -  adorn_pct_formatting() %>%
    -  adorn_ns() %>%
    -  adorn_title("combined")
    -#>  employee_status/full_time         No        Yes
    -#>             Administration   0.0% (0) 100.0% (1)
    -#>                      Coach 100.0% (2)   0.0% (0)
    -#>                    Teacher  33.3% (3)  66.7% (6)
    -#>                      Total  41.7% (5)  58.3% (7)
    -

    Pipe that right into knitr::kable() in your RMarkdown report.

    -

    These modular adornments can be layered to reduce R’s deficit against Excel and SPSS when it comes to quick, informative counts. Learn more about tabyl() and the adorn_ functions from the tabyls vignette.

    -
    -
    -
    -
    -

    - Contact Me

    -

    You are welcome to:

    - -
    -
    -
    - - -
    - - -
    - -
    -

    Site built with pkgdown 1.5.0.

    -
    - -
    -
    - - - - - - diff --git a/docs/issue_template.html b/docs/issue_template.html deleted file mode 100644 index ce4dc689..00000000 --- a/docs/issue_template.html +++ /dev/null @@ -1,179 +0,0 @@ - - - - - - - - -NA • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - -
    -
    - - - -
    -

    -Feature requests

    -

    Briefly describe what the feature would do and why it is in scope for the janitor package.

    -
    -
    -

    -Bug reports

    -

    Please briefly describe your problem and what output you expect.

    -

    Please include a minimal reprex. The goal of a reprex is to make it as easy as possible for me to recreate your problem so that I can fix it. If you’ve never heard of a reprex before, start by reading https://github.com/jennybc/reprex#what-is-a-reprex, and follow the advice further down the page.

    -

    Delete these instructions once you have read them.

    -
    -

    Brief description of the problem

    -
    # insert reprex here
    -
    - - -
    - - - -
    - - - -
    - - -
    -

    Site built with pkgdown 1.5.0.

    -
    - -
    -
    - - - - - - - - diff --git a/docs/jquery.sticky-kit.min.js b/docs/jquery.sticky-kit.min.js deleted file mode 100644 index e2a3c6de..00000000 --- a/docs/jquery.sticky-kit.min.js +++ /dev/null @@ -1,9 +0,0 @@ -/* - Sticky-kit v1.1.2 | WTFPL | Leaf Corcoran 2015 | http://leafo.net -*/ -(function(){var b,f;b=this.jQuery||window.jQuery;f=b(window);b.fn.stick_in_parent=function(d){var A,w,J,n,B,K,p,q,k,E,t;null==d&&(d={});t=d.sticky_class;B=d.inner_scrolling;E=d.recalc_every;k=d.parent;q=d.offset_top;p=d.spacer;w=d.bottoming;null==q&&(q=0);null==k&&(k=void 0);null==B&&(B=!0);null==t&&(t="is_stuck");A=b(document);null==w&&(w=!0);J=function(a,d,n,C,F,u,r,G){var v,H,m,D,I,c,g,x,y,z,h,l;if(!a.data("sticky_kit")){a.data("sticky_kit",!0);I=A.height();g=a.parent();null!=k&&(g=g.closest(k)); -if(!g.length)throw"failed to find stick parent";v=m=!1;(h=null!=p?p&&a.closest(p):b("
    "))&&h.css("position",a.css("position"));x=function(){var c,f,e;if(!G&&(I=A.height(),c=parseInt(g.css("border-top-width"),10),f=parseInt(g.css("padding-top"),10),d=parseInt(g.css("padding-bottom"),10),n=g.offset().top+c+f,C=g.height(),m&&(v=m=!1,null==p&&(a.insertAfter(h),h.detach()),a.css({position:"",top:"",width:"",bottom:""}).removeClass(t),e=!0),F=a.offset().top-(parseInt(a.css("margin-top"),10)||0)-q, -u=a.outerHeight(!0),r=a.css("float"),h&&h.css({width:a.outerWidth(!0),height:u,display:a.css("display"),"vertical-align":a.css("vertical-align"),"float":r}),e))return l()};x();if(u!==C)return D=void 0,c=q,z=E,l=function(){var b,l,e,k;if(!G&&(e=!1,null!=z&&(--z,0>=z&&(z=E,x(),e=!0)),e||A.height()===I||x(),e=f.scrollTop(),null!=D&&(l=e-D),D=e,m?(w&&(k=e+u+c>C+n,v&&!k&&(v=!1,a.css({position:"fixed",bottom:"",top:c}).trigger("sticky_kit:unbottom"))),eb&&!v&&(c-=l,c=Math.max(b-u,c),c=Math.min(q,c),m&&a.css({top:c+"px"})))):e>F&&(m=!0,b={position:"fixed",top:c},b.width="border-box"===a.css("box-sizing")?a.outerWidth()+"px":a.width()+"px",a.css(b).addClass(t),null==p&&(a.after(h),"left"!==r&&"right"!==r||h.append(a)),a.trigger("sticky_kit:stick")),m&&w&&(null==k&&(k=e+u+c>C+n),!v&&k)))return v=!0,"static"===g.css("position")&&g.css({position:"relative"}), -a.css({position:"absolute",bottom:d,top:"auto"}).trigger("sticky_kit:bottom")},y=function(){x();return l()},H=function(){G=!0;f.off("touchmove",l);f.off("scroll",l);f.off("resize",y);b(document.body).off("sticky_kit:recalc",y);a.off("sticky_kit:detach",H);a.removeData("sticky_kit");a.css({position:"",bottom:"",top:"",width:""});g.position("position","");if(m)return null==p&&("left"!==r&&"right"!==r||a.insertAfter(h),h.remove()),a.removeClass(t)},f.on("touchmove",l),f.on("scroll",l),f.on("resize", -y),b(document.body).on("sticky_kit:recalc",y),a.on("sticky_kit:detach",H),setTimeout(l,0)}};n=0;for(K=this.length;n - - - - - diff --git a/docs/news/index.html b/docs/news/index.html deleted file mode 100644 index baafbe5a..00000000 --- a/docs/news/index.html +++ /dev/null @@ -1,584 +0,0 @@ - - - - - - - - -Changelog • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - -
    -
    - - -
    -

    -janitor 2.0.1 (2020-04-12) 2020-04-12 -

    -
    -

    -Bug fixes and Breaking changes

    -

    Transliteration of characters within make_clean_names() now operates across operating systems, independent of differences in stringi installations (Fix #365, thanks to @eamoncaddigan for reporting and @billdenney for fixing).

    -

    This bug patch represents a breaking change with the way that make_clean_names() worked in janitor versions 1.2.1.9000 and 2.0.0 as the transliterations are now more generalized and follow a more best-practice approach to transliterating to ASCII.

    -
    -
    -
    -

    -janitor 2.0.0 (2020-04-07) 2020-04-08 -

    -
    -

    -Breaking changes

    -
      -
    • -clean_names() and make_clean_names() are now more locale-independent and translation to ASCII is simpler (in many cases, Unicode is removed, e.g., the Greek character “delta” becomes a “d”). You may also now control how substitutions occur and add your own substitutions (like “%” becoming “percent”). As a result of these changes, the clean names generated by these functions may break with what was produced in prior versions of janitor. (Fix #331, thanks to @billdenney)
    • -
    -

    As part of the improvements to make_clean_names() and clean_names(), the ... argument was added, allowing the user to pass additional information to the underlying transformation function from the snakecase package, to_any_case(). This allows for greater user control of clean_names() / make_clean_names() and for new functionality like specifying case = "title" for transforming variable names back to title case for making plots.

    -
      -
    • The adorn_* family of functions now allows control of columns to be adorned using the ... argument. This often-requested feature results in a small breakage as the now-redundant argument skip_first_col in adorn_percentages() was removed.

    • -
    • Obsolete functions were deprecated: crosstab, adorn_crosstab, use_first_valid_of, convert_to_NA, remove_empty_cols, remove_empty_rows, add_totals_col, add_totals_row.

    • -
    -
    -
    -

    -Major features

    - -
    -
    -

    -Minor features

    -
      -
    • A quiet argument was added to remove_empty() and remove_constant() providing more information when quiet = 'FALSE' (#70, thanks to @jbkunst for suggesting and @billdenney for implementing).

    • -
    • row_to_names() works on matrix input (#320, thanks to @billdenney for suggesting and implementing

    • -
    • clean_names() can now be called on tbl_graph objects from the tidygraph package. (#252, thanks to @gvdr for bringing up the issue and thanks to @Tazinho for proposing solution).

    • -
    -
    -
    -

    -Bug fixes

    -
      -
    • adorn_ns() doesn’t append anything to character columns when called on a data.frame resulting from a call to adorn_percentages(). (#195).

    • -
    • The name argument to adorn_totals() is correctly applied to 3-way tabyls (#306) (thanks to @jzadra for reporting).

    • -
    • adorn_rounding() now works when called on a 3-way tabyl.

    • -
    • remove_constant() works correctly with tibbles (in addition to already working on data.frames and matrices) (thanks to @billdenney for implementing).

    • -
    • get_dupes() works when called on a grouped tibble (#329) (thanks to @jzadra for fixing).

    • -
    • When the second variable in a tabyl (the column variable) contains the empty string "", it is converted to "emptystring_ before being spread to the tabyl’s column names. Previously it became the default variable name V1. (#203).

    • -
    • Behind-the-scenes code changes to maintain compatibility with breaking changes to dplyr 1.0.0, tibble 3.0.0, and R 4.0.0.

    • -
    -
    -
    -
    -

    -janitor 1.2.1 (2020-01-22) 2020-01-22 -

    -

    Adjusted a single test to account for a different error message produced by the tidyselect package. No changes to package functionality.

    -
    -
    -

    -janitor 1.2.0 (2019-04-20) 2019-04-21 -

    -
    -

    -Major features

    -
      -
    • The new function make_clean_names() takes a character vector and returns the cleaned text, with the same functionality as the existing clean_names(), which runs on a data.frame, manipulating its names. (#197, thanks @tazinho and everyone who contributed to the discussion).
    • -
    -

    This function can be supplied as a value for the .name_repair argument of as_tibble() in the tibble package. For example: as_tibble(iris, .name_repair = make_clean_names).

    -
      -
    • The new function compare_df_cols() compares the names and classes of columns in a set of supplied data.frames or tibbles, reporting on the specific columns that are or are not similar. This is for the common use case where a set of data files should all have the same specifications but, in practice, may not. A companion function compare_df_cols_same() gives a TRUE/FALSE result indicating if the columns are the same (and therefore bindable, though FALSE is not definitive that binding will fail).

    • -
    • Its helper function describe_class() is exported for developers who wish to extend it so that the compare_df_ functions treat their custom classes appropriately.

    • -
    -

    This feature (#50) took almost 3 years from conception to implementation. Major thanks to @billdenney for making it happen!

    -
      -
    • A new function round_to_fraction() allows rounding to a fraction with specified denominator, e.g., to the nearest 1/7 (#235, thanks to @billdenney for suggesting & implementing).

    • -
    • The functions janitor::chisq.test() and janitor::fisher.test() to enable running these statistical tests from the base stats package on two-way tabyl objects. While the package loading message says the base functions are masked, the base tests still run on table objects (#255, thanks @juba for implementing).

    • -
    • remove_empty() now has a companion function remove_constant() which removes columns containing only a single unique value, optionally ignoring NA (#222, thanks to @billdenney for suggesting & implementing).

    • -
    -
    -
    -

    -Minor features

    -
      -
    • excel_numeric_to_date() now returns a POSIXct object and includes a time zone. (#225, thanks to @billdenney for the feature.)

    • -
    • clean_names() can now be called on a simple features object from the sf package. (#247, thanks to @JosiahParry for suggesting & implementing.)

    • -
    • adorn_totals() gains an argument "name" that allows the user to specify a value other than “Total” to appear as the name of the added row and/or column (#263). Thanks to @StephieLaPugh for suggesting and @daniel-barnett for implementing.

    • -
    • remove_empty() and remove_constant() now work with matrices (returning a matrix). (#215) Thanks to @jsta for reporting and @billdenney for patching.

    • -
    • If the third variable in a three-way tabyl is a factor, the resulting list is sorted in order of its levels (#250). Empty factor levels in the 3rd variable are still omitted regardless of the value of show_missing_levels.

    • -
    -
    -
    -

    -Bug fixes

    - -
    -
    -
    -

    -janitor 1.1.1 (2018-07-30) 2018-07-31 -

    -
    -

    -Release summary

    -

    Patches a bug introduced in version 1.1.0 where excel_numeric_to_date() would fail if given an input vector containing an NA value.

    -
    -
    -

    -Bug fixes

    -
      -
    • -excel_numeric_to_date() again handles NA correctly, in version 1.1.0 the function would error if any values of the input vector were NA. (#220). Thanks @emilelatour for reporting and @billdenney for patching.
    • -
    -
    -
    -
    -

    -janitor 1.1.0 (2018-07-17) 2018-07-18 -

    -
    -

    -Release summary

    -

    This release was requested by CRAN to address some minor package dependency issues. It also contains several updates and additions described below.

    -
    -
    -

    -Major features

    -

    The new function row_to_names() handles the case where a dirty data file is read in with its names stored as a row of the data.frame, rather than in the names. This function sets the names of the data.frame to this row and optionally cleans up the rows above and including where the names were stored. Thanks to @billdenney for writing this feature.

    -
    -
    -

    -Minor features

    -

    excel_numeric_to_date() can now convert fractions of a day to time, e.g., excel_numeric_to_date(43001.01, include_time = TRUE) returns the POSIXlt value "2017-09-23 00:14:24". Thanks to @billdenney.

    -
    -
    -

    -Breaking changes

    -

    As part of excel_numeric_to_date() now handling times, if a Date-only result is requested (the default behavior of include_time = FALSE), any fractional part of the date is now removed. The printed date itself is identical, but the internal representation of this object now contains only the integer part of the date. For example, while under both the old and new versions of this function the call excel_numeric_to_date_old(42001.1) would return the Date object "2014-12-28", calling as.numeric on this Date result would previously return 16432.1, while now it returns 16432.

    -

    This an improved behavior, as now excel_numeric_to_date(42001.1, include_time = FALSE) == as.Date("2014-12-28") returns TRUE, while previously it would appear to be equivalent from the printed value but this comparison would return FALSE.

    -
    -
    -
    -

    -janitor 1.0.0 (2018-03-17) 2018-03-22 -

    -
    -

    -Release summary

    -

    A stable version 1.0.0, with a new tabyl API and with breaking changes to the output of clean_names().

    -

    This builds on the original functionality of janitor, with similar-but-improved tools and significantly-changed implementation.

    -
    -
    -

    -Breaking changes

    -
    -

    -A fully-overhauled tabyl -

    -

    tabyl() is now a single function that can count combinations of one, two, or three variables, ala base R’s table(). The resulting tabyl data.frames can be manipulated and formatted using a family of adorn_ functions. See the tabyls vignette for more.

    -

    The now-redundant legacy functions crosstab() and adorn_crosstab() have been deprecated, but remain in the package for now. Existing code that relies on the version of tabyl present in janitor versions <= 0.3.1 will break if the sort argument was used, as that argument no longer exists in tabyl (use dplyr::arrange() instead).

    -
    -
    -

    -Improvements to clean_names -

    -

    clean_names() now detects and preserves camelCase inputs, allows multiple options for case outputs of the cleaned names, and preserves whether there’s space between letters and numbers. It also transliterates accented letters and turns # into "number".

    -

    These changes may cause old code to break. E.g., a raw column name variableName would now be converted to variable_name (or variableName, VariableName, etc. depending on your preference), where previously it would have been converted to variablename.

    -

    To minimize this inconvenience, there’s a quick fix for compatibility: you can find-and-replace to insert the argument case = "old_janitor", preserving the old behavior of clean_names() as of janitor version 0.3.1 (and thus not have to redo your scripts beyond that.)

    -

    No further changes are planned to clean_names() and its results should be stable from version 1.0.0 onward.

    -
    -
    -
    -

    -Major features

    -
      -
    • clean_names() transliterates accented letters, e.g., çãüœ becomes cauoe (#120). Thanks to @fernandovmacedo.

    • -
    • -clean_names() offers multiple options for variable name styling. In addition to snake_case output you can select smallCamelCase, BigCamelCase, ALL_CAPS and others. (#131).
    • -
    • Thanks to @tazinho, who wrote the snakecase package that janitor depends on to do this, as well as the patch to incorporate it into clean_names(). And thanks to @maelle for proposing this feature.

    • -
    • Launched the janitor documentation website: http://sfirke.github.io/janitor. Thanks to the pkgdown package.

    • -
    • Deprecated the functions remove_empty_rows() and remove_empty_cols(), which are replaced by the single function remove_empty(). (#100) -
    • -
    • To encourage transparency, remove_empty() prints a message if no value is supplied for the which argument; to suppress this, supply a value to which, even if it’s the default c("rows", "cols").

    • -
    • The new adorn_title() function adds the name of the 2nd tabyl variable (i.e., the name of the column variable). This un-tidies the data.frame but makes the result clearer to readers (#77)

    • -
    -
    -
    -

    -Minor features

    - -
    -
    -

    -Bug fixes

    - -
    -
    -
    -
    -

    -janitor 0.3.1 (2018-01-04) 2018-01-04 -

    -
    -

    -Release summary

    -

    This is a bug-fix release with no new functionality or changes. It fixes a bug where adorn_crosstab() failed if the tibble package was version > 1.4.

    -

    Major changes to janitor are currently in development on GitHub and will be released soon. This is not that next big release.

    -
    -
    -
    -
    -

    -janitor 0.3.0 (2017-05-06) 2017-05-06 -

    -
    -

    -Release summary

    -

    The primary purpose of this release is to maintain accuracy given breaking changes to the dplyr package, upon which janitor is built, in dplyr version >0.6.0. This update also contains a number of minor improvements.

    -

    Critical: if you update the package dplyr to version >0.6.0, you must update janitor to version 0.3.0 to ensure accurate results from janitor’s tabyl() function. This is due to a change in the behavior of dplyr’s _join functions (discussed in #111).

    -

    janitor 0.3.0 is compatible with this new version of dplyr as well as old versions of dplyr back to 0.5.0. That is, updating janitor to 0.3.0 does not necessitate an update to dplyr >0.6.0.

    -
    -
    -

    -Breaking changes

    -
      -
    • The functions add_totals_row and add_totals_col were combined into a single function, adorn_totals(). (#57). The add_totals_ functions are now deprecated and should not be used.
    • -
    • The first argument of adorn_crosstab() is now “dat” instead of “crosstab” (indicating that the function can be called on any data.frame, not just a result of crosstab())
    • -
    -
    -
    -

    -Major features

    -
      -
    • Exported the %>% pipe from magrittr (#107).
    • -
    -

    Deprecated the following functions:

    - -
    -
    -

    -Minor features

    -
      -
    • -adorn_totals() and ns_to_percents() can now be called on data.frames that have non-numeric columns beyond the first one (those columns will be ignored) (#57) -
    • -
    • -adorn_totals("col") retains factor class in 1st column if 1st column in the input data.frame was a factor
    • -
    -
    -
    -

    -Bug fixes

    - -
    -
    -
    -
    -

    -janitor 0.2.1 (2016-10-30) 2016-10-31 -

    -
    -

    -Bug fixes

    - -
    -
    -
    -
    -

    -janitor 0.2.0 (2016-10-03) 2016-10-03 -

    -
    -

    -Features

    -
    -

    -Major

    -

    Submitted to CRAN!

    -
    -
    -

    -Minor

    -
      -
    • The count in tabyl() for factor levels that aren’t present is now 0 instead of NA (#48) -
    • -
    -
    -
    -
    -

    -Bug fixes

    -
      -
    • Can call tabyl() on the result of a tabyl(), e.g., mtcars %>% tabyl(mpg) %>% tabyl(n) (#54) -
    • -
    • -get_dupes() now works on variables with spaces in column names (#62) -
    • -
    -
    -
    -

    -Package management

    -
      -
    • Reached 100% unit test code coverage
    • -
    -
    -
    -
    -
    -

    -janitor 0.1.2 Unreleased -

    -
    -

    -Features

    -
    -

    -Major

    -
      -
    • Added a function adorn_crosstab() that formats the results of a crosstab() for pretty printing. Shows % and N in the same cell, with the % symbol, user-specified rounding (method and number of digits), and the option to include a totals row and/or column. E.g., mtcars %>% crosstab(cyl, gear) %>% adorn_crosstab().
    • -
    • -crosstab() can be called in a %>% pipeline, e.g., mtcars %>% crosstab(cyl, gear). Thanks to @chrishaid (#34) -
    • -
    • -tabyl() can also be called in a %>% pipeline, e.g., mtcars %>% tabyl(cyl) (#35) -
    • -
    • Added use_first_valid_of() function (#32) -
    • -
    • Added minor functions for manipulating numeric data.frames for presentation: ns_to_percents(), add_totals_row(), add_totals_col(),
    • -
    -
    -
    -

    -Minor

    -
      -
    • -crosstab() returns 0 instead of NA when there are no instances of a variable combination.
    • -
    • A call like tabyl(df$vecname) retains the more-descriptive $ symbol in the column name of the result - if you want a legal R name in the result, call it as df %>% tabyl(vecname) -
    • -
    • Single and double quotation marks are handled by clean_names() -
    • -
    -
    -
    -
    -

    -Package management

    -
      -
    • Added codecov to measure test coverage
    • -
    • Added unit test coverage
    • -
    • Added Travis-CI for continuous integration
    • -
    -
    -
    -
    -
    -

    -janitor 0.1 (2016-04-17) Unreleased -

    -
      -
    • Initial draft of skeleton package on GitHub
    • -
    -
    -
    - - - -
    - - -
    - - -
    -

    Site built with pkgdown 1.5.0.

    -
    - -
    -
    - - - - - - - - diff --git a/docs/pkgdown.css b/docs/pkgdown.css deleted file mode 100644 index c01e5923..00000000 --- a/docs/pkgdown.css +++ /dev/null @@ -1,367 +0,0 @@ -/* Sticky footer */ - -/** - * Basic idea: https://philipwalton.github.io/solved-by-flexbox/demos/sticky-footer/ - * Details: https://github.com/philipwalton/solved-by-flexbox/blob/master/assets/css/components/site.css - * - * .Site -> body > .container - * .Site-content -> body > .container .row - * .footer -> footer - * - * Key idea seems to be to ensure that .container and __all its parents__ - * have height set to 100% - * - */ - -html, body { - height: 100%; -} - -body { - position: relative; -} - -body > .container { - display: flex; - height: 100%; - flex-direction: column; -} - -body > .container .row { - flex: 1 0 auto; -} - -footer { - margin-top: 45px; - padding: 35px 0 36px; - border-top: 1px solid #e5e5e5; - color: #666; - display: flex; - flex-shrink: 0; -} -footer p { - margin-bottom: 0; -} -footer div { - flex: 1; -} -footer .pkgdown { - text-align: right; -} -footer p { - margin-bottom: 0; -} - -img.icon { - float: right; -} - -img { - max-width: 100%; -} - -/* Fix bug in bootstrap (only seen in firefox) */ -summary { - display: list-item; -} - -/* Typographic tweaking ---------------------------------*/ - -.contents .page-header { - margin-top: calc(-60px + 1em); -} - -dd { - margin-left: 3em; -} - -/* Section anchors ---------------------------------*/ - -a.anchor { - margin-left: -30px; - display:inline-block; - width: 30px; - height: 30px; - visibility: hidden; - - background-image: url(./link.svg); - background-repeat: no-repeat; - background-size: 20px 20px; - background-position: center center; -} - -.hasAnchor:hover a.anchor { - visibility: visible; -} - -@media (max-width: 767px) { - .hasAnchor:hover a.anchor { - visibility: hidden; - } -} - - -/* Fixes for fixed navbar --------------------------*/ - -.contents h1, .contents h2, .contents h3, .contents h4 { - padding-top: 60px; - margin-top: -40px; -} - -/* Navbar submenu --------------------------*/ - -.dropdown-submenu { - position: relative; -} - -.dropdown-submenu>.dropdown-menu { - top: 0; - left: 100%; - margin-top: -6px; - margin-left: -1px; - border-radius: 0 6px 6px 6px; -} - -.dropdown-submenu:hover>.dropdown-menu { - display: block; -} - -.dropdown-submenu>a:after { - display: block; - content: " "; - float: right; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; - border-width: 5px 0 5px 5px; - border-left-color: #cccccc; - margin-top: 5px; - margin-right: -10px; -} - -.dropdown-submenu:hover>a:after { - border-left-color: #ffffff; -} - -.dropdown-submenu.pull-left { - float: none; -} - -.dropdown-submenu.pull-left>.dropdown-menu { - left: -100%; - margin-left: 10px; - border-radius: 6px 0 6px 6px; -} - -/* Sidebar --------------------------*/ - -#pkgdown-sidebar { - margin-top: 30px; - position: -webkit-sticky; - position: sticky; - top: 70px; -} - -#pkgdown-sidebar h2 { - font-size: 1.5em; - margin-top: 1em; -} - -#pkgdown-sidebar h2:first-child { - margin-top: 0; -} - -#pkgdown-sidebar .list-unstyled li { - margin-bottom: 0.5em; -} - -/* bootstrap-toc tweaks ------------------------------------------------------*/ - -/* All levels of nav */ - -nav[data-toggle='toc'] .nav > li > a { - padding: 4px 20px 4px 6px; - font-size: 1.5rem; - font-weight: 400; - color: inherit; -} - -nav[data-toggle='toc'] .nav > li > a:hover, -nav[data-toggle='toc'] .nav > li > a:focus { - padding-left: 5px; - color: inherit; - border-left: 1px solid #878787; -} - -nav[data-toggle='toc'] .nav > .active > a, -nav[data-toggle='toc'] .nav > .active:hover > a, -nav[data-toggle='toc'] .nav > .active:focus > a { - padding-left: 5px; - font-size: 1.5rem; - font-weight: 400; - color: inherit; - border-left: 2px solid #878787; -} - -/* Nav: second level (shown on .active) */ - -nav[data-toggle='toc'] .nav .nav { - display: none; /* Hide by default, but at >768px, show it */ - padding-bottom: 10px; -} - -nav[data-toggle='toc'] .nav .nav > li > a { - padding-left: 16px; - font-size: 1.35rem; -} - -nav[data-toggle='toc'] .nav .nav > li > a:hover, -nav[data-toggle='toc'] .nav .nav > li > a:focus { - padding-left: 15px; -} - -nav[data-toggle='toc'] .nav .nav > .active > a, -nav[data-toggle='toc'] .nav .nav > .active:hover > a, -nav[data-toggle='toc'] .nav .nav > .active:focus > a { - padding-left: 15px; - font-weight: 500; - font-size: 1.35rem; -} - -/* orcid ------------------------------------------------------------------- */ - -.orcid { - font-size: 16px; - color: #A6CE39; - /* margins are required by official ORCID trademark and display guidelines */ - margin-left:4px; - margin-right:4px; - vertical-align: middle; -} - -/* Reference index & topics ----------------------------------------------- */ - -.ref-index th {font-weight: normal;} - -.ref-index td {vertical-align: top;} -.ref-index .icon {width: 40px;} -.ref-index .alias {width: 40%;} -.ref-index-icons .alias {width: calc(40% - 40px);} -.ref-index .title {width: 60%;} - -.ref-arguments th {text-align: right; padding-right: 10px;} -.ref-arguments th, .ref-arguments td {vertical-align: top;} -.ref-arguments .name {width: 20%;} -.ref-arguments .desc {width: 80%;} - -/* Nice scrolling for wide elements --------------------------------------- */ - -table { - display: block; - overflow: auto; -} - -/* Syntax highlighting ---------------------------------------------------- */ - -pre { - word-wrap: normal; - word-break: normal; - border: 1px solid #eee; -} - -pre, code { - background-color: #f8f8f8; - color: #333; -} - -pre code { - overflow: auto; - word-wrap: normal; - white-space: pre; -} - -pre .img { - margin: 5px 0; -} - -pre .img img { - background-color: #fff; - display: block; - height: auto; -} - -code a, pre a { - color: #375f84; -} - -a.sourceLine:hover { - text-decoration: none; -} - -.fl {color: #1514b5;} -.fu {color: #000000;} /* function */ -.ch,.st {color: #036a07;} /* string */ -.kw {color: #264D66;} /* keyword */ -.co {color: #888888;} /* comment */ - -.message { color: black; font-weight: bolder;} -.error { color: orange; font-weight: bolder;} -.warning { color: #6A0366; font-weight: bolder;} - -/* Clipboard --------------------------*/ - -.hasCopyButton { - position: relative; -} - -.btn-copy-ex { - position: absolute; - right: 0; - top: 0; - visibility: hidden; -} - -.hasCopyButton:hover button.btn-copy-ex { - visibility: visible; -} - -/* headroom.js ------------------------ */ - -.headroom { - will-change: transform; - transition: transform 200ms linear; -} -.headroom--pinned { - transform: translateY(0%); -} -.headroom--unpinned { - transform: translateY(-100%); -} - -/* mark.js ----------------------------*/ - -mark { - background-color: rgba(255, 255, 51, 0.5); - border-bottom: 2px solid rgba(255, 153, 51, 0.3); - padding: 1px; -} - -/* vertical spacing after htmlwidgets */ -.html-widget { - margin-bottom: 10px; -} - -/* fontawesome ------------------------ */ - -.fab { - font-family: "Font Awesome 5 Brands" !important; -} - -/* don't display links in code chunks when printing */ -/* source: https://stackoverflow.com/a/10781533 */ -@media print { - code a:link:after, code a:visited:after { - content: ""; - } -} diff --git a/docs/pkgdown.js b/docs/pkgdown.js deleted file mode 100644 index 7e7048fa..00000000 --- a/docs/pkgdown.js +++ /dev/null @@ -1,108 +0,0 @@ -/* http://gregfranko.com/blog/jquery-best-practices/ */ -(function($) { - $(function() { - - $('.navbar-fixed-top').headroom(); - - $('body').css('padding-top', $('.navbar').height() + 10); - $(window).resize(function(){ - $('body').css('padding-top', $('.navbar').height() + 10); - }); - - $('[data-toggle="tooltip"]').tooltip(); - - var cur_path = paths(location.pathname); - var links = $("#navbar ul li a"); - var max_length = -1; - var pos = -1; - for (var i = 0; i < links.length; i++) { - if (links[i].getAttribute("href") === "#") - continue; - // Ignore external links - if (links[i].host !== location.host) - continue; - - var nav_path = paths(links[i].pathname); - - var length = prefix_length(nav_path, cur_path); - if (length > max_length) { - max_length = length; - pos = i; - } - } - - // Add class to parent
  • , and enclosing
  • if in dropdown - if (pos >= 0) { - var menu_anchor = $(links[pos]); - menu_anchor.parent().addClass("active"); - menu_anchor.closest("li.dropdown").addClass("active"); - } - }); - - function paths(pathname) { - var pieces = pathname.split("/"); - pieces.shift(); // always starts with / - - var end = pieces[pieces.length - 1]; - if (end === "index.html" || end === "") - pieces.pop(); - return(pieces); - } - - // Returns -1 if not found - function prefix_length(needle, haystack) { - if (needle.length > haystack.length) - return(-1); - - // Special case for length-0 haystack, since for loop won't run - if (haystack.length === 0) { - return(needle.length === 0 ? 0 : -1); - } - - for (var i = 0; i < haystack.length; i++) { - if (needle[i] != haystack[i]) - return(i); - } - - return(haystack.length); - } - - /* Clipboard --------------------------*/ - - function changeTooltipMessage(element, msg) { - var tooltipOriginalTitle=element.getAttribute('data-original-title'); - element.setAttribute('data-original-title', msg); - $(element).tooltip('show'); - element.setAttribute('data-original-title', tooltipOriginalTitle); - } - - if(ClipboardJS.isSupported()) { - $(document).ready(function() { - var copyButton = ""; - - $(".examples, div.sourceCode").addClass("hasCopyButton"); - - // Insert copy buttons: - $(copyButton).prependTo(".hasCopyButton"); - - // Initialize tooltips: - $('.btn-copy-ex').tooltip({container: 'body'}); - - // Initialize clipboard: - var clipboardBtnCopies = new ClipboardJS('[data-clipboard-copy]', { - text: function(trigger) { - return trigger.parentNode.textContent; - } - }); - - clipboardBtnCopies.on('success', function(e) { - changeTooltipMessage(e.trigger, 'Copied!'); - e.clearSelection(); - }); - - clipboardBtnCopies.on('error', function() { - changeTooltipMessage(e.trigger,'Press Ctrl+C or Command+C to copy'); - }); - }); - } -})(window.jQuery || window.$) diff --git a/docs/pkgdown.yml b/docs/pkgdown.yml deleted file mode 100644 index f32affa8..00000000 --- a/docs/pkgdown.yml +++ /dev/null @@ -1,8 +0,0 @@ -pandoc: 1.19.2.4 -pkgdown: 1.5.0 -pkgdown_sha: ~ -articles: - janitor: janitor.html - tabyls: tabyls.html -last_built: 2020-04-12T14:27Z - diff --git a/docs/planning.html b/docs/planning.html deleted file mode 100644 index 88e62703..00000000 --- a/docs/planning.html +++ /dev/null @@ -1,232 +0,0 @@ - - - - - - - - -High-level package planning • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - -
    -
    - - -
    - -

    2016-12-23

    - -

    This page is for planning the janitor package, at a high level. More-finite questions and ideas can be handled via GitHub issues. This is for say, articulating what the package does or doesn’t do, and how it should be organized. If it turns out we need a more discussion- and comment-friendly format, we can move to Google Docs, but let’s try commenting and editing here.

    -
    -

    -Package vision

    -
    -

    -Purpose

    -

    Provide a framework and associated functions for checking and cleaning dirty data. There are two kinds of checks: interactive checks, like tabyl, and programmatic checks that say, confirm in production that some variables contain no duplicate records, or contain no missing values.

    -
    -

    -In scope:

    -
    -
    -

    -Out of scope:

    -
      -
    • A thorough set of alerting functions for assertive data cleaning in production (instead, recommend assertr or other package)
    • -
    -
    -
    -
    -

    -Questions to resolve

    -
      -
    1. Where should the organizing framework go - vignette? Bookdown? Main page?
    2. -
    -
    -
    -

    -Priorities

    -
    -

    -Big items

    -
      -
    1. Establish organizing framework for the package -
        -
      1. Write up documentation/vignette showing check/clean iterative cycle
      2. -
      3. Figure out new names for functions to fit schema, and rename them
      4. -
      5. Redo vignette
      6. -
      7. Redo homepage
      8. -
      -
    2. -
    3. New function: fuzzy dupes
    4. -
    5. New function family: bindability issues
    6. -
    -
    -
    -

    -Smaller items

    -
      -
    1. -get_dupes should have an option for returning with or without Ns as a column (it’s so much faster without)
    2. -
    -
    -
    -
    -
    - -
    - - - -
    - - - -
    - - -
    -

    Site built with pkgdown 1.5.0.

    -
    - -
    -
    - - - - - - - - diff --git a/docs/pull_request_template.html b/docs/pull_request_template.html deleted file mode 100644 index 5bf16471..00000000 --- a/docs/pull_request_template.html +++ /dev/null @@ -1,185 +0,0 @@ - - - - - - - - -NA • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - -
    -
    - - - -
    -

    -Description

    - -
    - -
    -

    -Example

    - - -
    - - -
    - - - -
    - - - -
    - - -
    -

    Site built with pkgdown 1.5.0.

    -
    - -
    -
    - - - - - - - - diff --git a/docs/reference/add_totals_col.html b/docs/reference/add_totals_col.html deleted file mode 100644 index bf5c843c..00000000 --- a/docs/reference/add_totals_col.html +++ /dev/null @@ -1,184 +0,0 @@ - - - - - - - - -Append a totals column to a data.frame. — add_totals_col • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - -
    -
    - - -
    -

    This function is deprecated, use adorn_totals instead.

    -
    - -
    add_totals_col(dat, na.rm = TRUE)
    - -

    Arguments

    - - - - - - - - - - -
    dat

    an input data.frame with at least one numeric column.

    na.rm

    should missing values (including NaN) be omitted from the calculations?

    - -

    Value

    - -

    Returns a data.frame with a totals column containing row-wise sums.

    - -
    - -
    - - -
    - - -
    -

    Site built with pkgdown 1.5.0.

    -
    - -
    -
    - - - - - - - - diff --git a/docs/reference/add_totals_row.html b/docs/reference/add_totals_row.html deleted file mode 100644 index a2b9a622..00000000 --- a/docs/reference/add_totals_row.html +++ /dev/null @@ -1,188 +0,0 @@ - - - - - - - - -Append a totals row to a data.frame. — add_totals_row • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - -
    -
    - - -
    -

    This function is deprecated, use adorn_totals instead.

    -
    - -
    add_totals_row(dat, fill = "-", na.rm = TRUE)
    - -

    Arguments

    - - - - - - - - - - - - - - -
    dat

    an input data.frame with at least one numeric column.

    fill

    if there are more than one non-numeric columns, what string should fill the bottom row of those columns?

    na.rm

    should missing values (including NaN) be omitted from the calculations?

    - -

    Value

    - -

    Returns a data.frame with a totals row, consisting of "Total" in the first column and column sums in the others.

    - -
    - -
    - - -
    - - -
    -

    Site built with pkgdown 1.5.0.

    -
    - -
    -
    - - - - - - - - diff --git a/docs/reference/adorn_col_title.html b/docs/reference/adorn_col_title.html deleted file mode 100644 index b38a98b3..00000000 --- a/docs/reference/adorn_col_title.html +++ /dev/null @@ -1,160 +0,0 @@ - - - - - - - - -Add column name to the top of a two-way tabyl. — adorn_col_title • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - -
    - -
    -
    - - - -

    This function adds the column variable name to the top of a tabyl for a complete display of information. This makes the tabyl prettier, but renders the data.frame less useful for further manipulation.

    - - -
    adorn_col_title(dat, placement = "top")
    - -

    Arguments

    - - - - - - - - - - -
    dat

    a data.frame of class tabyl.

    placement

    whether the column name should be added to the top of the tabyl in an otherwise-empty row "top" or appended to the already-present row name variable ("combined"). The formatting in the "top" option has the look of base R's table(); it also wipes out the other column names, making it hard to further use the data.frame besides formatting it for reporting. The "combined" option is more conservative in this regard.

    - -

    Value

    - -

    the input tabyl, augmented with the column title.

    - - -

    Examples

    -
    -mtcars %>% - tabyl(am, cyl) %>% - adorn_col_title(placement = "top")
    #> Error in adorn_col_title(., placement = "top"): object 'ns' not found
    -
    - -
    - -
    - - -
    -

    Site built with pkgdown.

    -
    - -
    -
    - - - diff --git a/docs/reference/adorn_crosstab.html b/docs/reference/adorn_crosstab.html deleted file mode 100644 index 37d0f3da..00000000 --- a/docs/reference/adorn_crosstab.html +++ /dev/null @@ -1,207 +0,0 @@ - - - - - - - - -Add presentation formatting to a crosstabulation table. — adorn_crosstab • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - -
    -
    - - -
    -

    This function is deprecated, use the adorn_ family of functions instead.

    -
    - -
    adorn_crosstab(
    -  dat,
    -  denom = "row",
    -  show_n = TRUE,
    -  digits = 1,
    -  show_totals = FALSE,
    -  rounding = "half to even"
    -)
    - -

    Arguments

    - - - - - - - - - - - - - - - - - - - - - - - - - - -
    dat

    a data.frame with row names in the first column and numeric values in all other columns. Usually the piped-in result of a call to crosstab that included the argument percent = "none".

    denom

    the denominator to use for calculating percentages. One of "row", "col", or "all".

    show_n

    should counts be displayed alongside the percentages?

    digits

    how many digits should be displayed after the decimal point?

    show_totals

    display a totals summary? Will be a row, column, or both depending on the value of denom.

    rounding

    method to use for truncating percentages - either "half to even", the base R default method, or "half up", where 14.5 rounds up to 15.

    - -

    Value

    - -

    Returns a data.frame.

    - -
    - -
    - - -
    - - -
    -

    Site built with pkgdown 1.5.0.

    -
    - -
    -
    - - - - - - - - diff --git a/docs/reference/adorn_ns.html b/docs/reference/adorn_ns.html deleted file mode 100644 index 91dc7425..00000000 --- a/docs/reference/adorn_ns.html +++ /dev/null @@ -1,201 +0,0 @@ - - - - - - - - -Add underlying Ns to a tabyl displaying percentages. — adorn_ns • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - -
    -
    - - -
    -

    This function adds back the underlying Ns to a tabyl whose percentages were calculated using adorn_percentages(), to display the Ns and percentages together. You can also call it on a non-tabyl data.frame to which you wish to append Ns.

    -
    - -
    adorn_ns(dat, position = "rear", ns = attr(dat, "core"), ...)
    - -

    Arguments

    - - - - - - - - - - - - - - - - - - -
    dat

    a data.frame of class tabyl that has had adorn_percentages and/or adorn_pct_formatting called on it. If given a list of data.frames, this function will apply itself to each data.frame in the list (designed for 3-way tabyl lists).

    position

    should the N go in the front, or in the rear, of the percentage?

    ns

    the Ns to append. The default is the "core" attribute of the input tabyl dat, where the original Ns of a two-way tabyl are stored. However, if you need to modify the numbers, e.g., to format 4000 as 4,000 or 4k, you can do that separately and supply the formatted result here.

    ...

    columns to adorn. This takes a tidyselect specification. By default, all columns are adorned except for the first column and columns not of class numeric, but this allows you to manually specify which columns should be adorned, for use on a data.frame that does not result from a call to tabyl.

    - -

    Value

    - -

    a data.frame with Ns appended

    - -

    Examples

    -
    -mtcars %>% - tabyl(am, cyl) %>% - adorn_percentages("col") %>% - adorn_pct_formatting() %>% - adorn_ns(position = "front")
    #> am 4 6 8 -#> 0 3 (27.3%) 4 (57.1%) 12 (85.7%) -#> 1 8 (72.7%) 3 (42.9%) 2 (14.3%)
    -
    - -
    - - -
    - - -
    -

    Site built with pkgdown 1.5.0.

    -
    - -
    -
    - - - - - - - - diff --git a/docs/reference/adorn_pct_formatting.html b/docs/reference/adorn_pct_formatting.html deleted file mode 100644 index 2cf8f624..00000000 --- a/docs/reference/adorn_pct_formatting.html +++ /dev/null @@ -1,210 +0,0 @@ - - - - - - - - -Format a data.frame of decimals as percentages. — adorn_pct_formatting • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - -
    -
    - - -
    -

    Numeric columns get multiplied by 100 and formatted as percentages according to user specifications. This function defaults to excluding the first column of the input data.frame, assuming that it contains a descriptive variable, but this can be overridden by specifying the columns to adorn in the ... argument. Non-numeric columns are always excluded.

    -
    - -
    adorn_pct_formatting(
    -  dat,
    -  digits = 1,
    -  rounding = "half to even",
    -  affix_sign = TRUE,
    -  ...
    -)
    - -

    Arguments

    - - - - - - - - - - - - - - - - - - - - - - -
    dat

    a data.frame with decimal values, typically the result of a call to adorn_percentages on a tabyl. If given a list of data.frames, this function will apply itself to each data.frame in the list (designed for 3-way tabyl lists).

    digits

    how many digits should be displayed after the decimal point?

    rounding

    method to use for rounding - either "half to even", the base R default method, or "half up", where 14.5 rounds up to 15.

    affix_sign

    should the % sign be affixed to the end?

    ...

    columns to adorn. This takes a tidyselect specification. By default, all numeric columns (besides the initial column, if numeric) are adorned, but this allows you to manually specify which columns should be adorned, for use on a data.frame that does not result from a call to tabyl.

    - -

    Value

    - -

    a data.frame with formatted percentages

    - -

    Examples

    -
    -mtcars %>% - tabyl(am, cyl) %>% - adorn_percentages("col") %>% - adorn_pct_formatting()
    #> am 4 6 8 -#> 0 27.3% 57.1% 85.7% -#> 1 72.7% 42.9% 14.3%
    -
    - -
    - - -
    - - -
    -

    Site built with pkgdown 1.5.0.

    -
    - -
    -
    - - - - - - - - diff --git a/docs/reference/adorn_percentages.html b/docs/reference/adorn_percentages.html deleted file mode 100644 index 92d2397e..00000000 --- a/docs/reference/adorn_percentages.html +++ /dev/null @@ -1,207 +0,0 @@ - - - - - - - - -Convert a data.frame of counts to percentages. — adorn_percentages • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - -
    -
    - - -
    -

    This function defaults to excluding the first column of the input data.frame, assuming that it contains a descriptive variable, but this can be overridden by specifying the columns to adorn in the ... argument.

    -
    - -
    adorn_percentages(dat, denominator = "row", na.rm = TRUE, ...)
    - -

    Arguments

    - - - - - - - - - - - - - - - - - - -
    dat

    a tabyl or other data.frame with a tabyl-like layout. If given a list of data.frames, this function will apply itself to each data.frame in the list (designed for 3-way tabyl lists).

    denominator

    the direction to use for calculating percentages. One of "row", "col", or "all".

    na.rm

    should missing values (including NaN) be omitted from the calculations?

    ...

    columns to adorn. This takes a tidyselect specification. By default, all numeric columns (besides the initial column, if numeric) are adorned, but this allows you to manually specify which columns should be adorned, for use on a data.frame that does not result from a call to tabyl.

    - -

    Value

    - -

    Returns a data.frame of percentages, expressed as numeric values between 0 and 1.

    - -

    Examples

    -
    -mtcars %>% - tabyl(am, cyl) %>% - adorn_percentages("col")
    #> am 4 6 8 -#> 0 0.2727273 0.5714286 0.8571429 -#> 1 0.7272727 0.4285714 0.1428571
    -# calculates correctly even with totals column and/or row: -mtcars %>% - tabyl(am, cyl) %>% - adorn_totals("row") %>% - adorn_percentages()
    #> am 4 6 8 -#> 0 0.1578947 0.2105263 0.6315789 -#> 1 0.6153846 0.2307692 0.1538462 -#> Total 0.3437500 0.2187500 0.4375000
    -
    - -
    - - -
    - - -
    -

    Site built with pkgdown 1.5.0.

    -
    - -
    -
    - - - - - - - - diff --git a/docs/reference/adorn_rounding.html b/docs/reference/adorn_rounding.html deleted file mode 100644 index 0e845bcd..00000000 --- a/docs/reference/adorn_rounding.html +++ /dev/null @@ -1,222 +0,0 @@ - - - - - - - - -Round the numeric columns in a data.frame. — adorn_rounding • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - -
    -
    - - -
    -

    Can run on any data.frame with at least one numeric column. This function defaults to excluding the first column of the input data.frame, assuming that it contains a descriptive variable, but this can be overridden by specifying the columns to round in the ... argument.

    -

    If you're formatting percentages, e.g., the result of adorn_percentages(), use adorn_pct_formatting() instead. This is a more flexible variant for ad-hoc usage. Compared to adorn_pct_formatting(), it does not multiply by 100 or pad the numbers with spaces for alignment in the results data.frame. This function retains the class of numeric input columns.

    -
    - -
    adorn_rounding(dat, digits = 1, rounding = "half to even", ...)
    - -

    Arguments

    - - - - - - - - - - - - - - - - - - -
    dat

    a tabyl or other data.frame with similar layout. If given a list of data.frames, this function will apply itself to each data.frame in the list (designed for 3-way tabyl lists).

    digits

    how many digits should be displayed after the decimal point?

    rounding

    method to use for rounding - either "half to even", the base R default method, or "half up", where 14.5 rounds up to 15.

    ...

    columns to adorn. This takes a tidyselect specification. By default, all numeric columns (besides the initial column, if numeric) are adorned, but this allows you to manually specify which columns should be adorned, for use on a data.frame that does not result from a call to tabyl.

    - -

    Value

    - -

    Returns the data.frame with rounded numeric columns.

    - -

    Examples

    -
    -mtcars %>% - tabyl(am, cyl) %>% - adorn_percentages() %>% - adorn_rounding(digits = 2, rounding = "half up")
    #> am 4 6 8 -#> 0 0.16 0.21 0.63 -#> 1 0.62 0.23 0.15
    -# tolerates non-numeric columns: -library(dplyr)
    #> -#> Attaching package: ‘dplyr’
    #> The following objects are masked from ‘package:stats’: -#> -#> filter, lag
    #> The following objects are masked from ‘package:base’: -#> -#> intersect, setdiff, setequal, union
    mtcars %>% - tabyl(am, cyl) %>% - adorn_percentages("all") %>% - mutate(dummy = "a") %>% - adorn_rounding()
    #> am 4 6 8 dummy -#> 0 0.1 0.1 0.4 a -#> 1 0.2 0.1 0.1 a
    -# control the columns modified using the ... argument: -mtcars %>% - tabyl(am, cyl) %>% - adorn_percentages("row") %>% - adorn_rounding(digits = 1, rounding = "half up", starts_with("8"))
    #> am 4 6 8 -#> 0 0.1578947 0.2105263 0.6 -#> 1 0.6153846 0.2307692 0.2
    -
    - -
    - - -
    - - -
    -

    Site built with pkgdown 1.5.0.

    -
    - -
    -
    - - - - - - - - diff --git a/docs/reference/adorn_title.html b/docs/reference/adorn_title.html deleted file mode 100644 index 035ba2ed..00000000 --- a/docs/reference/adorn_title.html +++ /dev/null @@ -1,210 +0,0 @@ - - - - - - - - -Add column name to the top of a two-way tabyl. — adorn_title • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - -
    -
    - - -
    -

    This function adds the column variable name to the top of a tabyl for a complete display of information. This makes the tabyl prettier, but renders the data.frame less useful for further manipulation.

    -
    - -
    adorn_title(dat, placement = "top", row_name, col_name)
    - -

    Arguments

    - - - - - - - - - - - - - - - - - - -
    dat

    a data.frame of class tabyl or other data.frame with a tabyl-like layout. If given a list of data.frames, this function will apply itself to each data.frame in the list (designed for 3-way tabyl lists).

    placement

    whether the column name should be added to the top of the tabyl in an otherwise-empty row "top" or appended to the already-present row name variable ("combined"). The formatting in the "top" option has the look of base R's table(); it also wipes out the other column names, making it hard to further use the data.frame besides formatting it for reporting. The "combined" option is more conservative in this regard.

    row_name

    (optional) default behavior is to pull the row name from the attributes of the input tabyl object. If you wish to override that text, or if your input is not a tabyl, supply a string here.

    col_name

    (optional) default behavior is to pull the column_name from the attributes of the input tabyl object. If you wish to override that text, or if your input is not a tabyl, supply a string here.

    - -

    Value

    - -

    the input tabyl, augmented with the column title. Non-tabyl inputs that are of class tbl_df are downgraded to basic data.frames so that the title row prints correctly.

    - -

    Examples

    -
    -mtcars %>% - tabyl(am, cyl) %>% - adorn_title(placement = "top")
    #> cyl -#> am 4 6 8 -#> 0 3 4 12 -#> 1 8 3 2
    -# Adding a title to a non-tabyl -library(tidyr); library(dplyr) -mtcars %>% - group_by(gear, am) %>% - summarise(avg_mpg = mean(mpg)) %>% - spread(gear, avg_mpg) %>% - adorn_title("top", row_name = "Gears", col_name = "Cylinders")
    #> Cylinders -#> 1 Gears 3 4 5 -#> 2 0 16.1066666666667 21.05 <NA> -#> 3 1 <NA> 26.275 21.38
    -
    - -
    - - -
    - - -
    -

    Site built with pkgdown 1.5.0.

    -
    - -
    -
    - - - - - - - - diff --git a/docs/reference/adorn_totals.html b/docs/reference/adorn_totals.html deleted file mode 100644 index 8784bd58..00000000 --- a/docs/reference/adorn_totals.html +++ /dev/null @@ -1,207 +0,0 @@ - - - - - - - - -Append a totals row and/or column to a data.frame. — adorn_totals • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - -
    -
    - - -
    -

    This function defaults to excluding the first column of the input data.frame, assuming that it contains a descriptive variable, but this can be overridden by specifying the columns to be totaled in the ... argument. Non-numeric columns are converted to character class and have a user-specified fill character inserted in the totals row.

    -
    - -
    adorn_totals(dat, where = "row", fill = "-", na.rm = TRUE, name = "Total", ...)
    - -

    Arguments

    - - - - - - - - - - - - - - - - - - - - - - - - - - -
    dat

    an input data.frame with at least one numeric column. If given a list of data.frames, this function will apply itself to each data.frame in the list (designed for 3-way tabyl lists).

    where

    one of "row", "col", or c("row", "col")

    fill

    if there are non-numeric columns, what string should fill the bottom row of those columns?

    na.rm

    should missing values (including NaN) be omitted from the calculations?

    name

    name of the totals column or row

    ...

    columns to total. This takes a tidyselect specification. By default, all numeric columns (besides the initial column, if numeric) are included in the totals, but this allows you to manually specify which columns should be included, for use on a data.frame that does not result from a call to tabyl.

    - -

    Value

    - -

    Returns a data.frame augmented with a totals row, column, or both. The data.frame is now also of class tabyl and stores information about the attached totals and underlying data in the tabyl attributes.

    - -

    Examples

    -
    mtcars %>% - tabyl(am, cyl) %>% - adorn_totals()
    #> am 4 6 8 -#> 0 3 4 12 -#> 1 8 3 2 -#> Total 11 7 14
    -
    - -
    - - -
    - - -
    -

    Site built with pkgdown 1.5.0.

    -
    - -
    -
    - - - - - - - - diff --git a/docs/reference/as_tabyl.html b/docs/reference/as_tabyl.html deleted file mode 100644 index 43b16e3b..00000000 --- a/docs/reference/as_tabyl.html +++ /dev/null @@ -1,241 +0,0 @@ - - - - - - - - -Add <code>tabyl</code> attributes to a data.frame. — as_tabyl • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - -
    -
    - - -
    -

    A tabyl is a data.frame containing counts of a variable or co-occurrences of two variables (a.k.a., a contingency table or crosstab). This specialized kind of data.frame has attributes that enable adorn_ functions to be called for precise formatting and presentation of results. E.g., display results as a mix of percentages, Ns, add totals rows or columns, rounding options, in the style of Microsoft Excel PivotTable.

    -

    A tabyl can be the result of a call to janitor::tabyl(), in which case these attributes are added automatically. This function adds tabyl class attributes to a data.frame that isn't the result of a call to tabyl but meets the requirements of a two-way tabyl: -1) First column contains values of variable 1 -2) Column names 2:n are the values of variable 2 -3) Numeric values in columns 2:n are counts of the co-occurrences of the two variables.*

    -

    * = this is the ideal form of a tabyl, but janitor's adorn_ functions tolerate and ignore non-numeric columns in positions 2:n.

    -

    For instance, the result of dplyr::count() followed by tidyr::spread() can be treated as a tabyl.

    -

    The result of calling tabyl() on a single variable is a special class of one-way tabyl; this function only pertains to the two-way tabyl.

    -
    - -
    as_tabyl(dat, axes = 2, row_var_name = NULL, col_var_name = NULL)
    - -

    Arguments

    - - - - - - - - - - - - - - - - - - -
    dat

    a data.frame with variable values in the first column and numeric values in all other columns.

    axes

    is this a two_way tabyl or a one_way tabyl? If this function is being called by a user, this should probably be "2". One-way tabyls are created by tabyl but are a special case.

    row_var_name

    (optional) the name of the variable in the row dimension; used by adorn_title().

    col_var_name

    (optional) the name of the variable in the column dimension; used by adorn_title().

    - -

    Value

    - -

    Returns the same data.frame, but with the additional class of "tabyl" and the attribute "core".

    - -

    Examples

    -
    as_tabyl(mtcars)
    #> mpg cyl disp hp drat wt qsec vs am gear carb -#> 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4 -#> 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4 -#> 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 -#> 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1 -#> 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2 -#> 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1 -#> 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4 -#> 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2 -#> 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2 -#> 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4 -#> 17.8 6 167.6 123 3.92 3.440 18.90 1 0 4 4 -#> 16.4 8 275.8 180 3.07 4.070 17.40 0 0 3 3 -#> 17.3 8 275.8 180 3.07 3.730 17.60 0 0 3 3 -#> 15.2 8 275.8 180 3.07 3.780 18.00 0 0 3 3 -#> 10.4 8 472.0 205 2.93 5.250 17.98 0 0 3 4 -#> 10.4 8 460.0 215 3.00 5.424 17.82 0 0 3 4 -#> 14.7 8 440.0 230 3.23 5.345 17.42 0 0 3 4 -#> 32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 1 -#> 30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 2 -#> 33.9 4 71.1 65 4.22 1.835 19.90 1 1 4 1 -#> 21.5 4 120.1 97 3.70 2.465 20.01 1 0 3 1 -#> 15.5 8 318.0 150 2.76 3.520 16.87 0 0 3 2 -#> 15.2 8 304.0 150 3.15 3.435 17.30 0 0 3 2 -#> 13.3 8 350.0 245 3.73 3.840 15.41 0 0 3 4 -#> 19.2 8 400.0 175 3.08 3.845 17.05 0 0 3 2 -#> 27.3 4 79.0 66 4.08 1.935 18.90 1 1 4 1 -#> 26.0 4 120.3 91 4.43 2.140 16.70 0 1 5 2 -#> 30.4 4 95.1 113 3.77 1.513 16.90 1 1 5 2 -#> 15.8 8 351.0 264 4.22 3.170 14.50 0 1 5 4 -#> 19.7 6 145.0 175 3.62 2.770 15.50 0 1 5 6 -#> 15.0 8 301.0 335 3.54 3.570 14.60 0 1 5 8 -#> 21.4 4 121.0 109 4.11 2.780 18.60 1 1 4 2
    -
    -
    - -
    - - -
    - - -
    -

    Site built with pkgdown 1.5.0.

    -
    - -
    -
    - - - - - - - - diff --git a/docs/reference/chisq.test.html b/docs/reference/chisq.test.html deleted file mode 100644 index 97d210c6..00000000 --- a/docs/reference/chisq.test.html +++ /dev/null @@ -1,216 +0,0 @@ - - - - - - - - -Apply stats::chisq.test to a two-way tabyl — chisq.test • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - -
    -
    - - -
    -

    This generic function overrides stats::chisq.test. If the passed table -is a two-way tabyl, it runs it through janitor::chisq.test.tabyl, otherwise -it just calls stats::chisq.test.

    -
    - -
    chisq.test(x, ...)
    -
    -# S3 method for default
    -chisq.test(x, y = NULL, ...)
    -
    -# S3 method for tabyl
    -chisq.test(x, tabyl_results = TRUE, ...)
    - -

    Arguments

    - - - - - - - - - - - - - - - - - - -
    x

    a two-way tabyl, a numeric vector or a factor

    ...

    other parameters passed to stats::chisq.test

    y

    if x is a vector, must be another vector or factor of the same length

    tabyl_results

    if TRUE and x is a tabyl object, also return `observed`, `expected`, `residuals` and `stdres` as tabyl

    - -

    Value

    - -

    The result is the same as the one of stats::chisq.test. If `tabyl_results` -is TRUE, the returned tables `observed`, `expected`, `residuals` and `stdres` -are converted to tabyls.

    - -

    Examples

    -
    tab <- tabyl(mtcars, gear, cyl) -chisq.test(tab)
    #> Warning: Chi-squared approximation may be incorrect
    #> -#> Pearson's Chi-squared test -#> -#> data: tab -#> X-squared = 18.036, df = 4, p-value = 0.001214 -#>
    chisq.test(tab)$residuals
    #> Warning: Chi-squared approximation may be incorrect
    #> gear 4 6 8 -#> 3 -1.8303523 -0.70731720 2.1225827 -#> 4 1.9079181 0.84866842 -2.2912878 -#> 5 0.2145291 -0.08964215 -0.1267731
    -
    -
    - -
    - - -
    - - -
    -

    Site built with pkgdown 1.5.0.

    -
    - -
    -
    - - - - - - - - diff --git a/docs/reference/clean_names.html b/docs/reference/clean_names.html deleted file mode 100644 index 5b04017c..00000000 --- a/docs/reference/clean_names.html +++ /dev/null @@ -1,271 +0,0 @@ - - - - - - - - -Cleans names of an object (usually a data.frame). — clean_names • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - -
    -
    - - -
    -

    Resulting names are unique and consist only of the _ character, numbers, and letters. -Capitalization preferences can be specified using the case parameter.

    -

    Accented characters are transliterated to ASCII. For example, an "o" with a -German umlaut over it becomes "o", and the Spanish character "enye" becomes -"n".

    -

    This function takes and returns a data.frame, for ease of piping with -`%>%`. For the underlying function that works on a character vector -of names, see make_clean_names.

    -
    - -
    clean_names(dat, ...)
    -
    -# S3 method for data.frame
    -clean_names(dat, ...)
    -
    -# S3 method for default
    -clean_names(dat, ...)
    -
    -# S3 method for sf
    -clean_names(dat, ...)
    -
    -# S3 method for tbl_graph
    -clean_names(dat, ...)
    - -

    Arguments

    - - - - - - - - - - -
    dat

    the input data.frame.

    ...

    Arguments passed on to make_clean_names

    -
    case

    The desired target case (default is "snake") will be -passed to snakecase::to_any_case() with the exception of "old_janitor", -which exists only to support legacy code (it preserves the behavior of -clean_names() prior to addition of the "case" argument (janitor -versions <= 0.3.1). "old_janitor" is not intended for new code. See -to_any_case for a wide variety of supported cases, -including "sentence" and "title" case.

    -
    replace

    A named character vector where the name is replaced by the -value.

    -
    ascii

    Convert the names to ASCII (TRUE, default) or not -(FALSE).

    -
    use_make_names

    Should make.names() be applied to ensure that the -output is usable as a name without quoting? (Avoiding make.names() -ensures that the output is locale-independent but quoting may be required.)

    -
    sep_in

    (short for separator input) if character, is interpreted as a -regular expression (wrapped internally into stringr::regex()). -The default value is a regular expression that matches any sequence of -non-alphanumeric values. All matches will be replaced by underscores -(additionally to "_" and " ", for which this is always true, even -if NULL is supplied). These underscores are used internally to split -the strings into substrings and specify the word boundaries.

    -
    transliterations

    A character vector (if not NULL). The entries of this argument -need to be elements of stringi::stri_trans_list() (like "Latin-ASCII", which is often useful) or names of lookup tables (currently only "german" is supported). In the order of the entries the letters of the input - string will be transliterated via stringi::stri_trans_general() or replaced via the - matches of the lookup table. When named character elements are supplied as part of `transliterations`, anything that matches the names is replaced by the corresponding value. -You should use this feature with care in case of case = "parsed", case = "internal_parsing" and -case = "none", since for upper case letters, which have transliterations/replacements - of length 2, the second letter will be transliterated to lowercase, for example Oe, Ae, Ss, which - might not always be what is intended. In this case you can make usage of the option to supply named elements and specify the transliterations yourself.

    -
    parsing_option

    An integer that will determine the parsing_option. -

      -
    • 1: "RRRStudio" -> "RRR_Studio"

    • -
    • 2: "RRRStudio" -> "RRRS_tudio"

    • -
    • 3: "RRRStudio" -> "RRRSStudio". This will become for example "Rrrstudio" when we convert to lower camel case.

    • -
    • -1, -2, -3: These parsing_options's will suppress the conversion after non-alphanumeric values.

    • -
    • 0: no parsing

    • -

    -
    numerals

    A character specifying the alignment of numerals ("middle", left, right, asis or tight). I.e. numerals = "left" ensures that no output separator is in front of a digit.

    - -
    - -

    Value

    - -

    Returns the data.frame with clean names.

    -

    Details

    - -

    clean_names() is intended to be used on data.frames - and data.frame like objects. For this reason there are methods to - support using clean_names() on sf and tbl_graph (from - tidygraph) objects. For cleaning named lists and vectors, consider - using make_clean_names().

    - -

    Examples

    -
    # not run: -# clean_names(poorly_named_df) - -# or pipe in the input data.frame: -# poorly_named_df %>% clean_names() - -# if you prefer camelCase variable names: -# poorly_named_df %>% clean_names(., "small_camel") - -# not run: -# library(readxl) -# read_excel("messy_excel_file.xlsx") %>% clean_names() -
    -
    - -
    - - -
    - - -
    -

    Site built with pkgdown 1.5.0.

    -
    - -
    -
    - - - - - - - - diff --git a/docs/reference/compare_df_cols.html b/docs/reference/compare_df_cols.html deleted file mode 100644 index 58ca7237..00000000 --- a/docs/reference/compare_df_cols.html +++ /dev/null @@ -1,244 +0,0 @@ - - - - - - - - -Generate a comparison of data.frames (or similar objects) that indicates if -they will successfully bind together by rows. — compare_df_cols • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - -
    -
    - - -
    -

    Generate a comparison of data.frames (or similar objects) that indicates if -they will successfully bind together by rows.

    -
    - -
    compare_df_cols(
    -  ...,
    -  return = c("all", "match", "mismatch"),
    -  bind_method = c("bind_rows", "rbind"),
    -  strict_description = FALSE
    -)
    - -

    Arguments

    - - - - - - - - - - - - - - - - - - -
    ...

    A combination of data.frames, tibbles, and lists of -data.frames/tibbles. The values may optionally be named arguments; if -named, the output column will be the name; if not named, the output column -will be the data.frame name (see examples section).

    return

    Should a summary of "all" columns be returned, only return -"match"ing columns, or only "mismatch"ing columns?

    bind_method

    What method of binding should be used to determine -matches? With "bind_rows", columns missing from a data.frame would be -considered a match (as in dplyr::bind_rows(); with "rbind", columns -missing from a data.frame would be considered a mismatch (as in -base::rbind().

    strict_description

    Passed to describe_class. Also, see the -Details section.

    - -

    Value

    - -

    A data.frame with a column named "column_name" with a value named - after the input data.frames' column names, and then one column per - data.frame (named after the input data.frame). If more than one input has - the same column name, the column naming will have suffixes defined by - sequential use of base::merge() and may differ from expected naming. - The rows within the data.frame-named columns are descriptions of the - classes of the data within the columns (generated by - describe_class).

    -

    Details

    - -

    Due to the returned "column_name" column, no input data.frame may be - named "column_name".

    -

    The strict_description argument is most typically used to understand - if factor levels match or are bindable. Factors are typically bindable, - but the behavior of what happens when they bind differs based on the - binding method ("bind_rows" or "rbind"). Even when - strict_description is FALSE, data.frames may still bind - because some classes (like factors and characters) can bind even if they - appear to differ.

    -

    See also

    - -

    Other Data frame type comparison: -compare_df_cols_same(), -describe_class()

    - -

    Examples

    -
    compare_df_cols(data.frame(A=1), data.frame(B=2))
    #> column_name data.frame(A = 1) data.frame(B = 2) -#> 1 A numeric <NA> -#> 2 B <NA> numeric
    # user-defined names -compare_df_cols(dfA=data.frame(A=1), dfB=data.frame(B=2))
    #> column_name dfA dfB -#> 1 A numeric <NA> -#> 2 B <NA> numeric
    # a combination of list and data.frame input -compare_df_cols(listA=list(dfA=data.frame(A=1), dfB=data.frame(B=2)), data.frame(A=3))
    #> column_name dfA dfB data.frame(A = 3) -#> 1 A numeric <NA> numeric -#> 2 B <NA> numeric <NA>
    -
    - -
    - - -
    - - -
    -

    Site built with pkgdown 1.5.0.

    -
    - -
    -
    - - - - - - - - diff --git a/docs/reference/compare_df_cols_same.html b/docs/reference/compare_df_cols_same.html deleted file mode 100644 index ad313d7b..00000000 --- a/docs/reference/compare_df_cols_same.html +++ /dev/null @@ -1,211 +0,0 @@ - - - - - - - - -Do the the data.frames have the same columns & types? — compare_df_cols_same • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - -
    -
    - - -
    -

    Check whether a set of data.frames are row-bindable. Calls -compare_df_cols()and returns TRUE if there are no mis-matching rows. `

    -
    - -
    compare_df_cols_same(
    -  ...,
    -  bind_method = c("bind_rows", "rbind"),
    -  verbose = TRUE
    -)
    - -

    Arguments

    - - - - - - - - - - - - - - -
    ...

    A combination of data.frames, tibbles, and lists of -data.frames/tibbles. The values may optionally be named arguments; if -named, the output column will be the name; if not named, the output column -will be the data.frame name (see examples section).

    bind_method

    What method of binding should be used to determine -matches? With "bind_rows", columns missing from a data.frame would be -considered a match (as in dplyr::bind_rows(); with "rbind", columns -missing from a data.frame would be considered a mismatch (as in -base::rbind().

    verbose

    Print the mismatching columns if binding will fail.

    - -

    Value

    - -

    TRUE if row binding will succeed or FALSE if it will - fail.

    -

    See also

    - -

    Other Data frame type comparison: -compare_df_cols(), -describe_class()

    - -

    Examples

    -
    compare_df_cols_same(data.frame(A=1), data.frame(A=2))
    #> [1] TRUE
    compare_df_cols_same(data.frame(A=1), data.frame(B=2))
    #> [1] TRUE
    compare_df_cols_same(data.frame(A=1), data.frame(B=2), verbose=FALSE)
    #> [1] TRUE
    compare_df_cols_same(data.frame(A=1), data.frame(B=2), bind_method="rbind")
    #> column_name ..1 ..2 -#> 1 A numeric <NA> -#> 2 B <NA> numeric
    #> [1] FALSE
    -
    - -
    - - -
    - - -
    -

    Site built with pkgdown 1.5.0.

    -
    - -
    -
    - - - - - - - - diff --git a/docs/reference/convert_to_NA.html b/docs/reference/convert_to_NA.html deleted file mode 100644 index 9a38f535..00000000 --- a/docs/reference/convert_to_NA.html +++ /dev/null @@ -1,190 +0,0 @@ - - - - - - - - -Convert string values to true <code>NA</code> values. — convert_to_NA • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - -
    -
    - - -
    -

    Converts instances of user-specified strings into NA. Can operate on either a single vector or an entire data.frame.

    -
    - -
    convert_to_NA(dat, strings)
    - -

    Arguments

    - - - - - - - - - - -
    dat

    vector or data.frame to operate on.

    strings

    character vector of strings to convert.

    - -

    Value

    - -

    Returns a cleaned object. Can be a vector, data.frame, or tibble::tbl_df depending on the provided input.

    -

    Warning

    - -

    Deprecated, do not use in new code. Use dplyr::na_if() instead.

    -

    See also

    - -

    janitor_deprecated

    - -
    - -
    - - -
    - - -
    -

    Site built with pkgdown 1.5.0.

    -
    - -
    -
    - - - - - - - - diff --git a/docs/reference/convert_to_date.html b/docs/reference/convert_to_date.html deleted file mode 100644 index 34497a64..00000000 --- a/docs/reference/convert_to_date.html +++ /dev/null @@ -1,244 +0,0 @@ - - - - - - - - -Convert many date and datetime formats as may be received from Microsoft -Excel — convert_to_date • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - -
    -
    - - -
    -

    Convert many date and datetime formats as may be received from Microsoft -Excel

    -
    - -
    convert_to_date(
    -  x,
    -  ...,
    -  character_fun = lubridate::ymd,
    -  string_conversion_failure = c("error", "warning")
    -)
    -
    -convert_to_datetime(
    -  x,
    -  ...,
    -  tz = "UTC",
    -  character_fun = lubridate::ymd_hms,
    -  string_conversion_failure = c("error", "warning")
    -)
    - -

    Arguments

    - - - - - - - - - - - - - - - - - - - - - - -
    x

    The object to convert

    ...

    Passed to further methods. Eventually may be passed to -`excel_numeric_to_date()`, `base::as.POXIXct()`, or `base::as.Date()`.

    character_fun

    A function to convert non-numeric-looking, non-NA values -in `x` to POSIXct objects.

    string_conversion_failure

    If a character value fails to parse into the -desired class and instead returns `NA`, should the function return the -result with a warning or throw an error?

    tz

    The timezone for POSIXct output, unless an object is POSIXt -already. Ignored for Date output.

    - -

    Value

    - -

    POSIXct objects for `convert_to_datetime()` or Date objects for - `convert_to_date()`.

    -

    Details

    - -

    Character conversion checks if it matches something that looks like - a Microsoft Excel numeric date, converts those to numeric, and then runs - convert_to_datetime_helper() on those numbers. Then, character to Date or - POSIXct conversion occurs via `character_fun(x, ...)` or - `character_fun(x, tz=tz, ...)`, respectively.

    -

    Functions

    - - -
      -
    • convert_to_datetime: Convert to a date-time (POSIXct)

    • -
    -

    See also

    - -

    Other Date-time cleaning: -excel_numeric_to_date()

    - -

    Examples

    -
    convert_to_date("2009-07-06")
    #> [1] "2009-07-06"
    convert_to_date(40000)
    #> [1] "2009-07-06"
    convert_to_date("40000.1")
    #> [1] "2009-07-06"
    # Mixed date source data can be provided. -convert_to_date(c("2020-02-29", "40000.1"))
    #> [1] "2020-02-29" "2009-07-06"
    convert_to_datetime( - c("2009-07-06", "40000.1", "40000", NA), - character_fun=lubridate::ymd_h, truncated=1, tz="UTC" -)
    #> [1] "2009-07-06 00:00:00 UTC" "2009-07-06 02:24:00 UTC" -#> [3] "2009-07-06 00:00:00 UTC" NA
    -
    - -
    - - -
    - - -
    -

    Site built with pkgdown 1.5.0.

    -
    - -
    -
    - - - - - - - - diff --git a/docs/reference/crosstab.html b/docs/reference/crosstab.html deleted file mode 100644 index a53f3c67..00000000 --- a/docs/reference/crosstab.html +++ /dev/null @@ -1,177 +0,0 @@ - - - - - - - - -Generate a crosstabulation of two vectors. — crosstab • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - -
    -
    - - -
    -

    This function is deprecated, use tabyl(dat, var1, var2) instead.

    -
    - -
    crosstab(...)
    - -

    Arguments

    - - - - - - -
    ...

    arguments

    - - -
    - -
    - - -
    - - -
    -

    Site built with pkgdown 1.5.0.

    -
    - -
    -
    - - - - - - - - diff --git a/docs/reference/describe_class.html b/docs/reference/describe_class.html deleted file mode 100644 index 187ac7fd..00000000 --- a/docs/reference/describe_class.html +++ /dev/null @@ -1,216 +0,0 @@ - - - - - - - - -Describe the class(es) of an object — describe_class • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - -
    -
    - - -
    -

    Describe the class(es) of an object

    -
    - -
    describe_class(x, strict_description = TRUE)
    -
    -# S3 method for factor
    -describe_class(x, strict_description = TRUE)
    -
    -# S3 method for default
    -describe_class(x, strict_description = TRUE)
    - -

    Arguments

    - - - - - - - - - - -
    x

    The object to describe

    strict_description

    Should differing factor levels be treated -as differences for the purposes of identifying mismatches? -strict_description = `TRUE` is stricter and factors with different -levels will be treated as different classes. FALSE is more -lenient: for class comparison purposes, the variable is just a "factor".

    - -

    Value

    - -

    A character scalar describing the class(es) of an object where if the - scalar will match, columns in a data.frame (or similar object) should bind - together without issue.

    -

    Details

    - -

    For package developers, an S3 generic method can be written for - describe_class() for custom classes that may need more definition - than the default method. This function is called by compare_df_cols.

    -

    Methods (by class)

    - - -
      -
    • factor: Describe factors with their levels -and if they are ordered.

    • -
    • default: List all classes of an object.

    • -
    -

    See also

    - -

    Other Data frame type comparison: -compare_df_cols_same(), -compare_df_cols()

    - -

    Examples

    -
    describe_class(1)
    #> [1] "numeric"
    describe_class(factor("A"))
    #> [1] "factor(levels=c(\"A\"))"
    describe_class(ordered(c("A", "B")))
    #> [1] "ordered, factor(levels=c(\"A\", \"B\"))"
    describe_class(ordered(c("A", "B")), strict_description=FALSE)
    #> [1] "factor"
    -
    - -
    - - -
    - - -
    -

    Site built with pkgdown 1.5.0.

    -
    - -
    -
    - - - - - - - - diff --git a/docs/reference/excel_numeric_to_date.html b/docs/reference/excel_numeric_to_date.html deleted file mode 100644 index 4f78bb54..00000000 --- a/docs/reference/excel_numeric_to_date.html +++ /dev/null @@ -1,243 +0,0 @@ - - - - - - - - -Convert dates encoded as serial numbers to Date class. — excel_numeric_to_date • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - -
    -
    - - -
    -

    Converts numbers like 42370 into date values like -2016-01-01.

    -

    Defaults to the modern Excel date encoding system. However, Excel for Mac -2008 and earlier Mac versions of Excel used a different date system. To -determine what platform to specify: if the date 2016-01-01 is represented by -the number 42370 in your spreadsheet, it's the modern system. If it's 40908, -it's the old Mac system. More on date encoding systems at -http://support.office.com/en-us/article/Date-calculations-in-Excel-e7fe7167-48a9-4b96-bb53-5612a800b487.

    -

    A list of all timezones is available from base::OlsonNames(), and the -current timezone is available from base::Sys.timezone().

    -

    If your input data has a mix of Excel numeric dates and actual dates, see the -more powerful functions `convert_to_date()` and `convert_to_datetime()`.

    -
    - -
    excel_numeric_to_date(
    -  date_num,
    -  date_system = "modern",
    -  include_time = FALSE,
    -  round_seconds = TRUE,
    -  tz = ""
    -)
    - -

    Arguments

    - - - - - - - - - - - - - - - - - - - - - - -
    date_num

    numeric vector of serial numbers to convert.

    date_system

    the date system, either "modern" or "mac -pre-2011".

    include_time

    Include the time (hours, minutes, seconds) in the output? -(See details)

    round_seconds

    Round the seconds to an integer (only has an effect when -include_time is TRUE)?

    tz

    Time zone, used when include_time = TRUE (see details for -more information on timezones).

    - -

    Value

    - -

    Returns a vector of class Date if include_time is - FALSE. Returns a vector of class POSIXlt if include_time is - TRUE.

    -

    Details

    - -

    When using include_time=TRUE, days with leap seconds will not - be accurately handled as they do not appear to be accurately handled by - Windows (as described in - https://support.microsoft.com/en-us/help/2722715/support-for-the-leap-second).

    -

    See also

    - -

    Other Date-time cleaning: -convert_to_date()

    - -

    Examples

    -
    excel_numeric_to_date(40000)
    #> [1] "2009-07-06"
    excel_numeric_to_date(40000.5) # No time is included
    #> [1] "2009-07-06"
    excel_numeric_to_date(40000.5, include_time = TRUE) # Time is included
    #> [1] "2009-07-06 13:00:00 EDT"
    excel_numeric_to_date(40000.521, include_time = TRUE) # Time is included
    #> [1] "2009-07-06 13:30:14 EDT"
    excel_numeric_to_date(40000.521, include_time = TRUE, - round_seconds = FALSE) # Time with fractional seconds is included
    #> [1] "2009-07-06 13:30:14 EDT"
    -
    - -
    - - -
    - - -
    -

    Site built with pkgdown 1.5.0.

    -
    - -
    -
    - - - - - - - - diff --git a/docs/reference/figures/dirty_data.PNG b/docs/reference/figures/dirty_data.PNG deleted file mode 100644 index 95f82e9e64dfed024fa10464f1eb309c0abf97d1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 80566 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 - - - - - - - -Apply stats::fisher.test to a two-way tabyl — fisher.test • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - -
    -
    - - -
    -

    This generic function overrides stats::fisher.test. If the passed table -is a two-way tabyl, it runs it through janitor::fisher.test.tabyl, otherwise -it just calls stats::fisher.test.

    -
    - -
    fisher.test(x, ...)
    -
    -# S3 method for default
    -fisher.test(x, y = NULL, ...)
    -
    -# S3 method for tabyl
    -fisher.test(x, ...)
    - -

    Arguments

    - - - - - - - - - - - - - - -
    x

    a two-way tabyl, a numeric vector or a factor

    ...

    other parameters passed to stats::fisher.test

    y

    if x is a vector, must be another vector or factor of the same length

    - -

    Value

    - -

    The result is the same as the one of stats::fisher.test.

    - -

    Examples

    -
    tab <- tabyl(mtcars, gear, cyl) -fisher.test(tab)
    #> -#> Fisher's Exact Test for Count Data -#> -#> data: tab -#> p-value = 8.26e-05 -#> alternative hypothesis: two.sided -#>
    -
    -
    - -
    - - -
    - - -
    -

    Site built with pkgdown 1.5.0.

    -
    - -
    -
    - - - - - - - - diff --git a/docs/reference/get_dupes.html b/docs/reference/get_dupes.html deleted file mode 100644 index ab3802c7..00000000 --- a/docs/reference/get_dupes.html +++ /dev/null @@ -1,264 +0,0 @@ - - - - - - - - -Get rows of a <code>data.frame</code> with identical values for the specified variables. — get_dupes • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - -
    -
    - - -
    -

    For hunting duplicate records during data cleaning. Specify the data.frame and the variable combination to search for duplicates and get back the duplicated rows.

    -
    - -
    get_dupes(dat, ...)
    - -

    Arguments

    - - - - - - - - - - -
    dat

    The input data.frame.

    ...

    Unquoted variable names to search for duplicates. This takes a tidyselect specification.

    - -

    Value

    - -

    Returns a data.frame with the full records where the specified variables have duplicated values, as well as a variable dupe_count showing the number of rows sharing that combination of duplicated values. If the input data.frame was of class tbl_df, the output is as well.

    - -

    Examples

    -
    get_dupes(mtcars, mpg, hp)
    #> mpg hp dupe_count cyl disp drat wt qsec vs am gear carb -#> Mazda RX4 21 110 2 6 160 3.9 2.620 16.46 0 1 4 4 -#> Mazda RX4 Wag 21 110 2 6 160 3.9 2.875 17.02 0 1 4 4
    -# or called with the magrittr pipe %>% : -mtcars %>% get_dupes(wt)
    #> wt dupe_count mpg cyl disp hp drat qsec vs am gear carb -#> Hornet Sportabout 3.44 3 18.7 8 360.0 175 3.15 17.02 0 0 3 2 -#> Merc 280 3.44 3 19.2 6 167.6 123 3.92 18.30 1 0 4 4 -#> Merc 280C 3.44 3 17.8 6 167.6 123 3.92 18.90 1 0 4 4 -#> Duster 360 3.57 2 14.3 8 360.0 245 3.21 15.84 0 0 3 4 -#> Maserati Bora 3.57 2 15.0 8 301.0 335 3.54 14.60 0 1 5 8
    -# You can use tidyselect helpers to specify variables: -mtcars %>% get_dupes(-c(wt, qsec))
    #> mpg cyl disp hp drat vs am gear carb dupe_count wt qsec -#> Mazda RX4 21 6 160 110 3.9 0 1 4 4 2 2.620 16.46 -#> Mazda RX4 Wag 21 6 160 110 3.9 0 1 4 4 2 2.875 17.02
    mtcars %>% get_dupes(starts_with("cy"))
    #> cyl dupe_count mpg disp hp drat wt qsec vs am gear -#> Datsun 710 4 11 22.8 108.0 93 3.85 2.320 18.61 1 1 4 -#> Merc 240D 4 11 24.4 146.7 62 3.69 3.190 20.00 1 0 4 -#> Merc 230 4 11 22.8 140.8 95 3.92 3.150 22.90 1 0 4 -#> Fiat 128 4 11 32.4 78.7 66 4.08 2.200 19.47 1 1 4 -#> Honda Civic 4 11 30.4 75.7 52 4.93 1.615 18.52 1 1 4 -#> Toyota Corolla 4 11 33.9 71.1 65 4.22 1.835 19.90 1 1 4 -#> Toyota Corona 4 11 21.5 120.1 97 3.70 2.465 20.01 1 0 3 -#> Fiat X1-9 4 11 27.3 79.0 66 4.08 1.935 18.90 1 1 4 -#> Porsche 914-2 4 11 26.0 120.3 91 4.43 2.140 16.70 0 1 5 -#> Lotus Europa 4 11 30.4 95.1 113 3.77 1.513 16.90 1 1 5 -#> Volvo 142E 4 11 21.4 121.0 109 4.11 2.780 18.60 1 1 4 -#> Mazda RX4 6 7 21.0 160.0 110 3.90 2.620 16.46 0 1 4 -#> Mazda RX4 Wag 6 7 21.0 160.0 110 3.90 2.875 17.02 0 1 4 -#> Hornet 4 Drive 6 7 21.4 258.0 110 3.08 3.215 19.44 1 0 3 -#> Valiant 6 7 18.1 225.0 105 2.76 3.460 20.22 1 0 3 -#> Merc 280 6 7 19.2 167.6 123 3.92 3.440 18.30 1 0 4 -#> Merc 280C 6 7 17.8 167.6 123 3.92 3.440 18.90 1 0 4 -#> Ferrari Dino 6 7 19.7 145.0 175 3.62 2.770 15.50 0 1 5 -#> Hornet Sportabout 8 14 18.7 360.0 175 3.15 3.440 17.02 0 0 3 -#> Duster 360 8 14 14.3 360.0 245 3.21 3.570 15.84 0 0 3 -#> Merc 450SE 8 14 16.4 275.8 180 3.07 4.070 17.40 0 0 3 -#> Merc 450SL 8 14 17.3 275.8 180 3.07 3.730 17.60 0 0 3 -#> Merc 450SLC 8 14 15.2 275.8 180 3.07 3.780 18.00 0 0 3 -#> Cadillac Fleetwood 8 14 10.4 472.0 205 2.93 5.250 17.98 0 0 3 -#> Lincoln Continental 8 14 10.4 460.0 215 3.00 5.424 17.82 0 0 3 -#> Chrysler Imperial 8 14 14.7 440.0 230 3.23 5.345 17.42 0 0 3 -#> Dodge Challenger 8 14 15.5 318.0 150 2.76 3.520 16.87 0 0 3 -#> AMC Javelin 8 14 15.2 304.0 150 3.15 3.435 17.30 0 0 3 -#> Camaro Z28 8 14 13.3 350.0 245 3.73 3.840 15.41 0 0 3 -#> Pontiac Firebird 8 14 19.2 400.0 175 3.08 3.845 17.05 0 0 3 -#> Ford Pantera L 8 14 15.8 351.0 264 4.22 3.170 14.50 0 1 5 -#> Maserati Bora 8 14 15.0 301.0 335 3.54 3.570 14.60 0 1 5 -#> carb -#> Datsun 710 1 -#> Merc 240D 2 -#> Merc 230 2 -#> Fiat 128 1 -#> Honda Civic 2 -#> Toyota Corolla 1 -#> Toyota Corona 1 -#> Fiat X1-9 1 -#> Porsche 914-2 2 -#> Lotus Europa 2 -#> Volvo 142E 2 -#> Mazda RX4 4 -#> Mazda RX4 Wag 4 -#> Hornet 4 Drive 1 -#> Valiant 1 -#> Merc 280 4 -#> Merc 280C 4 -#> Ferrari Dino 6 -#> Hornet Sportabout 2 -#> Duster 360 4 -#> Merc 450SE 3 -#> Merc 450SL 3 -#> Merc 450SLC 3 -#> Cadillac Fleetwood 4 -#> Lincoln Continental 4 -#> Chrysler Imperial 4 -#> Dodge Challenger 2 -#> AMC Javelin 2 -#> Camaro Z28 4 -#> Pontiac Firebird 2 -#> Ford Pantera L 4 -#> Maserati Bora 8
    -
    - -
    - - -
    - - -
    -

    Site built with pkgdown 1.5.0.

    -
    - -
    -
    - - - - - - - - diff --git a/docs/reference/index.html b/docs/reference/index.html deleted file mode 100644 index 0555c822..00000000 --- a/docs/reference/index.html +++ /dev/null @@ -1,382 +0,0 @@ - - - - - - - - -Function reference • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -

    All functions

    -

    -
    -

    add_totals_col()

    -

    Append a totals column to a data.frame.

    -

    add_totals_row()

    -

    Append a totals row to a data.frame.

    -

    adorn_ns()

    -

    Add underlying Ns to a tabyl displaying percentages.

    -

    adorn_pct_formatting()

    -

    Format a data.frame of decimals as percentages.

    -

    adorn_percentages()

    -

    Convert a data.frame of counts to percentages.

    -

    adorn_rounding()

    -

    Round the numeric columns in a data.frame.

    -

    adorn_title()

    -

    Add column name to the top of a two-way tabyl.

    -

    adorn_totals()

    -

    Append a totals row and/or column to a data.frame.

    -

    as_tabyl()

    -

    Add tabyl attributes to a data.frame.

    -

    chisq.test()

    -

    Apply stats::chisq.test to a two-way tabyl

    -

    clean_names()

    -

    Cleans names of an object (usually a data.frame).

    -

    compare_df_cols()

    -

    Generate a comparison of data.frames (or similar objects) that indicates if -they will successfully bind together by rows.

    -

    compare_df_cols_same()

    -

    Do the the data.frames have the same columns & types?

    -

    convert_to_NA()

    -

    Convert string values to true NA values.

    -

    convert_to_date() convert_to_datetime()

    -

    Convert many date and datetime formats as may be received from Microsoft -Excel

    -

    describe_class()

    -

    Describe the class(es) of an object

    -

    excel_numeric_to_date()

    -

    Convert dates encoded as serial numbers to Date class.

    -

    fisher.test()

    -

    Apply stats::fisher.test to a two-way tabyl

    -

    get_dupes()

    -

    Get rows of a data.frame with identical values for the specified variables.

    -

    janitor_deprecated

    -

    Deprecated Functions in Package janitor

    -

    make_clean_names()

    -

    Cleans a vector of text, typically containing the names of an object.

    -

    remove_constant()

    -

    Remove constant columns from a data.frame or matrix.

    -

    remove_empty()

    -

    Remove empty rows and/or columns from a data.frame or matrix.

    -

    remove_empty_cols()

    -

    Removes empty columns from a data.frame.

    -

    remove_empty_rows()

    -

    Removes empty rows from a data.frame.

    -

    round_half_up()

    -

    Round a numeric vector; halves will be rounded up, ala Microsoft Excel.

    -

    round_to_fraction()

    -

    Round to the nearest fraction of a specified denominator.

    -

    row_to_names()

    -

    Elevate a row to be the column names of a data.frame.

    -

    signif_half_up()

    -

    Round a numeric vector to the specified number of significant digits; halves will be rounded up.

    -

    tabyl()

    -

    Generate a frequency table (1-, 2-, or 3-way).

    -

    top_levels()

    -

    Generate a frequency table of a factor grouped into top-n, bottom-n, and all other levels.

    -

    untabyl()

    -

    Remove tabyl attributes from a data.frame.

    -

    use_first_valid_of()

    -

    Returns first non-NA value from a set of vectors.

    -
    - - -
    - - -
    - - -
    -

    Site built with pkgdown 1.5.0.

    -
    - -
    -
    - - - - - - - - diff --git a/docs/reference/janitor.html b/docs/reference/janitor.html deleted file mode 100644 index c3c7d239..00000000 --- a/docs/reference/janitor.html +++ /dev/null @@ -1,189 +0,0 @@ - - - - - - - - -janitor — janitor • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - -
    -
    - - -
    -

    janitor has simple little tools for examining and cleaning dirty data.

    -
    - - - -

    Main functions

    - - - -

    The main janitor functions can: perfectly format ugly data.frame column names; isolate -duplicate records for further study; and provide quick one- and two-variable tabulations -(i.e., frequency tables and crosstabs) that improve on the base R function table().

    - -

    Other functions in the package can format for reporting the results of these tabulations. -These tabulate-and-report functions approximate popular features of SPSS and Microsoft Excel.

    -

    Package context

    - - - -

    This package follows the principles of the "tidyverse" and in particular works well with -the %>% pipe function.

    - -

    janitor was built with beginning-to-intermediate R users in mind -and is optimized for user-friendliness. Advanced users can already do everything -covered here, but they can do it faster with janitor and save their thinking for -more fun tasks.

    - -
    - -
    - - -
    - - -
    -

    Site built with pkgdown 1.5.0.

    -
    - -
    -
    - - - - - - - - diff --git a/docs/reference/janitor_deprecated.html b/docs/reference/janitor_deprecated.html deleted file mode 100644 index 0395a0cc..00000000 --- a/docs/reference/janitor_deprecated.html +++ /dev/null @@ -1,182 +0,0 @@ - - - - - - - - -Deprecated Functions in Package janitor — janitor_deprecated • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - -
    -
    - - -
    -

    These functions have already become defunct or may be defunct as soon as the next release.

    -
    - - - -

    Details

    - - - - - -
    - -
    - - -
    - - -
    -

    Site built with pkgdown 1.5.0.

    -
    - -
    -
    - - - - - - - - diff --git a/docs/reference/make_clean_names.html b/docs/reference/make_clean_names.html deleted file mode 100644 index 912d8589..00000000 --- a/docs/reference/make_clean_names.html +++ /dev/null @@ -1,333 +0,0 @@ - - - - - - - - -Cleans a vector of text, typically containing the names of an object. — make_clean_names • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - -
    -
    - - -
    -

    Resulting strings are unique and consist only of the _ -character, numbers, and letters. By default, the resulting strings will only -consist of ASCII characters, but non-ASCII (e.g. Unicode) may be allowed by -setting ascii=FALSE. Capitalization preferences can be specified -using the case parameter.

    -

    For use on the names of a data.frame, e.g., in a `%>%` pipeline, -call the convenience function clean_names.

    -

    When ascii=TRUE (the default), accented characters are transliterated -to ASCII. For example, an "o" with a German umlaut over it becomes "o", and -the Spanish character "enye" becomes "n".

    -

    The order of operations is: replace, (optional) ASCII conversion, -removing initial spaces and punctuation, apply base::make.names(), -apply to_any_case, and add numeric suffixes to -duplicates.

    -

    See the documentation for snakecase::to_any_case for more about how -to control its behavior.

    -

    On some systems, not all transliterators to ASCII are available. If this is -the case on your system, all available transliterators will be used, and a -warning will be issued once per session indicating that results may be -different when run on a different system. That warning can be disabled with -options(janitor_warn_transliterators=FALSE).

    -

    If the objective of your call to make_clean_names() is only to translate to -ASCII, try the following instead: -stringi::stri_trans_general(x, id="Any-Latin;Greek-Latin;Latin-ASCII").

    -
    - -
    make_clean_names(
    -  string,
    -  case = "snake",
    -  replace = c(`'` = "", `"` = "", `%` = "_percent_", `#` = "_number_"),
    -  ascii = TRUE,
    -  use_make_names = TRUE,
    -  sep_in = "\\.",
    -  transliterations = "Latin-ASCII",
    -  parsing_option = 1,
    -  numerals = "asis",
    -  ...
    -)
    - -

    Arguments

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    string

    A character vector of names to clean.

    case

    The desired target case (default is "snake") will be -passed to snakecase::to_any_case() with the exception of "old_janitor", -which exists only to support legacy code (it preserves the behavior of -clean_names() prior to addition of the "case" argument (janitor -versions <= 0.3.1). "old_janitor" is not intended for new code. See -to_any_case for a wide variety of supported cases, -including "sentence" and "title" case.

    replace

    A named character vector where the name is replaced by the -value.

    ascii

    Convert the names to ASCII (TRUE, default) or not -(FALSE).

    use_make_names

    Should make.names() be applied to ensure that the -output is usable as a name without quoting? (Avoiding make.names() -ensures that the output is locale-independent but quoting may be required.)

    sep_in

    (short for separator input) if character, is interpreted as a -regular expression (wrapped internally into stringr::regex()). -The default value is a regular expression that matches any sequence of -non-alphanumeric values. All matches will be replaced by underscores -(additionally to "_" and " ", for which this is always true, even -if NULL is supplied). These underscores are used internally to split -the strings into substrings and specify the word boundaries.

    transliterations

    A character vector (if not NULL). The entries of this argument -need to be elements of stringi::stri_trans_list() (like "Latin-ASCII", which is often useful) or names of lookup tables (currently only "german" is supported). In the order of the entries the letters of the input - string will be transliterated via stringi::stri_trans_general() or replaced via the - matches of the lookup table. When named character elements are supplied as part of `transliterations`, anything that matches the names is replaced by the corresponding value. -You should use this feature with care in case of case = "parsed", case = "internal_parsing" and -case = "none", since for upper case letters, which have transliterations/replacements - of length 2, the second letter will be transliterated to lowercase, for example Oe, Ae, Ss, which - might not always be what is intended. In this case you can make usage of the option to supply named elements and specify the transliterations yourself.

    parsing_option

    An integer that will determine the parsing_option.

      -
    • 1: "RRRStudio" -> "RRR_Studio"

    • -
    • 2: "RRRStudio" -> "RRRS_tudio"

    • -
    • 3: "RRRStudio" -> "RRRSStudio". This will become for example "Rrrstudio" when we convert to lower camel case.

    • -
    • -1, -2, -3: These parsing_options's will suppress the conversion after non-alphanumeric values.

    • -
    • 0: no parsing

    • -
    numerals

    A character specifying the alignment of numerals ("middle", left, right, asis or tight). I.e. numerals = "left" ensures that no output separator is in front of a digit.

    ...

    Arguments passed on to snakecase::to_any_case

    -
    abbreviations

    character. (Case insensitive) matched abbreviations are surrounded by underscores. In this way, they can get recognized by the parser. This is useful when e.g. parsing_option 1 is needed for the use case, but some abbreviations but some substrings would require parsing_option 2. Furthermore, this argument also specifies the formatting of abbreviations in the output for the cases title, mixed, lower and upper camel. E.g. for upper camel the first letter is always in upper case, but when the abbreviation is supplied in upper case, this will also be visible in the output.Use this feature with care: One letter abbreviations and abbreviations next to each other are hard to read and also not easy to parse for further processing.

    -
    sep_out

    (short for separator output) String that will be used as separator. The defaults are "_" -and "", regarding the specified case. When length(sep_out) > 1, the last element of sep_out gets recycled and separators are incorporated per string according to their order.

    -
    unique_sep

    A string. If not NULL, then duplicated names will get -a suffix integer -in the order of their appearance. The suffix is separated by the supplied string - to this argument.

    -
    empty_fill

    A string. If it is supplied, then each entry that matches "" will be replaced -by the supplied string to this argument.

    -
    prefix

    prefix (string).

    -
    postfix

    postfix (string).

    - -
    - -

    Value

    - -

    Returns the "cleaned" character vector.

    -

    See also

    - - - -

    Examples

    -
    -# cleaning the names of a vector: -x <- structure(1:3, names = c("name with space", "TwoWords", "total $ (2009)")) -x
    #> name with space TwoWords total $ (2009) -#> 1 2 3
    names(x) <- make_clean_names(names(x)) -x # now has cleaned names
    #> name_with_space two_words total_2009 -#> 1 2 3
    -# if you prefer camelCase variable names: -make_clean_names(names(x), "small_camel")
    #> [1] "nameWithSpace" "twoWords" "total2009"
    -# similar to janitor::clean_names(poorly_named_df): -# not run: -# make_clean_names(names(poorly_named_df)) - -
    -
    - -
    - - -
    - - -
    -

    Site built with pkgdown 1.5.0.

    -
    - -
    -
    - - - - - - - - diff --git a/docs/reference/pipe.html b/docs/reference/pipe.html deleted file mode 100644 index 85077719..00000000 --- a/docs/reference/pipe.html +++ /dev/null @@ -1,180 +0,0 @@ - - - - - - - - -Pipe operator — %>% • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - -
    -
    - - -
    -

    Exported from the magrittr package. To learn more, run ?magrittr::`%>%`.

    -
    - -
    lhs %>% rhs
    - - - -

    Examples

    -
    mtcars %>% - tabyl(carb, cyl) %>% - adorn_totals()
    #> carb 4 6 8 -#> 1 5 2 0 -#> 2 6 0 4 -#> 3 0 0 3 -#> 4 0 4 6 -#> 6 0 1 0 -#> 8 0 0 1 -#> Total 11 7 14
    -
    - -
    - - -
    - - -
    -

    Site built with pkgdown 1.5.0.

    -
    - -
    -
    - - - - - - - - diff --git a/docs/reference/remove_constant.html b/docs/reference/remove_constant.html deleted file mode 100644 index 06f4cf8d..00000000 --- a/docs/reference/remove_constant.html +++ /dev/null @@ -1,204 +0,0 @@ - - - - - - - - -Remove constant columns from a data.frame or matrix. — remove_constant • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - -
    -
    - - -
    -

    Remove constant columns from a data.frame or matrix.

    -
    - -
    remove_constant(dat, na.rm = FALSE, quiet = TRUE)
    - -

    Arguments

    - - - - - - - - - - - - - - -
    dat

    the input data.frame or matrix.

    na.rm

    should NA values be removed when considering whether a -column is constant? The default value of FALSE will result in a -column not being removed if it's a mix of a single value and NA.

    quiet

    Should messages be suppressed (TRUE) or printed -(FALSE) indicating the summary of empty columns or rows removed?

    - -

    See also

    - -

    remove_empty() for removing empty - columns or rows.

    -

    Other remove functions: -remove_empty()

    - -

    Examples

    -
    remove_constant(data.frame(A=1, B=1:3))
    #> B -#> 1 1 -#> 2 2 -#> 3 3
    -# To find the columns that are constant -data.frame(A=1, B=1:3) %>% - dplyr::select_at(setdiff(names(.), names(remove_constant(.)))) %>% - unique()
    #> A -#> 1 1
    -
    - -
    - - -
    - - -
    -

    Site built with pkgdown 1.5.0.

    -
    - -
    -
    - - - - - - - - diff --git a/docs/reference/remove_empty.html b/docs/reference/remove_empty.html deleted file mode 100644 index 1598a6b6..00000000 --- a/docs/reference/remove_empty.html +++ /dev/null @@ -1,203 +0,0 @@ - - - - - - - - -Remove empty rows and/or columns from a data.frame or matrix. — remove_empty • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - -
    -
    - - -
    -

    Removes all rows and/or columns from a data.frame or matrix that - are composed entirely of NA values.

    -
    - -
    remove_empty(dat, which = c("rows", "cols"), quiet = TRUE)
    - -

    Arguments

    - - - - - - - - - - - - - - -
    dat

    the input data.frame or matrix.

    which

    one of "rows", "cols", or c("rows", "cols"). Where no -value of which is provided, defaults to removing both empty rows and empty -columns, declaring the behavior with a printed message.

    quiet

    Should messages be suppressed (TRUE) or printed -(FALSE) indicating the summary of empty columns or rows removed?

    - -

    Value

    - -

    Returns the object without its missing rows or columns.

    -

    See also

    - -

    remove_constant() for removing - constant columns.

    -

    Other remove functions: -remove_constant()

    - -

    Examples

    -
    # not run: -# dat %>% remove_empty("rows") -
    -
    - -
    - - -
    - - -
    -

    Site built with pkgdown 1.5.0.

    -
    - -
    -
    - - - - - - - - diff --git a/docs/reference/remove_empty_cols.html b/docs/reference/remove_empty_cols.html deleted file mode 100644 index d4cde55e..00000000 --- a/docs/reference/remove_empty_cols.html +++ /dev/null @@ -1,184 +0,0 @@ - - - - - - - - -Removes empty columns from a data.frame. — remove_empty_cols • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - -
    -
    - - -
    -

    This function is deprecated, use remove_empty("cols") instead.

    -
    - -
    remove_empty_cols(dat)
    - -

    Arguments

    - - - - - - -
    dat

    the input data.frame.

    - -

    Value

    - -

    Returns the data.frame with no empty columns.

    - -

    Examples

    -
    # not run: -# dat %>% remove_empty_cols -
    -
    - -
    - - -
    - - -
    -

    Site built with pkgdown 1.5.0.

    -
    - -
    -
    - - - - - - - - diff --git a/docs/reference/remove_empty_rows.html b/docs/reference/remove_empty_rows.html deleted file mode 100644 index 7815ceee..00000000 --- a/docs/reference/remove_empty_rows.html +++ /dev/null @@ -1,184 +0,0 @@ - - - - - - - - -Removes empty rows from a data.frame. — remove_empty_rows • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - -
    -
    - - -
    -

    This function is deprecated, use remove_empty("rows") instead.

    -
    - -
    remove_empty_rows(dat)
    - -

    Arguments

    - - - - - - -
    dat

    the input data.frame.

    - -

    Value

    - -

    Returns the data.frame with no empty rows.

    - -

    Examples

    -
    # not run: -# dat %>% remove_empty_rows -
    -
    - -
    - - -
    - - -
    -

    Site built with pkgdown 1.5.0.

    -
    - -
    -
    - - - - - - - - diff --git a/docs/reference/round_half_up.html b/docs/reference/round_half_up.html deleted file mode 100644 index 0c1df91e..00000000 --- a/docs/reference/round_half_up.html +++ /dev/null @@ -1,186 +0,0 @@ - - - - - - - - -Round a numeric vector; halves will be rounded up, ala Microsoft Excel. — round_half_up • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - -
    -
    - - -
    -

    In base R round(), halves are rounded to even, e.g., 12.5 and 11.5 are both rounded to 12. This function rounds 12.5 to 13 (assuming digits = 0). Negative halves are rounded away from zero, e.g., -0.5 is rounded to -1.

    -

    This may skew subsequent statistical analysis of the data, but may be desirable in certain contexts. This function is implemented exactly from http://stackoverflow.com/a/12688836; see that question and comments for discussion of this issue.

    -
    - -
    round_half_up(x, digits = 0)
    - -

    Arguments

    - - - - - - - - - - -
    x

    a numeric vector to round.

    digits

    how many digits should be displayed after the decimal point?

    - - -

    Examples

    -
    round_half_up(12.5)
    #> [1] 13
    round_half_up(1.125, 2)
    #> [1] 1.13
    round_half_up(1.125, 1)
    #> [1] 1.1
    round_half_up(-0.5, 0) # negatives get rounded away from zero
    #> [1] -1
    -
    -
    - -
    - - -
    - - -
    -

    Site built with pkgdown 1.5.0.

    -
    - -
    -
    - - - - - - - - diff --git a/docs/reference/round_to_fraction.html b/docs/reference/round_to_fraction.html deleted file mode 100644 index bde0e340..00000000 --- a/docs/reference/round_to_fraction.html +++ /dev/null @@ -1,218 +0,0 @@ - - - - - - - - -Round to the nearest fraction of a specified denominator. — round_to_fraction • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - -
    -
    - - -
    -

    Round a decimal to the precise decimal value of a specified -fractional denominator. Common use cases include addressing floating point -imprecision and enforcing that data values fall into a certain set.

    -

    E.g., if a decimal represents hours and values should be logged to the nearest -minute, round_to_fraction(x, 60) would enforce that distribution and 0.57 -would be rounded to 0.566667, the equivalent of 34/60. 0.56 would also be rounded -to 34/60.

    -

    Set denominator = 1 to round to whole numbers.

    -

    The digits argument allows for rounding of the subsequent result.

    -
    - -
    round_to_fraction(x, denominator, digits = Inf)
    - -

    Arguments

    - - - - - - - - - - - - - - -
    x

    A numeric vector

    denominator

    The denominator of the fraction for rounding (a scalar or -vector positive integer).

    digits

    Integer indicating the number of decimal places to be used -after rounding to the fraction. This is passed to base::round()). -Negative values are allowed (see Details). (Inf indicates no -subsequent rounding)

    - -

    Value

    - -

    the input x rounded to a decimal value that has an integer numerator relative - to denominator (possibly subsequently rounded to a number of decimal - digits).

    -

    Details

    - -

    If digits is Inf, x is rounded to the fraction - and then kept at full precision. If digits is "auto", the - number of digits is automatically selected as - ceiling(log10(denominator)) + 1.

    - -

    Examples

    -
    round_to_fraction(1.6, denominator = 2)
    #> [1] 1.5
    round_to_fraction(pi, denominator = 7) # 22/7
    #> [1] 3.142857
    round_to_fraction(c(8.1, 9.2), denominator = c(7, 8))
    #> [1] 8.142857 9.250000
    round_to_fraction(c(8.1, 9.2), denominator = c(7, 8), digits = 3)
    #> [1] 8.143 9.250
    round_to_fraction(c(8.1, 9.2, 10.3), denominator = c(7, 8, 1001), digits = "auto")
    #> [1] 8.1400 9.2500 10.2997
    -
    - -
    - - -
    - - -
    -

    Site built with pkgdown 1.5.0.

    -
    - -
    -
    - - - - - - - - diff --git a/docs/reference/row_to_names.html b/docs/reference/row_to_names.html deleted file mode 100644 index 92f5b8e5..00000000 --- a/docs/reference/row_to_names.html +++ /dev/null @@ -1,201 +0,0 @@ - - - - - - - - -Elevate a row to be the column names of a data.frame. — row_to_names • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - -
    -
    - - -
    -

    Elevate a row to be the column names of a data.frame.

    -
    - -
    row_to_names(dat, row_number, remove_row = TRUE, remove_rows_above = TRUE)
    - -

    Arguments

    - - - - - - - - - - - - - - - - - - -
    dat

    The input data.frame

    row_number

    The row of dat containing the variable names

    remove_row

    Should the row row_number be removed from the resulting data.frame?

    remove_rows_above

    If row_number != 1, should the rows above row_number - that is, between -1:(row_number-1) - be removed from the resulting data.frame?

    - -

    Value

    - -

    A data.frame with new names (and some rows removed, if specified)

    - -

    Examples

    -
    x <- data.frame(X_1 = c(NA, "Title", 1:3), - X_2 = c(NA, "Title2", 4:6)) -x %>% - row_to_names(row_number = 2)
    #> Title Title2 -#> 3 1 4 -#> 4 2 5 -#> 5 3 6
    -
    - -
    - - -
    - - -
    -

    Site built with pkgdown 1.5.0.

    -
    - -
    -
    - - - - - - - - diff --git a/docs/reference/signif_half_up.html b/docs/reference/signif_half_up.html deleted file mode 100644 index 12c6f020..00000000 --- a/docs/reference/signif_half_up.html +++ /dev/null @@ -1,198 +0,0 @@ - - - - - - - - -Round a numeric vector to the specified number of significant digits; halves will be rounded up. — signif_half_up • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - -
    -
    - - -
    -

    In base R signif(), halves are rounded to even, e.g., -signif(11.5, 2) and signif(12.5, 2) are both rounded to 12. -This function rounds 12.5 to 13 (assuming digits = 2). Negative halves -are rounded away from zero, e.g., signif(-2.5, 1) is rounded to -3.

    -

    This may skew subsequent statistical analysis of the data, but may be -desirable in certain contexts. This function is implemented from -https://stackoverflow.com/a/1581007; see that question and -comments for discussion of this issue.

    -
    - -
    signif_half_up(x, digits = 6)
    - -

    Arguments

    - - - - - - - - - - -
    x

    a numeric vector to round.

    digits

    integer indicating the number of significant digits to be used.

    - - -

    Examples

    -
    signif_half_up(12.5, 2)
    #> [1] 13
    signif_half_up(1.125, 3)
    #> [1] 1.13
    signif_half_up(-2.5, 1) # negatives get rounded away from zero
    #> [1] -3
    -
    -
    - -
    - - -
    - - -
    -

    Site built with pkgdown 1.5.0.

    -
    - -
    -
    - - - - - - - - diff --git a/docs/reference/tabyl.html b/docs/reference/tabyl.html deleted file mode 100644 index 866adb30..00000000 --- a/docs/reference/tabyl.html +++ /dev/null @@ -1,256 +0,0 @@ - - - - - - - - -Generate a frequency table (1-, 2-, or 3-way). — tabyl • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - -
    -
    - - -
    -

    A fully-featured alternative to table(). Results are data.frames and can be formatted and enhanced with janitor's family of adorn_ functions.

    -

    Specify a data.frame and the one, two, or three unquoted column names you want to tabulate. Three variables generates a list of 2-way tabyls, split by the third variable.

    -

    Alternatively, you can tabulate a single variable that isn't in a data.frame by calling tabyl on a vector, e.g., tabyl(mtcars$gear).

    -
    - -
    tabyl(dat, ...)
    -
    -# S3 method for default
    -tabyl(dat, show_na = TRUE, show_missing_levels = TRUE, ...)
    -
    -# S3 method for data.frame
    -tabyl(dat, var1, var2, var3, show_na = TRUE, show_missing_levels = TRUE, ...)
    - -

    Arguments

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    dat

    a data.frame containing the variables you wish to count. Or, a vector you want to tabulate.

    ...

    the arguments to tabyl (here just for the sake of documentation compliance, as all arguments are listed with the vector- and data.frame-specific methods)

    show_na

    should counts of NA values be displayed? In a one-way tabyl, the presence of NA values triggers an additional column showing valid percentages(calculated excluding NA values).

    show_missing_levels

    should counts of missing levels of factors be displayed? These will be rows and/or columns of zeroes. Useful for keeping consistent output dimensions even when certain factor levels may not be present in the data.

    var1

    the column name of the first variable.

    var2

    (optional) the column name of the second variable (the rows in a 2-way tabulation).

    var3

    (optional) the column name of the third variable (the list in a 3-way tabulation).

    - -

    Value

    - -

    Returns a data.frame with frequencies and percentages of the tabulated variable(s). A 3-way tabulation returns a list of data.frames.

    - -

    Examples

    -
    -tabyl(mtcars, cyl)
    #> cyl n percent -#> 4 11 0.34375 -#> 6 7 0.21875 -#> 8 14 0.43750
    tabyl(mtcars, cyl, gear)
    #> cyl 3 4 5 -#> 4 1 8 2 -#> 6 2 4 1 -#> 8 12 0 2
    tabyl(mtcars, cyl, gear, am)
    #> $`0` -#> cyl 3 4 5 -#> 4 1 2 0 -#> 6 2 2 0 -#> 8 12 0 0 -#> -#> $`1` -#> cyl 3 4 5 -#> 4 0 6 2 -#> 6 0 2 1 -#> 8 0 0 2 -#>
    -# or using the %>% pipe -mtcars %>% - tabyl(cyl, gear)
    #> cyl 3 4 5 -#> 4 1 8 2 -#> 6 2 4 1 -#> 8 12 0 2
    -# illustrating show_na functionality: -my_cars <- rbind(mtcars, rep(NA, 11)) -my_cars %>% tabyl(cyl)
    #> cyl n percent valid_percent -#> 4 11 0.33333333 0.34375 -#> 6 7 0.21212121 0.21875 -#> 8 14 0.42424242 0.43750 -#> NA 1 0.03030303 NA
    my_cars %>% tabyl(cyl, show_na = FALSE)
    #> cyl n percent -#> 4 11 0.34375 -#> 6 7 0.21875 -#> 8 14 0.43750
    -# Calling on a single vector not in a data.frame: -val <- c("hi", "med", "med", "lo") -tabyl(val)
    #> val n percent -#> hi 1 0.25 -#> lo 1 0.25 -#> med 2 0.50
    -
    - -
    - - -
    - - -
    -

    Site built with pkgdown 1.5.0.

    -
    - -
    -
    - - - - - - - - diff --git a/docs/reference/top_levels.html b/docs/reference/top_levels.html deleted file mode 100644 index 6e8af455..00000000 --- a/docs/reference/top_levels.html +++ /dev/null @@ -1,193 +0,0 @@ - - - - - - - - -Generate a frequency table of a factor grouped into top-n, bottom-n, and all other levels. — top_levels • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - -
    -
    - - -
    -

    Get a frequency table of a factor variable, grouped into categories by level.

    -
    - -
    top_levels(input_vec, n = 2, show_na = FALSE)
    - -

    Arguments

    - - - - - - - - - - - - - - -
    input_vec

    the factor variable to tabulate.

    n

    number of levels to include in top and bottom groups

    show_na

    should cases where the variable is NA be shown?

    - -

    Value

    - -

    Returns a data.frame (actually a tbl_df) with the frequencies of the grouped, tabulated variable. Includes counts and percentages, and valid percentages (calculated omitting NA values, if present in the vector and show_na = TRUE.)

    - -

    Examples

    -
    top_levels(as.factor(mtcars$hp), 2)
    #> as.factor(mtcars$hp) n percent -#> 52, 62 2 0.0625 -#> <<< Middle Group (18 categories) >>> 28 0.8750 -#> 264, 335 2 0.0625
    -
    - -
    - - -
    - - -
    -

    Site built with pkgdown 1.5.0.

    -
    - -
    -
    - - - - - - - - diff --git a/docs/reference/untabyl.html b/docs/reference/untabyl.html deleted file mode 100644 index 1c348746..00000000 --- a/docs/reference/untabyl.html +++ /dev/null @@ -1,194 +0,0 @@ - - - - - - - - -Remove <code>tabyl</code> attributes from a data.frame. — untabyl • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - -
    -
    - - -
    -

    Strips away all tabyl-related attributes from a data.frame.

    -
    - -
    untabyl(dat)
    - -

    Arguments

    - - - - - - -
    dat

    a data.frame of class tabyl.

    - -

    Value

    - -

    Returns the same data.frame, but without the tabyl class and attributes.

    - -

    Examples

    -
    -mtcars %>% - tabyl(am) %>% - untabyl() %>% - attributes() # tabyl-specific attributes are gone
    #> $names -#> [1] "am" "n" "percent" -#> -#> $class -#> [1] "data.frame" -#> -#> $row.names -#> [1] 1 2 -#>
    -
    - -
    - - -
    - - -
    -

    Site built with pkgdown 1.5.0.

    -
    - -
    -
    - - - - - - - - diff --git a/docs/reference/use_first_valid_of.html b/docs/reference/use_first_valid_of.html deleted file mode 100644 index 84cc36e0..00000000 --- a/docs/reference/use_first_valid_of.html +++ /dev/null @@ -1,190 +0,0 @@ - - - - - - - - -Returns first non-NA value from a set of vectors. — use_first_valid_of • janitor - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    -
    - - - - -
    - -
    -
    - - -
    -

    At each position of the input vectors, iterates through in order and returns the first non-NA value. This is a robust replacement of the common ifelse(!is.na(x), x, ifelse(!is.na(y), y, z)). It's more readable and handles problems like ifelse's inability to work with dates in this way.

    -
    - -
    use_first_valid_of(..., if_all_NA = NA)
    - -

    Arguments

    - - - - - - - - - - -
    ...

    the input vectors. Order matters: these are searched and prioritized in the order they are supplied.

    if_all_NA

    what value should be used when all of the vectors return NA for a certain index? Default is NA.

    - -

    Value

    - -

    Returns a single vector with the selected values.

    -

    Warning

    - -

    Deprecated, do not use in new code. Use dplyr::coalesce() instead.

    -

    See also

    - -

    janitor_deprecated

    - -
    - -
    - - - -
    - - - - - - - - diff --git a/index.Rmd b/index.Rmd index 8d90bd03..173e15d3 100644 --- a/index.Rmd +++ b/index.Rmd @@ -71,7 +71,7 @@ Below are quick examples of how janitor tools are commonly used. ### Cleaning dirty data Take this roster of teachers at a fictional American high school, stored in the Microsoft Excel file [dirty_data.xlsx](https://github.com/sfirke/janitor/blob/master/dirty_data.xlsx): -![All kinds of dirty.](docs/reference/figures/dirty_data.PNG) +![All kinds of dirty.](man/figures/dirty_data.PNG) Dirtiness includes: diff --git a/index.md b/index.md index 7e74e1f8..35947344 100644 --- a/index.md +++ b/index.md @@ -79,7 +79,7 @@ Below are quick examples of how janitor tools are commonly used. Take this roster of teachers at a fictional American high school, stored in the Microsoft Excel file [dirty_data.xlsx](https://github.com/sfirke/janitor/blob/master/dirty_data.xlsx): -![All kinds of dirty.](docs/reference/figures/dirty_data.PNG) +![All kinds of dirty.](man/figures/dirty_data.PNG) Dirtiness includes: