├── .Rbuildignore ├── .github ├── .gitignore └── workflows │ ├── R-CMD-check.yaml │ ├── pkgdown.yaml │ └── test-coverage.yaml ├── .gitignore ├── .travis.yml ├── DESCRIPTION ├── NAMESPACE ├── NEWS.md ├── R ├── gendercodeR.R └── recode_gender.R ├── README.Rmd ├── README.md ├── _pkgdown.yml ├── codecov.yml ├── cran-comments.md ├── data ├── fewlevels_en.rda ├── howtoaddtodictionary.R ├── manylevels_en.rda └── sample.rda ├── docs ├── 404.html ├── CODE_OF_CONDUCT.html ├── LICENSE-text.html ├── LICENSE.html ├── articles │ ├── a01_rationale.html │ ├── a01_rationale_files │ │ ├── header-attrs-2.10.4 │ │ │ └── header-attrs.js │ │ └── header-attrs-2.10 │ │ │ └── header-attrs.js │ ├── a02_add_dictionary.html │ ├── a02_add_dictionary_files │ │ ├── header-attrs-2.10.4 │ │ │ └── header-attrs.js │ │ └── header-attrs-2.10 │ │ │ └── header-attrs.js │ └── index.html ├── authors.html ├── bootstrap-toc.css ├── bootstrap-toc.js ├── docsearch.css ├── docsearch.js ├── index.html ├── link.svg ├── pkgdown.css ├── pkgdown.js ├── pkgdown.yml └── reference │ ├── Rplot001.png │ ├── fewlevels_en.html │ ├── figures │ ├── README-pressure-1.png │ └── UI.png │ ├── gendercoder.html │ ├── index.html │ ├── manylevels_en.html │ ├── recode_gender.html │ └── sample.html ├── gendercodeR.Rproj ├── inst └── extdata │ ├── GenderDictionary_List.csv │ └── gender-free-text.csv ├── man ├── fewlevels_en.Rd ├── figures │ ├── README-pressure-1.png │ └── UI.png ├── gendercoder.Rd ├── manylevels_en.Rd ├── recode_gender.Rd └── sample.Rd ├── tests ├── testthat.R └── testthat │ ├── .gitignore │ └── test-recode_gender.R └── vignettes ├── .gitignore ├── a01_rationale.Rmd └── a02_add_dictionary.Rmd /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^docs$ 2 | ^_pkgdown\.yml$ 3 | ^README\.Rmd$ 4 | ^gendercoder\.Rproj$ 5 | ^\.Rproj\.user$ 6 | ^LICENSE.md$ 7 | ^\.travis\.yml$ 8 | ^\.github$ 9 | CODE_OF_CONDUCT.md 10 | paper 11 | cran-comments.md 12 | ^codecov\.yml$ 13 | -------------------------------------------------------------------------------- /.github/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | -------------------------------------------------------------------------------- /.github/workflows/R-CMD-check.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | 8 | name: R-CMD-check.yaml 9 | 10 | permissions: read-all 11 | 12 | jobs: 13 | R-CMD-check: 14 | runs-on: ${{ matrix.config.os }} 15 | 16 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 17 | 18 | strategy: 19 | fail-fast: false 20 | matrix: 21 | config: 22 | - {os: macos-latest, r: 'release'} 23 | - {os: windows-latest, r: 'release'} 24 | - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} 25 | - {os: ubuntu-latest, r: 'release'} 26 | - {os: ubuntu-latest, r: 'oldrel-1'} 27 | 28 | env: 29 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 30 | R_KEEP_PKG_SOURCE: yes 31 | 32 | steps: 33 | - uses: actions/checkout@v4 34 | 35 | - uses: r-lib/actions/setup-pandoc@v2 36 | 37 | - uses: r-lib/actions/setup-r@v2 38 | with: 39 | r-version: ${{ matrix.config.r }} 40 | http-user-agent: ${{ matrix.config.http-user-agent }} 41 | use-public-rspm: true 42 | 43 | - uses: r-lib/actions/setup-r-dependencies@v2 44 | with: 45 | extra-packages: any::rcmdcheck 46 | needs: check 47 | 48 | - uses: r-lib/actions/check-r-package@v2 49 | with: 50 | upload-snapshots: true 51 | build_args: 'c("--no-manual","--compact-vignettes=gs+qpdf")' 52 | -------------------------------------------------------------------------------- /.github/workflows/pkgdown.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | release: 8 | types: [published] 9 | workflow_dispatch: 10 | 11 | name: pkgdown.yaml 12 | 13 | permissions: read-all 14 | 15 | jobs: 16 | pkgdown: 17 | runs-on: ubuntu-latest 18 | # Only restrict concurrency for non-PR jobs 19 | concurrency: 20 | group: pkgdown-${{ github.event_name != 'pull_request' || github.run_id }} 21 | env: 22 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 23 | permissions: 24 | contents: write 25 | steps: 26 | - uses: actions/checkout@v4 27 | 28 | - uses: r-lib/actions/setup-pandoc@v2 29 | 30 | - uses: r-lib/actions/setup-r@v2 31 | with: 32 | use-public-rspm: true 33 | 34 | - uses: r-lib/actions/setup-r-dependencies@v2 35 | with: 36 | extra-packages: any::pkgdown, local::. 37 | needs: website 38 | 39 | - name: Build site 40 | run: pkgdown::build_site_github_pages(new_process = FALSE, install = FALSE) 41 | shell: Rscript {0} 42 | 43 | - name: Deploy to GitHub pages 🚀 44 | if: github.event_name != 'pull_request' 45 | uses: JamesIves/github-pages-deploy-action@v4.5.0 46 | with: 47 | clean: false 48 | branch: gh-pages 49 | folder: docs 50 | -------------------------------------------------------------------------------- /.github/workflows/test-coverage.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | 8 | name: test-coverage.yaml 9 | 10 | permissions: read-all 11 | 12 | jobs: 13 | test-coverage: 14 | runs-on: ubuntu-latest 15 | env: 16 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 17 | 18 | steps: 19 | - uses: actions/checkout@v4 20 | 21 | - uses: r-lib/actions/setup-r@v2 22 | with: 23 | use-public-rspm: true 24 | 25 | - uses: r-lib/actions/setup-r-dependencies@v2 26 | with: 27 | extra-packages: any::covr, any::xml2 28 | needs: coverage 29 | 30 | - name: Test coverage 31 | run: | 32 | cov <- covr::package_coverage( 33 | quiet = FALSE, 34 | clean = FALSE, 35 | install_path = file.path(normalizePath(Sys.getenv("RUNNER_TEMP"), winslash = "/"), "package") 36 | ) 37 | covr::to_cobertura(cov) 38 | shell: Rscript {0} 39 | 40 | - uses: codecov/codecov-action@v4 41 | with: 42 | # Fail if error if not on PR, or if on PR and token is given 43 | fail_ci_if_error: ${{ github.event_name != 'pull_request' || secrets.CODECOV_TOKEN }} 44 | file: ./cobertura.xml 45 | plugin: noop 46 | disable_search: true 47 | token: ${{ secrets.CODECOV_TOKEN }} 48 | 49 | - name: Show testthat output 50 | if: always() 51 | run: | 52 | ## -------------------------------------------------------------------- 53 | find '${{ runner.temp }}/package' -name 'testthat.Rout*' -exec cat '{}' \; || true 54 | shell: bash 55 | 56 | - name: Upload test results 57 | if: failure() 58 | uses: actions/upload-artifact@v4 59 | with: 60 | name: coverage-test-failures 61 | path: ${{ runner.temp }}/package 62 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | inst/doc 2 | .Rproj.user 3 | .Rhistory 4 | *.Rproj 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # R for travis: see documentation at https://docs.travis-ci.com/user/languages/r 2 | 3 | language: R 4 | cache: packages 5 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: gendercoder 2 | Title: Recodes Sex/Gender Descriptions into a Standard Set 3 | Version: 0.1.0 4 | Authors@R: c( 5 | person("Yaoxiang", "Li", role = c("aut", "cre"), 6 | email = "liyaoxiang@outlook.com", 7 | comment = c(ORCID = "0000-0001-9200-1016")), 8 | person("Jennifer", "Beaudry", role = "aut", 9 | email = "jbeaudry@swin.edu.au", 10 | comment = c(ORCID = "0000-0003-1596-6708")), 11 | person("Emily", "Kothe", role = "aut", 12 | email = "emily.kothe@deakin.edu.au", 13 | comment = c(ORCID = "0000-0003-1210-0554")), 14 | person("Felix", "Singleton Thorn", role = "aut", 15 | email = "fsingletonthorn@gmail.com", 16 | comment = c(ORCID = "0000-0002-0237-6146")), 17 | person("Rhydwyn", "McGuire", role = "aut", 18 | email = "rhydwyn@rhydwyn.net"), 19 | person("Nicholas", "Tierney", 20 | role = "aut", 21 | email = "nicholas.tierney@gmail.com", 22 | comment = c(ORCID = "0000-0003-1460-8722")), 23 | person("Mathew", "Ling", 24 | role = "aut", 25 | email = "mathewtyling@gmail.com", 26 | comment = c(ORCID = "0000-0002-0940-2538")), 27 | person("Julia", "Silge", 28 | role = "rev", 29 | comment = "Julia reviewed the package (v. 0.0.0.9000) for rOpenSci, see "), 30 | person("Elin", "Waring", 31 | role = "rev", 32 | comment = "Elin reviewed the package (v. 0.0.0.9000) for rOpenSci, see ") 33 | ) 34 | Description: Provides functions and dictionaries for recoding of freetext gender responses into more consistent categories. 35 | Depends: R (>= 3.0.0) 36 | Maintainer: Yaoxiang Li 37 | License: GPL-2 38 | Encoding: UTF-8 39 | LazyData: true 40 | RoxygenNote: 7.3.2 41 | Suggests: 42 | testthat (>= 2.1.0), 43 | knitr, 44 | rmarkdown, 45 | dplyr, 46 | covr 47 | VignetteBuilder: knitr 48 | URL: https://github.com/ropensci/gendercoder 49 | BugReports: https://github.com/ropensci/gendercoder/issues 50 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export(recode_gender) 4 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | # gendercoder 0.1 2 | 3 | * Added NEWS.md to track package updates 4 | * Changed dictionary names, now use `manylevels_en` in place of `broad` and `fewlevels_en` in place of `narrow` 5 | * Refactored core functionality to use named character vectors in place of lists. 6 | -------------------------------------------------------------------------------- /R/gendercodeR.R: -------------------------------------------------------------------------------- 1 | #' gendercoder: A Package for Recoding Freetext Gender Data 2 | #' 3 | #' Provides dictionaries and a function \code{recode_gender} to allow for easy automatic coding of common variations in free text responses to the question \strong{"What is your gender?"} 4 | #' 5 | #' @docType package 6 | #' @name gendercoder 7 | NULL 8 | 9 | #' sample 10 | #' 11 | #' A sample data.frame of free text gender in English for testing and demonstration 12 | #' 13 | #' @name sample 14 | #' @docType data 15 | NULL 16 | 17 | #' manylevels_en 18 | #' 19 | #' A English dictionary for the recode_gender function that has many levels 20 | #' 21 | #' @name manylevels_en 22 | #' @docType data 23 | NULL 24 | 25 | #' fewlevels_en 26 | #' 27 | #' A English dictionary for the recode_gender function that has fewer levels 28 | #' 29 | #' @name fewlevels_en 30 | #' @docType data 31 | NULL 32 | -------------------------------------------------------------------------------- /R/recode_gender.R: -------------------------------------------------------------------------------- 1 | #' recode_gender 2 | #' 3 | #' \code{recode_gender} matches uncleaned gender responses to cleaned list using 4 | #' an built-in or custom dictionary. 5 | #' 6 | #' @param gender a character vector of gender responses for recoding 7 | #' @param dictionary a list that the contains gender responses and their 8 | #' replacement values. A built-in dictionary \code{manylevels_en} is used by 9 | #' default if an alternative dictionary is not supplied. 10 | #' @param retain_unmatched logical indicating if gender responses that are not found in 11 | #' dictionary should be filled with the uncleaned values during recoding 12 | #' 13 | #' @return a character vector of recoded genders 14 | #' 15 | #' @examples 16 | #' 17 | #' 18 | #' df <- data.frame( 19 | #' stringsAsFactors = FALSE, 20 | #' gender = c("male", "MALE", "mle", "I am male", "femail", "female", "enby"), 21 | #' age = c(34L, 37L, 77L, 52L, 68L, 67L, 83L) 22 | #' ) 23 | #' 24 | #' dplyr::mutate(df, recoded_gender = recode_gender(gender, 25 | #' dictionary = manylevels_en, 26 | #' retain_unmatched = TRUE 27 | #' )) 28 | #' 29 | #' @export recode_gender 30 | recode_gender <- function(gender, 31 | dictionary = gendercoder::manylevels_en, 32 | retain_unmatched = FALSE) { 33 | # Ensure that gender is treated as character so that non-character input 34 | # still produces an output of the same length. 35 | gender <- as.character(gender) 36 | 37 | if (!is.character(dictionary)) { 38 | stop("The supplied dictionary is not a character vector") 39 | } 40 | 41 | # Normalize the dictionary 42 | dictionary <- tolower(dictionary) 43 | names(dictionary) <- tolower(names(dictionary)) 44 | dictionary <- dictionary[!duplicated(names(dictionary))] 45 | 46 | # Clean the gender input 47 | gender_lower <- tolower(trimws(gender)) 48 | recoded <- dictionary[gender_lower] 49 | 50 | if (retain_unmatched) { 51 | unmatched_indices <- which(is.na(recoded)) 52 | if (length(unmatched_indices) > 0) { 53 | message("Results not matched from the dictionary have been filled with the user inputted values") 54 | recoded[unmatched_indices] <- gender[unmatched_indices] 55 | } 56 | } 57 | 58 | unname(recoded) 59 | } 60 | -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | output: github_document 3 | --- 4 | 5 | 6 | 7 | ```{r setup, include = FALSE} 8 | knitr::opts_chunk$set( 9 | collapse = TRUE, 10 | comment = "#>", 11 | fig.path = "man/figures/README-", 12 | out.width = "100%" 13 | ) 14 | library(dplyr) 15 | ``` 16 | # gendercoder 17 | 18 | 19 | [![CRAN status](https://www.r-pkg.org/badges/version/gendercoder)](https://CRAN.R-project.org/package=gendercoder) 20 | [![Lifecycle: stable](https://img.shields.io/badge/lifecycle-stable-brightgreen.svg)](https://lifecycle.r-lib.org/articles/stages.html#stable) 21 | [![Project Status: Active – The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active) 22 | [![R-CMD-check](https://github.com/ropensci/gendercoder/workflows/R-CMD-check/badge.svg)](https://github.com/ropensci/gendercoder/actions) 23 | [![ROpenSci status](https://badges.ropensci.org/435_status.svg)](https://github.com/ropensci/software-review/issues/435) 24 | [![R-CMD-check](https://github.com/ropensci/gendercoder/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/ropensci/gendercoder/actions/workflows/R-CMD-check.yaml) 25 | [![Codecov test coverage](https://codecov.io/gh/ropensci/gendercoder/graph/badge.svg)](https://app.codecov.io/gh/ropensci/gendercoder) 26 | 27 | 28 | 29 | The goal of gendercoder is to allow simple re-coding of free-text gender 30 | responses. This is intended to permit representation of gender diversity, 31 | while managing troll-responses and the workload implications of manual coding. 32 | 33 | ## Installation 34 | 35 | This package is not on CRAN. To use this package please run the following code: 36 | 37 | ``` r 38 | devtools::install_github("ropensci/gendercoder") 39 | library(gendercoder) 40 | ``` 41 | ## Basic use 42 | 43 | The gendercoder package permits the efficient re-coding of free-text gender 44 | responses within a tidyverse pipeline. It contains two built-in English output 45 | dictionaries, a default `manylevels_en` dictionary which corrects spelling and 46 | standardises terms while maintaining the diversity of responses and a 47 | `fewlevels_en` dictionary which contains fewer gender categories, "man", "woman", 48 | "boy", "girl", and "sex and gender diverse". 49 | 50 | The core function, `gender_recode()`, takes 3 arguments, 51 | 52 | - `gender` the vector of free-text gender, 53 | 54 | - `dictionary` the preferred dictionary, and 55 | 56 | - `retain_unmatched` a logical indicating whether original values should be carried over if 57 | there is no match. 58 | 59 | Basic usage is demonstrated below. 60 | 61 | ```{r} 62 | library(gendercoder) 63 | 64 | tibble::tibble(gender = c("male", "MALE", "mle", "I am male", "femail", "female", "enby")) |> 65 | dplyr::mutate(manylevels_gender = recode_gender(gender, dictionary = manylevels_en, retain_unmatched = TRUE), 66 | fewlevels_gender = recode_gender(gender, dictionary = fewlevels_en, retain_unmatched = FALSE) 67 | ) 68 | 69 | ``` 70 | 71 | The package does not need to be used as part of a tidyverse pipeline: 72 | 73 | ```{r} 74 | df <- tibble(gender = c("male", "MALE", "mle", "I am male", "femail", "female", "enby")) 75 | 76 | df$manylevels_gender <- recode_gender(df$gender, dictionary = manylevels_en) 77 | df 78 | ``` 79 | 80 | 81 | ## Contributing to this package 82 | 83 | This package is a reflection of cultural context of the package contributors. 84 | We acknowledge that understandings of gender are bound by both culture and time 85 | and are continually changing. As such, we welcome issues and pull requests to 86 | make the package more inclusive, more reflective of current understandings of 87 | gender inclusive languages and/or suitable for a broader range of cultural 88 | contexts. We particularly welcome addition of non-English dictionaries or of 89 | other gender-diverse responses to the `manylevels_en` and `fewlevels_en` dictionaries. 90 | 91 | The ["Adding to the dictionary"](https://ropensci.github.io/gendercoder/articles/a02_add_dictionary.html) vignette includes information about how to make changes to the dictionary either for your own use or when contributiong to the gendercoder package. 92 | 93 | 94 | ## Acknowledgement of Country 95 | 96 | We acknowledge the Wurundjeri people of the Kulin Nation as the custodians of 97 | the land on which this package was developed and pay respects to elders past, 98 | present and future. 99 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # gendercoder 5 | 6 | 7 | 8 | [![CRAN 9 | status](https://www.r-pkg.org/badges/version/gendercoder)](https://CRAN.R-project.org/package=gendercoder) 10 | [![Lifecycle: 11 | stable](https://img.shields.io/badge/lifecycle-stable-brightgreen.svg)](https://lifecycle.r-lib.org/articles/stages.html#stable) 12 | [![Project Status: Active – The project has reached a stable, usable 13 | state and is being actively 14 | developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active) 15 | [![R-CMD-check](https://github.com/ropensci/gendercoder/workflows/R-CMD-check/badge.svg)](https://github.com/ropensci/gendercoder/actions) 16 | [![Codecov test 17 | coverage](https://codecov.io/gh/ropensci/gendercoder/branch/master/graph/badge.svg)](https://codecov.io/gh/ropensci/gendercoder?branch=master) 18 | 19 | 20 | The goal of gendercoder is to allow simple re-coding of free-text gender 21 | responses. This is intended to permit representation of gender 22 | diversity, while managing troll-responses and the workload implications 23 | of manual coding. 24 | 25 | ## Installation 26 | 27 | This package is not on CRAN. To use this package please run the 28 | following code: 29 | 30 | ``` r 31 | devtools::install_github("ropensci/gendercoder") 32 | library(gendercoder) 33 | ``` 34 | 35 | ## Basic use 36 | 37 | The gendercoder package permits the efficient re-coding of free-text 38 | gender responses within a tidyverse pipeline. It contains two built-in 39 | English output dictionaries, a default `manylevels_en` dictionary which 40 | corrects spelling and standardises terms while maintaining the diversity 41 | of responses and a `fewlevels_en` dictionary which contains fewer gender 42 | categories, “man”, “woman”, “boy”, “girl”, and “sex and gender diverse”. 43 | 44 | The core function, `gender_recode()`, takes 3 arguments, 45 | 46 | - `gender` the vector of free-text gender, 47 | 48 | - `dictionary` the preferred dictionary, and 49 | 50 | - `retain_unmatched` a logical indicating whether original values should 51 | be carried over if there is no match. 52 | 53 | Basic usage is demonstrated below. 54 | 55 | ``` r 56 | library(gendercoder) 57 | 58 | tibble(gender = c("male", "MALE", "mle", "I am male", "femail", "female", "enby")) %>% 59 | mutate(manylevels_gender = recode_gender(gender, dictionary = manylevels_en, retain_unmatched = TRUE), 60 | fewlevels_gender = recode_gender(gender, dictionary = fewlevels_en, retain_unmatched = FALSE) 61 | ) 62 | #> Results not matched from the dictionary have been filled with the user inputted values 63 | #> # A tibble: 7 × 3 64 | #> gender manylevels_gender fewlevels_gender 65 | #> 66 | #> 1 male man man 67 | #> 2 MALE man man 68 | #> 3 mle man man 69 | #> 4 I am male I am male 70 | #> 5 femail woman woman 71 | #> 6 female woman woman 72 | #> 7 enby non-binary sex and gender diverse 73 | ``` 74 | 75 | The package does not need to be used as part of a tidyverse pipeline: 76 | 77 | ``` r 78 | df <- tibble(gender = c("male", "MALE", "mle", "I am male", "femail", "female", "enby")) 79 | 80 | df$manylevels_gender <- recode_gender(df$gender, dictionary = manylevels_en) 81 | df 82 | #> # A tibble: 7 × 2 83 | #> gender manylevels_gender 84 | #> 85 | #> 1 male man 86 | #> 2 MALE man 87 | #> 3 mle man 88 | #> 4 I am male 89 | #> 5 femail woman 90 | #> 6 female woman 91 | #> 7 enby non-binary 92 | ``` 93 | 94 | ## Contributing to this package 95 | 96 | This package is a reflection of cultural context of the package 97 | contributors. We acknowledge that understandings of gender are bound by 98 | both culture and time and are continually changing. As such, we welcome 99 | issues and pull requests to make the package more inclusive, more 100 | reflective of current understandings of gender inclusive languages 101 | and/or suitable for a broader range of cultural contexts. We 102 | particularly welcome addition of non-English dictionaries or of other 103 | gender-diverse responses to the `manylevels_en` and `fewlevels_en` 104 | dictionaries. 105 | 106 | The [“Adding to the 107 | dictionary”](https://ropensci.github.io/gendercoder/articles/a02_add_dictionary.html) 108 | vignette includes information about how to make changes to the 109 | dictionary either for your own use or when contributiong to the 110 | gendercoder package. 111 | 112 | ## Citation Information 113 | 114 | Please cite this package as: 115 | 116 | Jennifer Beaudry, Emily Kothe, Felix Singleton Thorn, Rhydwyn McGuire, 117 | Nicholas Tierney and Mathew Ling (2020). gendercoder: Recodes Sex/Gender 118 | Descriptions into a Standard Set. R package version 0.0.0.9000. 119 | 120 | 121 | ## Acknowledgement of Country 122 | 123 | We acknowledge the Wurundjeri people of the Kulin Nation as the 124 | custodians of the land on which this package was developed and pay 125 | respects to elders past, present and future. 126 | -------------------------------------------------------------------------------- /_pkgdown.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/gendercoder/966aaa1296bf4a5db0a3e9039dc5d6adb1de8d39/_pkgdown.yml -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | comment: false 2 | 3 | coverage: 4 | status: 5 | project: 6 | default: 7 | target: auto 8 | threshold: 1% 9 | informational: true 10 | patch: 11 | default: 12 | target: auto 13 | threshold: 1% 14 | informational: true 15 | -------------------------------------------------------------------------------- /cran-comments.md: -------------------------------------------------------------------------------- 1 | ## Test environments 2 | * macOS X Catalina (gh-actions), R 4.0.5 3 | * ubuntu 20.04 (gh-actions), R 4.0.5 4 | * ubuntu 20.04 (gh-actions), dev 2021-04-05 r8014 5 | * windows server 19 (gh-actions), R 4.0.5 6 | 7 | ## R CMD check results 8 | Note: This is a new submission. 9 | 10 | ## Downstream dependencies 11 | 12 | There are currently no downstream dependencies for this package 13 | -------------------------------------------------------------------------------- /data/fewlevels_en.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/gendercoder/966aaa1296bf4a5db0a3e9039dc5d6adb1de8d39/data/fewlevels_en.rda -------------------------------------------------------------------------------- /data/howtoaddtodictionary.R: -------------------------------------------------------------------------------- 1 | ## Supply a new dictionary as a vector 2 | # 3 | # new_dictionary <- c( 4 | # mann = "man", 5 | # frau = "woman", 6 | # femme = "woman", 7 | # homme = "man", 8 | # nin = "man") 9 | 10 | ## Append the new dictionary to an old one 11 | # 12 | # new <- append(manylevels_en, custom_dictionary) 13 | # manylevels_en <- new 14 | # usethis::use_data(manylevels_en, overwrite = TRUE) 15 | 16 | ## Create a new dictionary 17 | # 18 | # usethis::use_data(new, overwrite = TRUE) 19 | -------------------------------------------------------------------------------- /data/manylevels_en.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/gendercoder/966aaa1296bf4a5db0a3e9039dc5d6adb1de8d39/data/manylevels_en.rda -------------------------------------------------------------------------------- /data/sample.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/gendercoder/966aaa1296bf4a5db0a3e9039dc5d6adb1de8d39/data/sample.rda -------------------------------------------------------------------------------- /docs/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Page not found (404) • gendercoder 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 55 | 56 | 57 | 58 | 59 | 60 | 61 |
62 |
63 | 117 | 118 | 119 | 120 |
121 | 122 |
123 |
124 | 127 | 128 | Content not found. Please use links in the navbar. 129 | 130 |
131 | 132 | 137 | 138 |
139 | 140 | 141 | 142 |
143 | 146 | 147 |
148 |

Site built with pkgdown 1.6.1.

149 |
150 | 151 |
152 |
153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | -------------------------------------------------------------------------------- /docs/CODE_OF_CONDUCT.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Contributor Covenant Code of Conduct • gendercoder 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 55 | 56 | 57 | 58 | 59 | 60 | 61 |
62 |
63 | 117 | 118 | 119 | 120 |
121 | 122 |
123 |
124 | 127 | 128 |
129 | 130 |
131 |

132 | Our Pledge

133 |

In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.

134 |
135 |
136 |

137 | Our Standards

138 |

Examples of behavior that contributes to creating a positive environment include:

139 |
    140 |
  • Using welcoming and inclusive language
  • 141 |
  • Being respectful of differing viewpoints and experiences
  • 142 |
  • Gracefully accepting constructive criticism
  • 143 |
  • Focusing on what is best for the community
  • 144 |
  • Showing empathy towards other community members
  • 145 |
146 |

Examples of unacceptable behavior by participants include:

147 |
    148 |
  • The use of sexualized language or imagery and unwelcome sexual attention or advances
  • 149 |
  • Trolling, insulting/derogatory comments, and personal or political attacks
  • 150 |
  • Public or private harassment
  • 151 |
  • Publishing others’ private information, such as a physical or electronic address, without explicit permission
  • 152 |
  • Other conduct which could reasonably be considered inappropriate in a professional setting
  • 153 |
154 |
155 |
156 |

157 | Our Responsibilities

158 |

Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.

159 |

Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.

160 |
161 |
162 |

163 | Scope

164 |

This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.

165 |
166 |
167 |

168 | Enforcement

169 |

Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at . All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.

170 |

Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project’s leadership.

171 |
172 |
173 |

174 | Attribution

175 |

This Code of Conduct is adapted from the Contributor Covenant, version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html

176 |

For answers to common questions about this code of conduct, see https://www.contributor-covenant.org/faq

177 |
178 |
179 | 180 |
181 | 182 | 187 | 188 |
189 | 190 | 191 | 192 |
193 | 196 | 197 |
198 |

Site built with pkgdown 1.6.1.

199 |
200 | 201 |
202 |
203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | -------------------------------------------------------------------------------- /docs/LICENSE-text.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | License • gendercoder 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 55 | 56 | 57 | 58 | 59 | 60 | 61 |
62 |
63 | 117 | 118 | 119 | 120 |
121 | 122 |
123 |
124 | 127 | 128 |
YEAR: 2018
129 | COPYRIGHT HOLDER: Emily Kothe
130 | 
131 | 132 |
133 | 134 | 139 | 140 |
141 | 142 | 143 | 144 |
145 | 148 | 149 |
150 |

Site built with pkgdown 1.6.1.

151 |
152 | 153 |
154 |
155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | -------------------------------------------------------------------------------- /docs/LICENSE.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | MIT License • gendercoder 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 55 | 56 | 57 | 58 | 59 | 60 | 61 |
62 |
63 | 117 | 118 | 119 | 120 |
121 | 122 |
123 |
124 | 127 | 128 |
129 | 130 |

Copyright (c) 2018 Emily Kothe

131 |

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:

132 |

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

133 |

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.

134 |
135 | 136 |
137 | 138 | 143 | 144 |
145 | 146 | 147 | 148 |
149 | 152 | 153 |
154 |

Site built with pkgdown 1.6.1.

155 |
156 | 157 |
158 |
159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | -------------------------------------------------------------------------------- /docs/articles/a01_rationale_files/header-attrs-2.10.4/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/a01_rationale_files/header-attrs-2.10/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/a02_add_dictionary.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Adding to the dictionary • gendercoder 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 20 | 21 | 22 |
23 |
78 | 79 | 80 | 81 | 82 |
83 |
84 | 92 | 93 | 94 | 95 |
96 |

97 | Outline

98 |

While the gendercoder dictionaries aim to be as comprehensive as possible, it is inevitable that new typos and variations will occur in wild data. Moreover, at present, the dictionaries are limited to data the authors have had access to which has been collected in English. As such, if you are collecting data, you will at some point want to add to or create your own dictionaries (and if so, we strongly encourage contributions either as a pull request via github, or by raising an issue so the team can help).

99 |
100 |
101 |

102 | Adding to the dictionary

103 |

Let’s say I have free-text gender data, but some of it is not in English.

104 |
105 | library(gendercoder)
106 | library(dplyr)
107 | df
108 | #> # A tibble: 9 x 1
109 | #>   gender
110 | #>   <chr> 
111 | #> 1 male  
112 | #> 2 enby  
113 | #> 3 womn  
114 | #> 4 mlae  
115 | #> 5 mann  
116 | #> 6 frau  
117 | #> 7 femme 
118 | #> 8 homme 
119 | #> 9 nin
120 |

I can create a new dictionary by creating a named vector, where the names are the raw, uncoded values, and the values are the desired outputs. This can then be used as the dictionary in the recode_gender() function.

121 |
122 | new_dictionary <- c(
123 |   mann = "man", 
124 |   frau = "woman", 
125 |   femme = "woman", 
126 |   homme = "man", 
127 |   nin = "man")
128 | 
129 | df %>% 
130 |   mutate(recoded_gender = recode_gender(gender, 
131 |                                         dictionary = new_dictionary, 
132 |                                         retain_unmatched = TRUE))
133 | #> Results not matched from the dictionary have been filled with the user inputted values
134 | #> # A tibble: 9 x 2
135 | #>   gender recoded_gender
136 | #>   <chr>  <chr>         
137 | #> 1 male   male          
138 | #> 2 enby   enby          
139 | #> 3 womn   womn          
140 | #> 4 mlae   mlae          
141 | #> 5 mann   man           
142 | #> 6 frau   woman         
143 | #> 7 femme  woman         
144 | #> 8 homme  man           
145 | #> 9 nin    man
146 |

However, as you can see using just this new dictionary leaves a number of responses uncoded that the built-in dictionaries could handle. As the dictionaries are just vectors, we can simply concatenate these to use both at the same time.

147 |

We can do this in-line…

148 |
149 | df %>% 
150 |   mutate(recoded_gender = recode_gender(gender, 
151 |                                         dictionary = c(manylevels_en, new_dictionary), 
152 |                                         retain_unmatched = TRUE))
153 | #> # A tibble: 9 x 2
154 | #>   gender recoded_gender
155 | #>   <chr>  <chr>         
156 | #> 1 male   man           
157 | #> 2 enby   non-binary    
158 | #> 3 womn   woman         
159 | #> 4 mlae   man           
160 | #> 5 mann   man           
161 | #> 6 frau   woman         
162 | #> 7 femme  woman         
163 | #> 8 homme  man           
164 | #> 9 nin    man
165 |

Or otherwise we can create a new dictionary and call that later, useful if you might want to save an augmented dictionary for later use or for contributing to the package.

166 |
167 | manylevels_plus <-  c(manylevels_en, new_dictionary)
168 | 
169 | df %>% 
170 |   mutate(recoded_gender = recode_gender(gender, 
171 |                                         dictionary = manylevels_plus, 
172 |                                         retain_unmatched = TRUE))
173 | #> # A tibble: 9 x 2
174 | #>   gender recoded_gender
175 | #>   <chr>  <chr>         
176 | #> 1 male   man           
177 | #> 2 enby   non-binary    
178 | #> 3 womn   woman         
179 | #> 4 mlae   man           
180 | #> 5 mann   man           
181 | #> 6 frau   woman         
182 | #> 7 femme  woman         
183 | #> 8 homme  man           
184 | #> 9 nin    man
185 |
186 |
187 |

188 | Making it official

189 |

Let’s say you are happy with your manylevels_plus dictionary and think it should be part of the manylevels_en dictionary in the package. All you need to do is fork the gendercoder repo, clone it to your local device, and then rename your vector and use the usethis::use_data() function to overwrite the manylevels_en dictionary as shown below.

190 |
191 | manylevels_en <-  manylevels_plus
192 | usethis::use_data(manylevels_en, overwrite = TRUE)
193 |

Once you’ve pushed the changes to your fork, you can make a pull request. Please tell us what you’re adding so we know what to look out for and how to test it.

194 |
195 |
196 | 197 | 202 | 203 |
204 | 205 | 206 | 207 |
210 | 211 |
212 |

Site built with pkgdown 1.6.1.

213 |
214 | 215 |
216 |
217 | 218 | 219 | 220 | 221 | 222 | 223 | -------------------------------------------------------------------------------- /docs/articles/a02_add_dictionary_files/header-attrs-2.10.4/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/a02_add_dictionary_files/header-attrs-2.10/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Articles • gendercoder 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 55 | 56 | 57 | 58 | 59 | 60 | 61 |
62 |
63 | 117 | 118 | 119 | 120 |
121 | 122 |
123 |
124 | 127 | 128 |
129 |

All vignettes

130 |

131 | 132 |
133 |
Introduction to gendercoder
134 |
135 |
Adding to the dictionary
136 |
137 |
138 |
139 |
140 |
141 | 142 | 143 |
144 | 147 | 148 |
149 |

Site built with pkgdown 1.6.1.

150 |
151 | 152 |
153 |
154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | -------------------------------------------------------------------------------- /docs/authors.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Authors • gendercoder 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 55 | 56 | 57 | 58 | 59 | 60 | 61 |
62 |
63 | 117 | 118 | 119 | 120 |
121 | 122 |
123 |
124 | 127 | 128 |
    129 |
  • 130 |

    Jennifer Beaudry. Author. 131 |

    132 |
  • 133 |
  • 134 |

    Emily Kothe. Author, maintainer. 135 |

    136 |
  • 137 |
  • 138 |

    Felix Singleton Thorn. Author. 139 |

    140 |
  • 141 |
  • 142 |

    Rhydwyn McGuire. Author. 143 |

    144 |
  • 145 |
  • 146 |

    Nicholas Tierney. Author. 147 |

    148 |
  • 149 |
  • 150 |

    Mathew Ling. Author. 151 |

    152 |
  • 153 |
  • 154 |

    Julia Silge. Reviewer. 155 |
    Julia reviewed the package (v. 0.0.0.9000) for rOpenSci, see

    156 |
  • 157 |
  • 158 |

    Elin Waring. Reviewer. 159 |
    Elin reviewed the package (v. 0.0.0.9000) for rOpenSci, see

    160 |
  • 161 |
162 | 163 |
164 | 165 |
166 | 167 | 168 | 169 |
170 | 173 | 174 |
175 |

Site built with pkgdown 1.6.1.

176 |
177 | 178 |
179 |
180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | -------------------------------------------------------------------------------- /docs/bootstrap-toc.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/) 3 | * Copyright 2015 Aidan Feldman 4 | * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */ 5 | 6 | /* modified from https://github.com/twbs/bootstrap/blob/94b4076dd2efba9af71f0b18d4ee4b163aa9e0dd/docs/assets/css/src/docs.css#L548-L601 */ 7 | 8 | /* All levels of nav */ 9 | nav[data-toggle='toc'] .nav > li > a { 10 | display: block; 11 | padding: 4px 20px; 12 | font-size: 13px; 13 | font-weight: 500; 14 | color: #767676; 15 | } 16 | nav[data-toggle='toc'] .nav > li > a:hover, 17 | nav[data-toggle='toc'] .nav > li > a:focus { 18 | padding-left: 19px; 19 | color: #563d7c; 20 | text-decoration: none; 21 | background-color: transparent; 22 | border-left: 1px solid #563d7c; 23 | } 24 | nav[data-toggle='toc'] .nav > .active > a, 25 | nav[data-toggle='toc'] .nav > .active:hover > a, 26 | nav[data-toggle='toc'] .nav > .active:focus > a { 27 | padding-left: 18px; 28 | font-weight: bold; 29 | color: #563d7c; 30 | background-color: transparent; 31 | border-left: 2px solid #563d7c; 32 | } 33 | 34 | /* Nav: second level (shown on .active) */ 35 | nav[data-toggle='toc'] .nav .nav { 36 | display: none; /* Hide by default, but at >768px, show it */ 37 | padding-bottom: 10px; 38 | } 39 | nav[data-toggle='toc'] .nav .nav > li > a { 40 | padding-top: 1px; 41 | padding-bottom: 1px; 42 | padding-left: 30px; 43 | font-size: 12px; 44 | font-weight: normal; 45 | } 46 | nav[data-toggle='toc'] .nav .nav > li > a:hover, 47 | nav[data-toggle='toc'] .nav .nav > li > a:focus { 48 | padding-left: 29px; 49 | } 50 | nav[data-toggle='toc'] .nav .nav > .active > a, 51 | nav[data-toggle='toc'] .nav .nav > .active:hover > a, 52 | nav[data-toggle='toc'] .nav .nav > .active:focus > a { 53 | padding-left: 28px; 54 | font-weight: 500; 55 | } 56 | 57 | /* from https://github.com/twbs/bootstrap/blob/e38f066d8c203c3e032da0ff23cd2d6098ee2dd6/docs/assets/css/src/docs.css#L631-L634 */ 58 | nav[data-toggle='toc'] .nav > .active > ul { 59 | display: block; 60 | } 61 | -------------------------------------------------------------------------------- /docs/bootstrap-toc.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/) 3 | * Copyright 2015 Aidan Feldman 4 | * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */ 5 | (function() { 6 | 'use strict'; 7 | 8 | window.Toc = { 9 | helpers: { 10 | // return all matching elements in the set, or their descendants 11 | findOrFilter: function($el, selector) { 12 | // http://danielnouri.org/notes/2011/03/14/a-jquery-find-that-also-finds-the-root-element/ 13 | // http://stackoverflow.com/a/12731439/358804 14 | var $descendants = $el.find(selector); 15 | return $el.filter(selector).add($descendants).filter(':not([data-toc-skip])'); 16 | }, 17 | 18 | generateUniqueIdBase: function(el) { 19 | var text = $(el).text(); 20 | var anchor = text.trim().toLowerCase().replace(/[^A-Za-z0-9]+/g, '-'); 21 | return anchor || el.tagName.toLowerCase(); 22 | }, 23 | 24 | generateUniqueId: function(el) { 25 | var anchorBase = this.generateUniqueIdBase(el); 26 | for (var i = 0; ; i++) { 27 | var anchor = anchorBase; 28 | if (i > 0) { 29 | // add suffix 30 | anchor += '-' + i; 31 | } 32 | // check if ID already exists 33 | if (!document.getElementById(anchor)) { 34 | return anchor; 35 | } 36 | } 37 | }, 38 | 39 | generateAnchor: function(el) { 40 | if (el.id) { 41 | return el.id; 42 | } else { 43 | var anchor = this.generateUniqueId(el); 44 | el.id = anchor; 45 | return anchor; 46 | } 47 | }, 48 | 49 | createNavList: function() { 50 | return $(''); 51 | }, 52 | 53 | createChildNavList: function($parent) { 54 | var $childList = this.createNavList(); 55 | $parent.append($childList); 56 | return $childList; 57 | }, 58 | 59 | generateNavEl: function(anchor, text) { 60 | var $a = $(''); 61 | $a.attr('href', '#' + anchor); 62 | $a.text(text); 63 | var $li = $('
  • '); 64 | $li.append($a); 65 | return $li; 66 | }, 67 | 68 | generateNavItem: function(headingEl) { 69 | var anchor = this.generateAnchor(headingEl); 70 | var $heading = $(headingEl); 71 | var text = $heading.data('toc-text') || $heading.text(); 72 | return this.generateNavEl(anchor, text); 73 | }, 74 | 75 | // Find the first heading level (`

    `, then `

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

    `). 76 | getTopLevel: function($scope) { 77 | for (var i = 1; i <= 6; i++) { 78 | var $headings = this.findOrFilter($scope, 'h' + i); 79 | if ($headings.length > 1) { 80 | return i; 81 | } 82 | } 83 | 84 | return 1; 85 | }, 86 | 87 | // returns the elements for the top level, and the next below it 88 | getHeadings: function($scope, topLevel) { 89 | var topSelector = 'h' + topLevel; 90 | 91 | var secondaryLevel = topLevel + 1; 92 | var secondarySelector = 'h' + secondaryLevel; 93 | 94 | return this.findOrFilter($scope, topSelector + ',' + secondarySelector); 95 | }, 96 | 97 | getNavLevel: function(el) { 98 | return parseInt(el.tagName.charAt(1), 10); 99 | }, 100 | 101 | populateNav: function($topContext, topLevel, $headings) { 102 | var $context = $topContext; 103 | var $prevNav; 104 | 105 | var helpers = this; 106 | $headings.each(function(i, el) { 107 | var $newNav = helpers.generateNavItem(el); 108 | var navLevel = helpers.getNavLevel(el); 109 | 110 | // determine the proper $context 111 | if (navLevel === topLevel) { 112 | // use top level 113 | $context = $topContext; 114 | } else if ($prevNav && $context === $topContext) { 115 | // create a new level of the tree and switch to it 116 | $context = helpers.createChildNavList($prevNav); 117 | } // else use the current $context 118 | 119 | $context.append($newNav); 120 | 121 | $prevNav = $newNav; 122 | }); 123 | }, 124 | 125 | parseOps: function(arg) { 126 | var opts; 127 | if (arg.jquery) { 128 | opts = { 129 | $nav: arg 130 | }; 131 | } else { 132 | opts = arg; 133 | } 134 | opts.$scope = opts.$scope || $(document.body); 135 | return opts; 136 | } 137 | }, 138 | 139 | // accepts a jQuery object, or an options object 140 | init: function(opts) { 141 | opts = this.helpers.parseOps(opts); 142 | 143 | // ensure that the data attribute is in place for styling 144 | opts.$nav.attr('data-toggle', 'toc'); 145 | 146 | var $topContext = this.helpers.createChildNavList(opts.$nav); 147 | var topLevel = this.helpers.getTopLevel(opts.$scope); 148 | var $headings = this.helpers.getHeadings(opts.$scope, topLevel); 149 | this.helpers.populateNav($topContext, topLevel, $headings); 150 | } 151 | }; 152 | 153 | $(function() { 154 | $('nav[data-toggle="toc"]').each(function(i, el) { 155 | var $nav = $(el); 156 | Toc.init($nav); 157 | }); 158 | }); 159 | })(); 160 | -------------------------------------------------------------------------------- /docs/docsearch.css: -------------------------------------------------------------------------------- 1 | /* Docsearch -------------------------------------------------------------- */ 2 | /* 3 | Source: https://github.com/algolia/docsearch/ 4 | License: MIT 5 | */ 6 | 7 | .algolia-autocomplete { 8 | display: block; 9 | -webkit-box-flex: 1; 10 | -ms-flex: 1; 11 | flex: 1 12 | } 13 | 14 | .algolia-autocomplete .ds-dropdown-menu { 15 | width: 100%; 16 | min-width: none; 17 | max-width: none; 18 | padding: .75rem 0; 19 | background-color: #fff; 20 | background-clip: padding-box; 21 | border: 1px solid rgba(0, 0, 0, .1); 22 | box-shadow: 0 .5rem 1rem rgba(0, 0, 0, .175); 23 | } 24 | 25 | @media (min-width:768px) { 26 | .algolia-autocomplete .ds-dropdown-menu { 27 | width: 175% 28 | } 29 | } 30 | 31 | .algolia-autocomplete .ds-dropdown-menu::before { 32 | display: none 33 | } 34 | 35 | .algolia-autocomplete .ds-dropdown-menu [class^=ds-dataset-] { 36 | padding: 0; 37 | background-color: rgb(255,255,255); 38 | border: 0; 39 | max-height: 80vh; 40 | } 41 | 42 | .algolia-autocomplete .ds-dropdown-menu .ds-suggestions { 43 | margin-top: 0 44 | } 45 | 46 | .algolia-autocomplete .algolia-docsearch-suggestion { 47 | padding: 0; 48 | overflow: visible 49 | } 50 | 51 | .algolia-autocomplete .algolia-docsearch-suggestion--category-header { 52 | padding: .125rem 1rem; 53 | margin-top: 0; 54 | font-size: 1.3em; 55 | font-weight: 500; 56 | color: #00008B; 57 | border-bottom: 0 58 | } 59 | 60 | .algolia-autocomplete .algolia-docsearch-suggestion--wrapper { 61 | float: none; 62 | padding-top: 0 63 | } 64 | 65 | .algolia-autocomplete .algolia-docsearch-suggestion--subcategory-column { 66 | float: none; 67 | width: auto; 68 | padding: 0; 69 | text-align: left 70 | } 71 | 72 | .algolia-autocomplete .algolia-docsearch-suggestion--content { 73 | float: none; 74 | width: auto; 75 | padding: 0 76 | } 77 | 78 | .algolia-autocomplete .algolia-docsearch-suggestion--content::before { 79 | display: none 80 | } 81 | 82 | .algolia-autocomplete .ds-suggestion:not(:first-child) .algolia-docsearch-suggestion--category-header { 83 | padding-top: .75rem; 84 | margin-top: .75rem; 85 | border-top: 1px solid rgba(0, 0, 0, .1) 86 | } 87 | 88 | .algolia-autocomplete .ds-suggestion .algolia-docsearch-suggestion--subcategory-column { 89 | display: block; 90 | padding: .1rem 1rem; 91 | margin-bottom: 0.1; 92 | font-size: 1.0em; 93 | font-weight: 400 94 | /* display: none */ 95 | } 96 | 97 | .algolia-autocomplete .algolia-docsearch-suggestion--title { 98 | display: block; 99 | padding: .25rem 1rem; 100 | margin-bottom: 0; 101 | font-size: 0.9em; 102 | font-weight: 400 103 | } 104 | 105 | .algolia-autocomplete .algolia-docsearch-suggestion--text { 106 | padding: 0 1rem .5rem; 107 | margin-top: -.25rem; 108 | font-size: 0.8em; 109 | font-weight: 400; 110 | line-height: 1.25 111 | } 112 | 113 | .algolia-autocomplete .algolia-docsearch-footer { 114 | width: 110px; 115 | height: 20px; 116 | z-index: 3; 117 | margin-top: 10.66667px; 118 | float: right; 119 | font-size: 0; 120 | line-height: 0; 121 | } 122 | 123 | .algolia-autocomplete .algolia-docsearch-footer--logo { 124 | background-image: url("data:image/svg+xml;utf8,"); 125 | background-repeat: no-repeat; 126 | background-position: 50%; 127 | background-size: 100%; 128 | overflow: hidden; 129 | text-indent: -9000px; 130 | width: 100%; 131 | height: 100%; 132 | display: block; 133 | transform: translate(-8px); 134 | } 135 | 136 | .algolia-autocomplete .algolia-docsearch-suggestion--highlight { 137 | color: #FF8C00; 138 | background: rgba(232, 189, 54, 0.1) 139 | } 140 | 141 | 142 | .algolia-autocomplete .algolia-docsearch-suggestion--text .algolia-docsearch-suggestion--highlight { 143 | box-shadow: inset 0 -2px 0 0 rgba(105, 105, 105, .5) 144 | } 145 | 146 | .algolia-autocomplete .ds-suggestion.ds-cursor .algolia-docsearch-suggestion--content { 147 | background-color: rgba(192, 192, 192, .15) 148 | } 149 | -------------------------------------------------------------------------------- /docs/docsearch.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | 3 | // register a handler to move the focus to the search bar 4 | // upon pressing shift + "/" (i.e. "?") 5 | $(document).on('keydown', function(e) { 6 | if (e.shiftKey && e.keyCode == 191) { 7 | e.preventDefault(); 8 | $("#search-input").focus(); 9 | } 10 | }); 11 | 12 | $(document).ready(function() { 13 | // do keyword highlighting 14 | /* modified from https://jsfiddle.net/julmot/bL6bb5oo/ */ 15 | var mark = function() { 16 | 17 | var referrer = document.URL ; 18 | var paramKey = "q" ; 19 | 20 | if (referrer.indexOf("?") !== -1) { 21 | var qs = referrer.substr(referrer.indexOf('?') + 1); 22 | var qs_noanchor = qs.split('#')[0]; 23 | var qsa = qs_noanchor.split('&'); 24 | var keyword = ""; 25 | 26 | for (var i = 0; i < qsa.length; i++) { 27 | var currentParam = qsa[i].split('='); 28 | 29 | if (currentParam.length !== 2) { 30 | continue; 31 | } 32 | 33 | if (currentParam[0] == paramKey) { 34 | keyword = decodeURIComponent(currentParam[1].replace(/\+/g, "%20")); 35 | } 36 | } 37 | 38 | if (keyword !== "") { 39 | $(".contents").unmark({ 40 | done: function() { 41 | $(".contents").mark(keyword); 42 | } 43 | }); 44 | } 45 | } 46 | }; 47 | 48 | mark(); 49 | }); 50 | }); 51 | 52 | /* Search term highlighting ------------------------------*/ 53 | 54 | function matchedWords(hit) { 55 | var words = []; 56 | 57 | var hierarchy = hit._highlightResult.hierarchy; 58 | // loop to fetch from lvl0, lvl1, etc. 59 | for (var idx in hierarchy) { 60 | words = words.concat(hierarchy[idx].matchedWords); 61 | } 62 | 63 | var content = hit._highlightResult.content; 64 | if (content) { 65 | words = words.concat(content.matchedWords); 66 | } 67 | 68 | // return unique words 69 | var words_uniq = [...new Set(words)]; 70 | return words_uniq; 71 | } 72 | 73 | function updateHitURL(hit) { 74 | 75 | var words = matchedWords(hit); 76 | var url = ""; 77 | 78 | if (hit.anchor) { 79 | url = hit.url_without_anchor + '?q=' + escape(words.join(" ")) + '#' + hit.anchor; 80 | } else { 81 | url = hit.url + '?q=' + escape(words.join(" ")); 82 | } 83 | 84 | return url; 85 | } 86 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Recodes Sex/Gender Descriptions into a Standard Set • gendercoder 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 20 | 21 | 22 |
    23 |
    78 | 79 | 80 | 81 | 82 |
    83 |
    84 |
    85 | 87 | 88 | 89 |

    The goal of gendercoder is to allow simple re-coding of free-text gender responses. This is intended to permit representation of gender diversity, while managing troll-responses and the workload implications of manual coding.

    90 |
    91 |

    92 | Installation

    93 |

    This package is not on CRAN. To use this package please run the following code:

    94 |
     95 | devtools::install_github("ropenscilabs/gendercoder")
     96 | library(gendercoder)
    97 |
    98 |
    99 |

    100 | Basic use

    101 |

    The gendercoder package permits the efficient re-coding of free-text gender responses within a tidyverse pipeline. It contains two built-in English output dictionaries, a default manylevels_en dictionary which corrects spelling and standardises terms while maintaining the diversity of responses and a fewlevels_en dictionary which contains fewer gender categories, “man”, “woman”, “boy”, “girl”, and “sex and gender diverse”.

    102 |

    The core function, gender_recode(), takes 3 arguments,

    103 |
      104 |
    • gender the vector of free-text gender,

    • 105 |
    • dictionary the preferred dictionary, and

    • 106 |
    • retain_unmatched a logical indicating whether original values should be carried over if there is no match.

    • 107 |
    108 |

    Basic usage is demonstrated below.

    109 |
    110 | library(gendercoder)
    111 | 
    112 | tibble(gender = c("male", "MALE", "mle", "I am male", "femail", "female", "enby")) %>% 
    113 |   mutate(manylevels_gender  = recode_gender(gender, dictionary = manylevels_en, retain_unmatched = TRUE),
    114 |          fewlevels_gender = recode_gender(gender, dictionary = fewlevels_en, retain_unmatched = FALSE)
    115 |   )
    116 | #> Results not matched from the dictionary have been filled with the user inputted values
    117 | #> # A tibble: 7 x 3
    118 | #>   gender    manylevels_gender fewlevels_gender      
    119 | #>   <chr>     <chr>             <chr>                 
    120 | #> 1 male      man               man                   
    121 | #> 2 MALE      man               man                   
    122 | #> 3 mle       man               man                   
    123 | #> 4 I am male I am male         <NA>                  
    124 | #> 5 femail    woman             woman                 
    125 | #> 6 female    woman             woman                 
    126 | #> 7 enby      non-binary        sex and gender diverse
    127 |

    The package does not need to be used as part of a tidyverse pipeline:

    128 |
    129 | df <- tibble(gender = c("male", "MALE", "mle", "I am male", "femail", "female", "enby")) 
    130 | 
    131 | df$manylevels_gender <- recode_gender(df$gender, dictionary = manylevels_en)
    132 | df
    133 | #> # A tibble: 7 x 2
    134 | #>   gender    manylevels_gender
    135 | #>   <chr>     <chr>            
    136 | #> 1 male      man              
    137 | #> 2 MALE      man              
    138 | #> 3 mle       man              
    139 | #> 4 I am male <NA>             
    140 | #> 5 femail    woman            
    141 | #> 6 female    woman            
    142 | #> 7 enby      non-binary
    143 |
    144 |
    145 |

    146 | Contributing to this package

    147 |

    This package is a reflection of cultural context of the package contributors. We acknowledge that understandings of gender are bound by both culture and time and are continually changing. As such, we welcome issues and pull requests to make the package more inclusive, more reflective of current understandings of gender inclusive languages and/or suitable for a broader range of cultural contexts. We particularly welcome addition of non-English dictionaries or of other gender-diverse responses to the manylevels_en and fewlevels_en dictionaries.

    148 |

    The “Adding to the dictionary” vignette includes information about how to make changes to the dictionary either for your own use or when contributiong to the gendercoder package.

    149 |
    150 |
    151 |

    152 | Citation Information

    153 |

    Please cite this package as:

    154 |

    Jennifer Beaudry, Emily Kothe, Felix Singleton Thorn, Rhydwyn McGuire, Nicholas Tierney and Mathew Ling (2020). gendercoder: Recodes Sex/Gender Descriptions into a Standard Set. R package version 0.0.0.9000. https://github.com/ropenscilabs/gendercoder

    155 |
    156 |
    157 |

    158 | Acknowledgement of Country

    159 |

    We acknowledge the Wurundjeri people of the Kulin Nation as the custodians of the land on which this package was developed and pay respects to elders past, present and future.

    160 |
    161 |
    162 |
    163 | 164 | 211 |
    212 | 213 | 214 |
    217 | 218 |
    219 |

    Site built with pkgdown 1.6.1.

    220 |
    221 | 222 |
    223 |
    224 | 225 | 226 | 227 | 228 | 229 | 230 | -------------------------------------------------------------------------------- /docs/link.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 12 | 13 | -------------------------------------------------------------------------------- /docs/pkgdown.css: -------------------------------------------------------------------------------- 1 | /* Sticky footer */ 2 | 3 | /** 4 | * Basic idea: https://philipwalton.github.io/solved-by-flexbox/demos/sticky-footer/ 5 | * Details: https://github.com/philipwalton/solved-by-flexbox/blob/master/assets/css/components/site.css 6 | * 7 | * .Site -> body > .container 8 | * .Site-content -> body > .container .row 9 | * .footer -> footer 10 | * 11 | * Key idea seems to be to ensure that .container and __all its parents__ 12 | * have height set to 100% 13 | * 14 | */ 15 | 16 | html, body { 17 | height: 100%; 18 | } 19 | 20 | body { 21 | position: relative; 22 | } 23 | 24 | body > .container { 25 | display: flex; 26 | height: 100%; 27 | flex-direction: column; 28 | } 29 | 30 | body > .container .row { 31 | flex: 1 0 auto; 32 | } 33 | 34 | footer { 35 | margin-top: 45px; 36 | padding: 35px 0 36px; 37 | border-top: 1px solid #e5e5e5; 38 | color: #666; 39 | display: flex; 40 | flex-shrink: 0; 41 | } 42 | footer p { 43 | margin-bottom: 0; 44 | } 45 | footer div { 46 | flex: 1; 47 | } 48 | footer .pkgdown { 49 | text-align: right; 50 | } 51 | footer p { 52 | margin-bottom: 0; 53 | } 54 | 55 | img.icon { 56 | float: right; 57 | } 58 | 59 | img { 60 | max-width: 100%; 61 | } 62 | 63 | /* Fix bug in bootstrap (only seen in firefox) */ 64 | summary { 65 | display: list-item; 66 | } 67 | 68 | /* Typographic tweaking ---------------------------------*/ 69 | 70 | .contents .page-header { 71 | margin-top: calc(-60px + 1em); 72 | } 73 | 74 | dd { 75 | margin-left: 3em; 76 | } 77 | 78 | /* Section anchors ---------------------------------*/ 79 | 80 | a.anchor { 81 | margin-left: -30px; 82 | display:inline-block; 83 | width: 30px; 84 | height: 30px; 85 | visibility: hidden; 86 | 87 | background-image: url(./link.svg); 88 | background-repeat: no-repeat; 89 | background-size: 20px 20px; 90 | background-position: center center; 91 | } 92 | 93 | .hasAnchor:hover a.anchor { 94 | visibility: visible; 95 | } 96 | 97 | @media (max-width: 767px) { 98 | .hasAnchor:hover a.anchor { 99 | visibility: hidden; 100 | } 101 | } 102 | 103 | 104 | /* Fixes for fixed navbar --------------------------*/ 105 | 106 | .contents h1, .contents h2, .contents h3, .contents h4 { 107 | padding-top: 60px; 108 | margin-top: -40px; 109 | } 110 | 111 | /* Navbar submenu --------------------------*/ 112 | 113 | .dropdown-submenu { 114 | position: relative; 115 | } 116 | 117 | .dropdown-submenu>.dropdown-menu { 118 | top: 0; 119 | left: 100%; 120 | margin-top: -6px; 121 | margin-left: -1px; 122 | border-radius: 0 6px 6px 6px; 123 | } 124 | 125 | .dropdown-submenu:hover>.dropdown-menu { 126 | display: block; 127 | } 128 | 129 | .dropdown-submenu>a:after { 130 | display: block; 131 | content: " "; 132 | float: right; 133 | width: 0; 134 | height: 0; 135 | border-color: transparent; 136 | border-style: solid; 137 | border-width: 5px 0 5px 5px; 138 | border-left-color: #cccccc; 139 | margin-top: 5px; 140 | margin-right: -10px; 141 | } 142 | 143 | .dropdown-submenu:hover>a:after { 144 | border-left-color: #ffffff; 145 | } 146 | 147 | .dropdown-submenu.pull-left { 148 | float: none; 149 | } 150 | 151 | .dropdown-submenu.pull-left>.dropdown-menu { 152 | left: -100%; 153 | margin-left: 10px; 154 | border-radius: 6px 0 6px 6px; 155 | } 156 | 157 | /* Sidebar --------------------------*/ 158 | 159 | #pkgdown-sidebar { 160 | margin-top: 30px; 161 | position: -webkit-sticky; 162 | position: sticky; 163 | top: 70px; 164 | } 165 | 166 | #pkgdown-sidebar h2 { 167 | font-size: 1.5em; 168 | margin-top: 1em; 169 | } 170 | 171 | #pkgdown-sidebar h2:first-child { 172 | margin-top: 0; 173 | } 174 | 175 | #pkgdown-sidebar .list-unstyled li { 176 | margin-bottom: 0.5em; 177 | } 178 | 179 | /* bootstrap-toc tweaks ------------------------------------------------------*/ 180 | 181 | /* All levels of nav */ 182 | 183 | nav[data-toggle='toc'] .nav > li > a { 184 | padding: 4px 20px 4px 6px; 185 | font-size: 1.5rem; 186 | font-weight: 400; 187 | color: inherit; 188 | } 189 | 190 | nav[data-toggle='toc'] .nav > li > a:hover, 191 | nav[data-toggle='toc'] .nav > li > a:focus { 192 | padding-left: 5px; 193 | color: inherit; 194 | border-left: 1px solid #878787; 195 | } 196 | 197 | nav[data-toggle='toc'] .nav > .active > a, 198 | nav[data-toggle='toc'] .nav > .active:hover > a, 199 | nav[data-toggle='toc'] .nav > .active:focus > a { 200 | padding-left: 5px; 201 | font-size: 1.5rem; 202 | font-weight: 400; 203 | color: inherit; 204 | border-left: 2px solid #878787; 205 | } 206 | 207 | /* Nav: second level (shown on .active) */ 208 | 209 | nav[data-toggle='toc'] .nav .nav { 210 | display: none; /* Hide by default, but at >768px, show it */ 211 | padding-bottom: 10px; 212 | } 213 | 214 | nav[data-toggle='toc'] .nav .nav > li > a { 215 | padding-left: 16px; 216 | font-size: 1.35rem; 217 | } 218 | 219 | nav[data-toggle='toc'] .nav .nav > li > a:hover, 220 | nav[data-toggle='toc'] .nav .nav > li > a:focus { 221 | padding-left: 15px; 222 | } 223 | 224 | nav[data-toggle='toc'] .nav .nav > .active > a, 225 | nav[data-toggle='toc'] .nav .nav > .active:hover > a, 226 | nav[data-toggle='toc'] .nav .nav > .active:focus > a { 227 | padding-left: 15px; 228 | font-weight: 500; 229 | font-size: 1.35rem; 230 | } 231 | 232 | /* orcid ------------------------------------------------------------------- */ 233 | 234 | .orcid { 235 | font-size: 16px; 236 | color: #A6CE39; 237 | /* margins are required by official ORCID trademark and display guidelines */ 238 | margin-left:4px; 239 | margin-right:4px; 240 | vertical-align: middle; 241 | } 242 | 243 | /* Reference index & topics ----------------------------------------------- */ 244 | 245 | .ref-index th {font-weight: normal;} 246 | 247 | .ref-index td {vertical-align: top; min-width: 100px} 248 | .ref-index .icon {width: 40px;} 249 | .ref-index .alias {width: 40%;} 250 | .ref-index-icons .alias {width: calc(40% - 40px);} 251 | .ref-index .title {width: 60%;} 252 | 253 | .ref-arguments th {text-align: right; padding-right: 10px;} 254 | .ref-arguments th, .ref-arguments td {vertical-align: top; min-width: 100px} 255 | .ref-arguments .name {width: 20%;} 256 | .ref-arguments .desc {width: 80%;} 257 | 258 | /* Nice scrolling for wide elements --------------------------------------- */ 259 | 260 | table { 261 | display: block; 262 | overflow: auto; 263 | } 264 | 265 | /* Syntax highlighting ---------------------------------------------------- */ 266 | 267 | pre { 268 | word-wrap: normal; 269 | word-break: normal; 270 | border: 1px solid #eee; 271 | } 272 | 273 | pre, code { 274 | background-color: #f8f8f8; 275 | color: #333; 276 | } 277 | 278 | pre code { 279 | overflow: auto; 280 | word-wrap: normal; 281 | white-space: pre; 282 | } 283 | 284 | pre .img { 285 | margin: 5px 0; 286 | } 287 | 288 | pre .img img { 289 | background-color: #fff; 290 | display: block; 291 | height: auto; 292 | } 293 | 294 | code a, pre a { 295 | color: #375f84; 296 | } 297 | 298 | a.sourceLine:hover { 299 | text-decoration: none; 300 | } 301 | 302 | .fl {color: #1514b5;} 303 | .fu {color: #000000;} /* function */ 304 | .ch,.st {color: #036a07;} /* string */ 305 | .kw {color: #264D66;} /* keyword */ 306 | .co {color: #888888;} /* comment */ 307 | 308 | .message { color: black; font-weight: bolder;} 309 | .error { color: orange; font-weight: bolder;} 310 | .warning { color: #6A0366; font-weight: bolder;} 311 | 312 | /* Clipboard --------------------------*/ 313 | 314 | .hasCopyButton { 315 | position: relative; 316 | } 317 | 318 | .btn-copy-ex { 319 | position: absolute; 320 | right: 0; 321 | top: 0; 322 | visibility: hidden; 323 | } 324 | 325 | .hasCopyButton:hover button.btn-copy-ex { 326 | visibility: visible; 327 | } 328 | 329 | /* headroom.js ------------------------ */ 330 | 331 | .headroom { 332 | will-change: transform; 333 | transition: transform 200ms linear; 334 | } 335 | .headroom--pinned { 336 | transform: translateY(0%); 337 | } 338 | .headroom--unpinned { 339 | transform: translateY(-100%); 340 | } 341 | 342 | /* mark.js ----------------------------*/ 343 | 344 | mark { 345 | background-color: rgba(255, 255, 51, 0.5); 346 | border-bottom: 2px solid rgba(255, 153, 51, 0.3); 347 | padding: 1px; 348 | } 349 | 350 | /* vertical spacing after htmlwidgets */ 351 | .html-widget { 352 | margin-bottom: 10px; 353 | } 354 | 355 | /* fontawesome ------------------------ */ 356 | 357 | .fab { 358 | font-family: "Font Awesome 5 Brands" !important; 359 | } 360 | 361 | /* don't display links in code chunks when printing */ 362 | /* source: https://stackoverflow.com/a/10781533 */ 363 | @media print { 364 | code a:link:after, code a:visited:after { 365 | content: ""; 366 | } 367 | } 368 | -------------------------------------------------------------------------------- /docs/pkgdown.js: -------------------------------------------------------------------------------- 1 | /* http://gregfranko.com/blog/jquery-best-practices/ */ 2 | (function($) { 3 | $(function() { 4 | 5 | $('.navbar-fixed-top').headroom(); 6 | 7 | $('body').css('padding-top', $('.navbar').height() + 10); 8 | $(window).resize(function(){ 9 | $('body').css('padding-top', $('.navbar').height() + 10); 10 | }); 11 | 12 | $('[data-toggle="tooltip"]').tooltip(); 13 | 14 | var cur_path = paths(location.pathname); 15 | var links = $("#navbar ul li a"); 16 | var max_length = -1; 17 | var pos = -1; 18 | for (var i = 0; i < links.length; i++) { 19 | if (links[i].getAttribute("href") === "#") 20 | continue; 21 | // Ignore external links 22 | if (links[i].host !== location.host) 23 | continue; 24 | 25 | var nav_path = paths(links[i].pathname); 26 | 27 | var length = prefix_length(nav_path, cur_path); 28 | if (length > max_length) { 29 | max_length = length; 30 | pos = i; 31 | } 32 | } 33 | 34 | // Add class to parent
  • , and enclosing
  • if in dropdown 35 | if (pos >= 0) { 36 | var menu_anchor = $(links[pos]); 37 | menu_anchor.parent().addClass("active"); 38 | menu_anchor.closest("li.dropdown").addClass("active"); 39 | } 40 | }); 41 | 42 | function paths(pathname) { 43 | var pieces = pathname.split("/"); 44 | pieces.shift(); // always starts with / 45 | 46 | var end = pieces[pieces.length - 1]; 47 | if (end === "index.html" || end === "") 48 | pieces.pop(); 49 | return(pieces); 50 | } 51 | 52 | // Returns -1 if not found 53 | function prefix_length(needle, haystack) { 54 | if (needle.length > haystack.length) 55 | return(-1); 56 | 57 | // Special case for length-0 haystack, since for loop won't run 58 | if (haystack.length === 0) { 59 | return(needle.length === 0 ? 0 : -1); 60 | } 61 | 62 | for (var i = 0; i < haystack.length; i++) { 63 | if (needle[i] != haystack[i]) 64 | return(i); 65 | } 66 | 67 | return(haystack.length); 68 | } 69 | 70 | /* Clipboard --------------------------*/ 71 | 72 | function changeTooltipMessage(element, msg) { 73 | var tooltipOriginalTitle=element.getAttribute('data-original-title'); 74 | element.setAttribute('data-original-title', msg); 75 | $(element).tooltip('show'); 76 | element.setAttribute('data-original-title', tooltipOriginalTitle); 77 | } 78 | 79 | if(ClipboardJS.isSupported()) { 80 | $(document).ready(function() { 81 | var copyButton = ""; 82 | 83 | $(".examples, div.sourceCode").addClass("hasCopyButton"); 84 | 85 | // Insert copy buttons: 86 | $(copyButton).prependTo(".hasCopyButton"); 87 | 88 | // Initialize tooltips: 89 | $('.btn-copy-ex').tooltip({container: 'body'}); 90 | 91 | // Initialize clipboard: 92 | var clipboardBtnCopies = new ClipboardJS('[data-clipboard-copy]', { 93 | text: function(trigger) { 94 | return trigger.parentNode.textContent; 95 | } 96 | }); 97 | 98 | clipboardBtnCopies.on('success', function(e) { 99 | changeTooltipMessage(e.trigger, 'Copied!'); 100 | e.clearSelection(); 101 | }); 102 | 103 | clipboardBtnCopies.on('error', function() { 104 | changeTooltipMessage(e.trigger,'Press Ctrl+C or Command+C to copy'); 105 | }); 106 | }); 107 | } 108 | })(window.jQuery || window.$) 109 | -------------------------------------------------------------------------------- /docs/pkgdown.yml: -------------------------------------------------------------------------------- 1 | pandoc: 2.11.4 2 | pkgdown: 1.6.1 3 | pkgdown_sha: ~ 4 | articles: 5 | a01_rationale: a01_rationale.html 6 | a02_add_dictionary: a02_add_dictionary.html 7 | last_built: 2022-03-02T00:44Z 8 | 9 | -------------------------------------------------------------------------------- /docs/reference/Rplot001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/gendercoder/966aaa1296bf4a5db0a3e9039dc5d6adb1de8d39/docs/reference/Rplot001.png -------------------------------------------------------------------------------- /docs/reference/fewlevels_en.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | fewlevels_en — fewlevels_en • gendercoder 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 56 | 57 | 58 | 59 | 60 | 61 | 62 |
    63 |
    64 | 118 | 119 | 120 | 121 |
    122 | 123 |
    124 |
    125 | 130 | 131 |
    132 |

    A English dictionary for the recode_gender function that has fewer levels

    133 |
    134 | 135 | 136 | 137 | 138 |
    139 | 144 |
    145 | 146 | 147 |
    148 | 151 | 152 |
    153 |

    Site built with pkgdown 1.6.1.

    154 |
    155 | 156 |
    157 |
    158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | -------------------------------------------------------------------------------- /docs/reference/figures/README-pressure-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/gendercoder/966aaa1296bf4a5db0a3e9039dc5d6adb1de8d39/docs/reference/figures/README-pressure-1.png -------------------------------------------------------------------------------- /docs/reference/figures/UI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/gendercoder/966aaa1296bf4a5db0a3e9039dc5d6adb1de8d39/docs/reference/figures/UI.png -------------------------------------------------------------------------------- /docs/reference/gendercoder.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | gendercoder: A Package for Recoding Freetext Gender Data — gendercoder • gendercoder 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 58 | 59 | 60 | 61 | 62 | 63 | 64 |
    65 |
    66 | 120 | 121 | 122 | 123 |
    124 | 125 |
    126 |
    127 | 132 | 133 |
    134 |

    Provides dictionaries and a function recode_gender 135 | to allow for easy automatic coding of common variations in free text 136 | responses to the question "What is your gender?"

    137 |
    138 | 139 | 140 | 141 | 142 |
    143 | 148 |
    149 | 150 | 151 |
    152 | 155 | 156 |
    157 |

    Site built with pkgdown 1.6.1.

    158 |
    159 | 160 |
    161 |
    162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | -------------------------------------------------------------------------------- /docs/reference/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Function reference • gendercoder 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 55 | 56 | 57 | 58 | 59 | 60 | 61 |
    62 |
    63 | 117 | 118 | 119 | 120 |
    121 | 122 |
    123 |
    124 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 153 | 154 | 155 | 156 | 159 | 160 | 161 | 162 | 165 | 166 | 167 | 168 | 171 | 172 | 173 | 174 | 177 | 178 | 179 | 180 |
    139 |

    All functions

    140 |

    141 |
    151 |

    fewlevels_en

    152 |

    fewlevels_en

    157 |

    gendercoder

    158 |

    gendercoder: A Package for Recoding Freetext Gender Data

    163 |

    manylevels_en

    164 |

    manylevels_en

    169 |

    recode_gender()

    170 |

    recode_gender

    175 |

    sample

    176 |

    sample

    181 |
    182 | 183 | 188 |
    189 | 190 | 191 |
    192 | 195 | 196 |
    197 |

    Site built with pkgdown 1.6.1.

    198 |
    199 | 200 |
    201 |
    202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | -------------------------------------------------------------------------------- /docs/reference/manylevels_en.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | manylevels_en — manylevels_en • gendercoder 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 56 | 57 | 58 | 59 | 60 | 61 | 62 |
    63 |
    64 | 118 | 119 | 120 | 121 |
    122 | 123 |
    124 |
    125 | 130 | 131 |
    132 |

    A English dictionary for the recode_gender function that has many levels

    133 |
    134 | 135 | 136 | 137 | 138 |
    139 | 144 |
    145 | 146 | 147 |
    148 | 151 | 152 |
    153 |

    Site built with pkgdown 1.6.1.

    154 |
    155 | 156 |
    157 |
    158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | -------------------------------------------------------------------------------- /docs/reference/recode_gender.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | recode_gender — recode_gender • gendercoder 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 57 | 58 | 59 | 60 | 61 | 62 | 63 |
    64 |
    65 | 119 | 120 | 121 | 122 |
    123 | 124 |
    125 |
    126 | 131 | 132 |
    133 |

    recode_gender matches uncleaned gender responses to cleaned list using 134 | an built-in or custom dictionary.

    135 |
    136 | 137 |
    recode_gender(
    138 |   gender = gender,
    139 |   dictionary = gendercoder::manylevels_en,
    140 |   retain_unmatched = FALSE
    141 | )
    142 | 143 |

    Arguments

    144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 155 | 156 | 157 | 158 | 160 | 161 |
    gender

    a character vector of gender responses for recoding

    dictionary

    a list that the contains gender responses and their 153 | replacement values. A built-in dictionary manylevels_en is used by 154 | default if an alternative dictionary is not supplied.

    retain_unmatched

    logical indicating if gender responses that are not found in 159 | dictionary should be filled with the uncleaned values during recoding

    162 | 163 |

    Value

    164 | 165 |

    a character vector of recoded genders

    166 | 167 |

    Examples

    168 |
    169 | 170 | df <- data.frame( 171 | stringsAsFactors = FALSE, 172 | gender = c("male", "MALE", "mle", "I am male", "femail", "female", "enby"), 173 | age = c(34L, 37L, 77L, 52L, 68L, 67L, 83L) 174 | ) 175 | 176 | df %>% mutate(recoded_gender = recode_gender(gender, 177 | dictionary = manylevels_en, 178 | retain_unmatched = TRUE 179 | )) 180 |
    #> Error in df %>% mutate(recoded_gender = recode_gender(gender, dictionary = manylevels_en, retain_unmatched = TRUE)): could not find function "%>%"
    181 |
    182 |
    183 | 188 |
    189 | 190 | 191 |
    192 | 195 | 196 |
    197 |

    Site built with pkgdown 1.6.1.

    198 |
    199 | 200 |
    201 |
    202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | -------------------------------------------------------------------------------- /docs/reference/sample.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | sample — sample • gendercoder 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 56 | 57 | 58 | 59 | 60 | 61 | 62 |
    63 |
    64 | 118 | 119 | 120 | 121 |
    122 | 123 |
    124 |
    125 | 130 | 131 |
    132 |

    A sample data.frame of free text gender in English for testing and demonstration

    133 |
    134 | 135 | 136 | 137 | 138 |
    139 | 144 |
    145 | 146 | 147 |
    148 | 151 | 152 |
    153 |

    Site built with pkgdown 1.6.1.

    154 |
    155 | 156 |
    157 |
    158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | -------------------------------------------------------------------------------- /gendercodeR.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | ProjectId: a49eb04b-5dce-42fc-81b2-0a0bdf312dcd 3 | 4 | RestoreWorkspace: No 5 | SaveWorkspace: No 6 | AlwaysSaveHistory: Default 7 | 8 | EnableCodeIndexing: Yes 9 | UseSpacesForTab: Yes 10 | NumSpacesForTab: 2 11 | Encoding: UTF-8 12 | 13 | RnwWeave: Sweave 14 | LaTeX: pdfLaTeX 15 | 16 | AutoAppendNewline: Yes 17 | StripTrailingWhitespace: Yes 18 | 19 | BuildType: Package 20 | PackageUseDevtools: Yes 21 | PackageInstallArgs: --no-multiarch --with-keep.source 22 | PackageRoxygenize: rd,collate,namespace 23 | -------------------------------------------------------------------------------- /inst/extdata/GenderDictionary_List.csv: -------------------------------------------------------------------------------- 1 | entries,manylevels_en,fewlevels_en 2 | female,female,female 3 | male,male,male 4 | androgynous,androgynous,sex and gender diverse 5 | non-binary,non-binary,sex and gender diverse 6 | nonbinary,non-binary,sex and gender diverse 7 | non binary,non-binary,sex and gender diverse 8 | trans,transgender,sex and gender diverse 9 | trans man,transgender male,male 10 | trans woman,transgender female,female 11 | transman,transgender male,male 12 | transwoman,transgender female,female 13 | transgender man,transgender male,male 14 | transgenderman,transgender male,male 15 | transgender male,transgender male,male 16 | transgendermale,transgender male,male 17 | transgender woman,transgender female,female 18 | transgender female,transgender female,female 19 | transgenderwoman,transgender female,female 20 | transgenderfemale,transgender female,female 21 | cis woman,cis female,female 22 | ciswoman,cis female,female 23 | cisfemale,cis female,female 24 | cis female,cis female,female 25 | female (cisgender),cis female,female 26 | cis man,cis male,male 27 | cisman,cis male,male 28 | cismale,cis male,male 29 | cis male,cis male,male 30 | male (cisgender),cis male,male 31 | girl,female,female 32 | boy,male,male 33 | intersex,intersex,sex and gender diverse 34 | m2f,transgender female,female 35 | f2m,transgender male,male 36 | mtf,transgender female,female 37 | ftm,transgender male,male 38 | m,male,male 39 | f,female,female 40 | w,female,female 41 | man,male,male 42 | woman,female,female 43 | famela,female,female 44 | fem,female,female 45 | femaiil,female,female 46 | femaile,female,female 47 | femalep,female,female 48 | feminine,female,female 49 | g,female,female 50 | maill,male,male 51 | malae,male,male 52 | man,male,male 53 | nb,non-binary,sex and gender diverse 54 | enby,non-binary,sex and gender diverse 55 | agender,agender,sex and gender diverse 56 | genderqueer,genderqueer,sex and gender diverse 57 | gender queer,genderqueer,sex and gender diverse 58 | -------------------------------------------------------------------------------- /man/fewlevels_en.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/gendercodeR.R 3 | \docType{data} 4 | \name{fewlevels_en} 5 | \alias{fewlevels_en} 6 | \title{fewlevels_en} 7 | \description{ 8 | A English dictionary for the recode_gender function that has fewer levels 9 | } 10 | -------------------------------------------------------------------------------- /man/figures/README-pressure-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/gendercoder/966aaa1296bf4a5db0a3e9039dc5d6adb1de8d39/man/figures/README-pressure-1.png -------------------------------------------------------------------------------- /man/figures/UI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/gendercoder/966aaa1296bf4a5db0a3e9039dc5d6adb1de8d39/man/figures/UI.png -------------------------------------------------------------------------------- /man/gendercoder.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/gendercodeR.R 3 | \docType{package} 4 | \name{gendercoder} 5 | \alias{gendercoder-package} 6 | \alias{gendercoder} 7 | \title{gendercoder: A Package for Recoding Freetext Gender Data} 8 | \description{ 9 | Provides dictionaries and a function \code{recode_gender} to allow for easy automatic coding of common variations in free text responses to the question \strong{"What is your gender?"} 10 | } 11 | \seealso{ 12 | Useful links: 13 | \itemize{ 14 | \item \url{https://github.com/ropensci/gendercoder} 15 | \item Report bugs at \url{https://github.com/ropensci/gendercoder/issues} 16 | } 17 | 18 | } 19 | \author{ 20 | \strong{Maintainer}: Yaoxiang Li \email{liyaoxiang@outlook.com} (\href{https://orcid.org/0000-0001-9200-1016}{ORCID}) 21 | 22 | Authors: 23 | \itemize{ 24 | \item Jennifer Beaudry \email{jbeaudry@swin.edu.au} (\href{https://orcid.org/0000-0003-1596-6708}{ORCID}) 25 | \item Emily Kothe \email{emily.kothe@deakin.edu.au} (\href{https://orcid.org/0000-0003-1210-0554}{ORCID}) 26 | \item Felix Singleton Thorn \email{fsingletonthorn@gmail.com} (\href{https://orcid.org/0000-0002-0237-6146}{ORCID}) 27 | \item Rhydwyn McGuire \email{rhydwyn@rhydwyn.net} 28 | \item Nicholas Tierney \email{nicholas.tierney@gmail.com} (\href{https://orcid.org/0000-0003-1460-8722}{ORCID}) 29 | \item Mathew Ling \email{mathewtyling@gmail.com} (\href{https://orcid.org/0000-0002-0940-2538}{ORCID}) 30 | } 31 | 32 | Other contributors: 33 | \itemize{ 34 | \item Julia Silge (Julia reviewed the package (v. 0.0.0.9000) for rOpenSci, see ) [reviewer] 35 | \item Elin Waring (Elin reviewed the package (v. 0.0.0.9000) for rOpenSci, see ) [reviewer] 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /man/manylevels_en.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/gendercodeR.R 3 | \docType{data} 4 | \name{manylevels_en} 5 | \alias{manylevels_en} 6 | \title{manylevels_en} 7 | \description{ 8 | A English dictionary for the recode_gender function that has many levels 9 | } 10 | -------------------------------------------------------------------------------- /man/recode_gender.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/recode_gender.R 3 | \name{recode_gender} 4 | \alias{recode_gender} 5 | \title{recode_gender} 6 | \usage{ 7 | recode_gender( 8 | gender, 9 | dictionary = gendercoder::manylevels_en, 10 | retain_unmatched = FALSE 11 | ) 12 | } 13 | \arguments{ 14 | \item{gender}{a character vector of gender responses for recoding} 15 | 16 | \item{dictionary}{a list that the contains gender responses and their 17 | replacement values. A built-in dictionary \code{manylevels_en} is used by 18 | default if an alternative dictionary is not supplied.} 19 | 20 | \item{retain_unmatched}{logical indicating if gender responses that are not found in 21 | dictionary should be filled with the uncleaned values during recoding} 22 | } 23 | \value{ 24 | a character vector of recoded genders 25 | } 26 | \description{ 27 | \code{recode_gender} matches uncleaned gender responses to cleaned list using 28 | an built-in or custom dictionary. 29 | } 30 | \examples{ 31 | 32 | 33 | df <- data.frame( 34 | stringsAsFactors = FALSE, 35 | gender = c("male", "MALE", "mle", "I am male", "femail", "female", "enby"), 36 | age = c(34L, 37L, 77L, 52L, 68L, 67L, 83L) 37 | ) 38 | 39 | dplyr::mutate(df, recoded_gender = recode_gender(gender, 40 | dictionary = manylevels_en, 41 | retain_unmatched = TRUE 42 | )) 43 | 44 | } 45 | -------------------------------------------------------------------------------- /man/sample.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/gendercodeR.R 3 | \docType{data} 4 | \name{sample} 5 | \alias{sample} 6 | \title{sample} 7 | \description{ 8 | A sample data.frame of free text gender in English for testing and demonstration 9 | } 10 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(gendercoder) 3 | 4 | test_check("gendercoder") 5 | -------------------------------------------------------------------------------- /tests/testthat/.gitignore: -------------------------------------------------------------------------------- 1 | .Rapp.history 2 | -------------------------------------------------------------------------------- /tests/testthat/test-recode_gender.R: -------------------------------------------------------------------------------- 1 | context("gender_recode") 2 | library(gendercoder) 3 | 4 | test_that("Recodes common typos",{ 5 | expect_match(recode_gender("enby", dictionary = manylevels_en, retain_unmatched = TRUE), "non-binary") 6 | expect_match(recode_gender("mlae", dictionary = manylevels_en, retain_unmatched = TRUE), "man") 7 | expect_match(recode_gender("famela", dictionary = manylevels_en, retain_unmatched = TRUE), "woman") 8 | expect_match(recode_gender("enby", dictionary = fewlevels_en, retain_unmatched = TRUE), "sex and gender diverse") 9 | expect_match(recode_gender("enby", dictionary = fewlevels_en, retain_unmatched = FALSE), "sex and gender diverse") 10 | 11 | }) 12 | 13 | test_that("Dictionaries generate different outcomes", { 14 | 15 | expect_true(recode_gender("enby", dictionary = manylevels_en, retain_unmatched = TRUE) != 16 | recode_gender("enby", dictionary = fewlevels_en, retain_unmatched = TRUE)) 17 | }) 18 | 19 | test_that("Leaves blanks if retain_unmatched = FALSE", { 20 | expect_true(is.na(recode_gender("apache", dictionary = fewlevels_en, retain_unmatched = FALSE))) 21 | 22 | }) 23 | 24 | test_that("Warns regarding replacement", { 25 | expect_message(recode_gender(c("mlae", "fish"), retain_unmatched = TRUE), 26 | regexp = "Results not matched from the dictionary have been filled with the user inputted values") 27 | }) 28 | 29 | test_that("Input matches output length", { 30 | expect_equal(length(1:3), length(recode_gender(1:3))) 31 | }) 32 | 33 | test_that("Error if dictionary not supplied as a character vector", { 34 | expect_error(recode_gender(c("mlae"), dictionary = 1:7), 35 | regexp = "The supplied dictionary is not a character vector") 36 | }) 37 | -------------------------------------------------------------------------------- /vignettes/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | *.R 3 | -------------------------------------------------------------------------------- /vignettes/a01_rationale.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Introduction to gendercoder" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{Introduction to gendercoder} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | The goal of gendercoder is to allow simple recoding of free-text gender responses. 11 | 12 | ## Installation 13 | 14 | This package is not on CRAN. To use this package please run the following code: 15 | 16 | ``` r 17 | devtools::install_github("ropensci/gendercoder") 18 | library(gendercoder) 19 | ``` 20 | 21 | ## Why would we do this? 22 | 23 | Researchers who collect self-reported demographic data from respondents 24 | occasionally collect gender using a free-text response option. This has the 25 | advantage of respecting the gender diversity of respondents without prompting 26 | users and potentially including misleading responses. However, this presents a 27 | challenge to researchers in that some inconsistencies in typography and spelling 28 | create a larger set of responses than would be required to fully capture the 29 | demographic characteristics of the sample. 30 | 31 | For example, male participants may provide free-text responses as "male", "man", 32 | "mail", "mael". Non-binary participants may provide responses as "nonbinary", 33 | "enby", "non-binary", "non binary" 34 | 35 | Manually coding of such free-text responses this is often not feasible with 36 | larger datasets. `gendercoder()` uses dictionaries of common 37 | misspellings to re-code free-text responses into a consistent set of 38 | responses. The small number of responses not automatically re-coded by 39 | gendercoder() can then be feasibly manually recoded. 40 | 41 | ## Motivating example 42 | 43 | `gendercoder()` includes a sample dataset with actual free-text 44 | responses to the question "What is your gender?" from a number of studies of 45 | English-speaking participants. The sample dataset includes responses from 7756 46 | participants. Naive coding identifies 103 unique responses to this item. 47 | 48 | 49 | ```{r message = FALSE, warning= FALSE} 50 | library(gendercoder) 51 | library(dplyr) 52 | 53 | sample %>% 54 | group_by(Gender) %>% 55 | summarise(count = n()) %>% 56 | arrange(-count) %>% 57 | knitr::kable(caption = "Summary of gender categories before coding") 58 | ``` 59 | 60 | Recoding using the `gender_coder()` function classifies all but 28 responses 61 | into pre-defined response categories. 62 | 63 | ```{r} 64 | sample %>% 65 | head(10) %>% 66 | mutate(recoded_gender = recode_gender(gender = Gender, dictionary = manylevels_en)) %>% 67 | knitr::kable(caption = "The manylevels_en dictionary applied to `head(sample)`") 68 | 69 | sample %>% 70 | mutate(recoded_gender = recode_gender(gender = Gender, dictionary = manylevels_en)) %>% 71 | filter(!is.na(recoded_gender)) %>% 72 | group_by(recoded_gender) %>% 73 | summarise(count = n()) %>% 74 | arrange(-count) %>% 75 | knitr::kable(caption = "Summary of gender categories after use of the *manylevels_en* dictionary") 76 | 77 | ``` 78 | 79 | In this dataset unclassified responses are a mix of unusual responses and 80 | apparent response errors (e.g. numbers and symbols). While some of these are 81 | genuinely missing (i.e. Gender = 40), other could be manually recoded, or added 82 | to a custom dictionary. 83 | 84 | ```{r} 85 | 86 | sample %>% 87 | mutate(recoded_gender = recode_gender(gender = Gender, dictionary = manylevels_en)) %>% 88 | filter(is.na(recoded_gender)) %>% 89 | knitr::kable(caption = "All responses not classified by the built-in dictionary") 90 | 91 | ``` 92 | 93 | ## Options within the function 94 | 95 | ### dictionary 96 | 97 | The package provides two built-in dictionaries. The use of these is controlled 98 | using the `dictionary` argument. The first `dictionary = manylevels_en` provides 99 | corrects spelling and standardises terms while maintaining the diversity of responses. 100 | This is the default dictionary for gendercoder() as it preserves as much gender 101 | diversity as possible. 102 | 103 | However in some cases you may wish to collapse gender into a smaller set of 104 | categories by using the `fewlevels_en` dictionary (`dictionary = fewlevels_en`). This 105 | dictionary contains fewer gender categories, "man", "woman", 106 | "boy", "girl", and "sex and gender diverse". 107 | 108 | The "man" category includes all participants who indicate that they are 109 | 110 | - male 111 | - trans male (including female to male transgender respondents) 112 | - cis male 113 | 114 | The "woman" category includes all participants who indicate that they are 115 | 116 | - female 117 | - trans female (including male to female transgender respondents) 118 | - cis female 119 | 120 | The "sex and gender diverse" category includes all participants who indicate 121 | that they are 122 | 123 | - agender 124 | - androgynous 125 | - intersex 126 | - non-binary 127 | - gender-queer 128 | 129 | ```{r} 130 | sample %>% 131 | head(10) %>% 132 | mutate(recoded_gender = recode_gender(gender = Gender, dictionary = fewlevels_en)) %>% 133 | knitr::kable(caption = "The fewlevels_en dictionary applied to `head(sample)`") 134 | 135 | sample %>% 136 | mutate(recoded_gender = recode_gender(gender = Gender, dictionary = fewlevels_en)) %>% 137 | group_by(recoded_gender) %>% 138 | summarise(count = n()) %>% 139 | arrange(-count) %>% 140 | knitr::kable(caption = "Summary of gender categories after use of the *fewlevels_en* dictionary") 141 | ``` 142 | 143 | You can also specify a custom dictionary to replace or supplement the built-in 144 | dictionary. The custom dictionary should be a list in the following 145 | format. 146 | 147 | ```{r} 148 | # name of the vector element is the user input value and the vector element is the 149 | # replacement value corresponding to that name as a lower case string. 150 | custom_dictionary <- c( 151 | masculino = "man", 152 | hombre = "man", 153 | mujer = "woman", 154 | femenina = "woman" 155 | ) 156 | 157 | str(custom_dictionary) 158 | ``` 159 | 160 | Custom dictionaries can be used in place of a built-in dictionary or can 161 | supplement the built-in dictionary by providing a vector of vectors to the 162 | dictionary argument. Where the lists contain duplicated elements, the last 163 | version of the duplicated value will be used for recoding. This allows you to 164 | use the built-in dictionary but change the coding of one or more responses from 165 | that dictionary. Here the addition of Spanish terms allows for recoding of 11 166 | previously uncoded responses. 167 | 168 | ```{r} 169 | 170 | sample %>% 171 | mutate(recoded_gender = recode_gender(gender = Gender, 172 | dictionary = c(fewlevels_en, 173 | custom_dictionary))) %>% 174 | group_by(recoded_gender) %>% 175 | summarise(count = n()) %>% 176 | arrange(-count) %>% 177 | knitr::kable(caption = "Summary of gender categories after use of the combined dictionaries") 178 | 179 | 180 | sample %>% 181 | mutate(recoded_gender = recode_gender(gender = Gender, 182 | dictionary = c(fewlevels_en, 183 | custom_dictionary))) %>% 184 | filter(is.na(recoded_gender)) %>% 185 | knitr::kable(caption = "All responses not classified by the combined dictionaries") 186 | ``` 187 | 188 | ### retain_unmatched 189 | 190 | The `retain_unmatched` argument is used to determine the handling for recoding of values 191 | not contained in the dictionary. By default, unmatched values are coded as NA. 192 | `retain_unmatched = TRUE` will fill unmatched responses with the participant provided 193 | response. 194 | 195 | ```{r} 196 | sample %>% 197 | mutate(recoded_gender = recode_gender(gender = Gender, 198 | dictionary = c(fewlevels_en, 199 | custom_dictionary), 200 | retain_unmatched = TRUE)) %>% 201 | group_by(recoded_gender) %>% 202 | summarise(count = n()) %>% 203 | arrange(-count) %>% 204 | knitr::kable(caption = "Summary of gender categories after use of the combined dictionary and `retain_unmatched = TRUE`") 205 | ``` 206 | 207 | # A disclaimer on handling gender responses 208 | 209 | This package attempts to remove typographical errors from free text gender data. 210 | The defaults that we used are specific to our context and the time at which the 211 | package was developed and your data or context may be different. 212 | 213 | We offer two built-in dictionaries, manylevels_en and fewlevels_en. Both are necessarily 214 | opinionated about how gender descriptors collapse into categories. 215 | 216 | However, as these are culturally specific, they may not be suitable for your data. 217 | In particular the fewlevels_en option makes opinionated choices about some responses that we want to acknowledge are potentially problematic. Specifically, 218 | 219 | - In 'fewlevels_en' coding intersex responses are recoded as 'sex and gender 220 | diverse' 221 | - In 'fewlevels_en' responses where people indicate they are trans and 222 | indicate their identified gender are recoded as the identified gender 223 | (e.g. 'Male to Female' is recoded as 'woman'). We wish to acknowledge 224 | that this may not reflect how some individuals would classify 225 | themselves when given these categories and in some contexts may make 226 | systematic errors. The manylevels_en coding dictionary attempts to avoid these 227 | issues as much as possible - however users can provide a custom 228 | dictionary to add to or overwrite our coding decisions if they feel 229 | this is more appropriate. We welcome people to update the built-in dictionary 230 | where desired responses are missing. 231 | - In both dictionaries, we assume that typographical features such as spacing 232 | are not relevant to recoding the gender response (e.g. we assume that 233 | "genderqueer" and "gender queer" are equivalent). This is unlikely to be 234 | true for all contexts. 235 | 236 | 237 | The 'manylevels_en' coding separates out those who identify as trans 238 | female/male or cis female/male into separate categories it should not 239 | be assumed that all people who describe as male/female are cis, if you 240 | are assessing trans status we recommend a two part question see: 241 | 242 | Bauer, Greta & Braimoh, Jessica & Scheim, Ayden & Dharma, Christoffer. 243 | (2017). Transgender-inclusive measures of sex/gender for population surveys: 244 | Mixed-methods evaluation and recommendations. PLoS ONE. 12. 245 | 246 | # Contributing to this package 247 | 248 | This package is a reflection of cultural context of the package contributors. 249 | We acknowledge that understandings of gender are bound by both culture and time 250 | and are continually changing. As such, we welcome issues and pull requests to 251 | make the package more inclusive, more reflective of current understandings of 252 | gender inclusive languages and/or suitable for a broader range of cultural 253 | contexts. We particularly welcome addition of non-English dictionaries or of 254 | other gender-diverse responses to the manylevels_en and fewlevels_en dictionaries. 255 | 256 | The ["Adding to the dictionary"](https://ropensci.github.io/gendercoder/articles/a02_add_dictionary.html) vignette includes information about how to make changes to the dictionary either for your own use or when contributiong to the gendercoder package. 257 | 258 | # Acknowledgement of Country 259 | 260 | We acknowledge the Wurundjeri people of the Kulin Nation as the custodians of 261 | the land on which this package was developed and pay respects to elders past, 262 | present and future. 263 | -------------------------------------------------------------------------------- /vignettes/a02_add_dictionary.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Adding to the dictionary" 3 | output: rmarkdown::html_vignette 4 | vignette: > 5 | %\VignetteIndexEntry{Adding to the dictionary} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | ```{r, include = FALSE} 11 | knitr::opts_chunk$set( 12 | collapse = TRUE, 13 | comment = "#>" 14 | ) 15 | ``` 16 | 17 | ```{r setup, echo = FALSE, message=FALSE} 18 | df <- dplyr::tibble(gender = c("male", "enby", "womn", "mlae", "mann", "frau", "femme", 19 | "homme", "nin")) 20 | ``` 21 | ## Outline 22 | 23 | While the `gendercoder` dictionaries aim to be as comprehensive as possible, it 24 | is inevitable that new typos and variations will occur in wild data. Moreover, 25 | at present, the dictionaries are limited to data the authors have had access to 26 | which has been collected in English. As such, if you are collecting data, you 27 | will at some point want to add to or create your own dictionaries (and if so, 28 | we strongly encourage contributions either as [a pull request via github](https://github.com/ropensci/gendercoder), or by [raising an issue](https://github.com/ropensci/gendercoder/issues/new) so the team can 29 | help). 30 | 31 | ## Adding to the dictionary 32 | 33 | Let's say I have free-text gender data, but some of it is not in English. 34 | 35 | ```{r example-data, message=FALSE} 36 | library(gendercoder) 37 | library(dplyr) 38 | df 39 | ``` 40 | 41 | I can create a new dictionary by creating a named vector, where the names are 42 | the raw, uncoded values, and the values are the desired outputs. This can then 43 | be used as the dictionary in the `recode_gender()` function. 44 | 45 | ```{r new-dictionary} 46 | new_dictionary <- c( 47 | mann = "man", 48 | frau = "woman", 49 | femme = "woman", 50 | homme = "man", 51 | nin = "man") 52 | 53 | df %>% 54 | mutate(recoded_gender = recode_gender(gender, 55 | dictionary = new_dictionary, 56 | retain_unmatched = TRUE)) 57 | 58 | ``` 59 | However, as you can see using just this new dictionary leaves a number of 60 | responses uncoded that the built-in dictionaries could handle. As the 61 | dictionaries are just vectors, we can simply concatenate these to use both at 62 | the same time. 63 | 64 | We can do this in-line... 65 | 66 | ```{r inline-augmentation} 67 | df %>% 68 | mutate(recoded_gender = recode_gender(gender, 69 | dictionary = c(manylevels_en, new_dictionary), 70 | retain_unmatched = TRUE)) 71 | ``` 72 | Or otherwise we can create a new dictionary and call that later, useful if you 73 | might want to save an augmented dictionary for later use or for contributing to 74 | the package. 75 | ```{r stepped-augmentation} 76 | manylevels_plus <- c(manylevels_en, new_dictionary) 77 | 78 | df %>% 79 | mutate(recoded_gender = recode_gender(gender, 80 | dictionary = manylevels_plus, 81 | retain_unmatched = TRUE)) 82 | ``` 83 | 84 | ## Making it official 85 | 86 | Let's say you are happy with your `manylevels_plus` dictionary and think it should be 87 | part of the `manylevels_en` dictionary in the package. All you need to do is [fork the 88 | gendercoder repo](https://docs.github.com/en/get-started/quickstart/fork-a-repo), 89 | [clone it to your local device](https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/cloning-a-repository-from-github/cloning-a-repository), and then rename 90 | your vector and use the `usethis::use_data()` function to overwrite the `manylevels_en` 91 | dictionary as shown below. 92 | 93 | ```{r replacing-dictionaries, eval=FALSE} 94 | manylevels_en <- manylevels_plus 95 | usethis::use_data(manylevels_en, overwrite = TRUE) 96 | ``` 97 | 98 | Once you've pushed the changes to your fork, you can [make a pull request](https://docs.github.com/en/github/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork). Please tell us 99 | what you're adding so we know what to look out for and how to test it. 100 | 101 | --------------------------------------------------------------------------------