unheadr

Handle Data With Embedded Subheaders

https://github.com/luisdva/unheadr

Science Score: 26.0%

This score indicates how likely this project is to be science-related based on various indicators:

  • CITATION.cff file
  • codemeta.json file
    Found codemeta.json file
  • .zenodo.json file
  • DOI references
    Found 6 DOI reference(s) in README
  • Academic publication links
  • Committers with academic emails
  • Institutional organization owner
  • JOSS paper metadata
  • Scientific vocabulary similarity
    Low similarity (19.2%) to scientific vocabulary
Last synced: 10 months ago · JSON representation

Repository

Handle Data With Embedded Subheaders

Basic Info
  • Host: GitHub
  • Owner: luisDVA
  • License: other
  • Language: R
  • Default Branch: master
  • Homepage: https://unheadr.liomys.mx/
  • Size: 23.3 MB
Statistics
  • Stars: 60
  • Watchers: 6
  • Forks: 2
  • Open Issues: 1
  • Releases: 5
Created about 8 years ago · Last pushed about 2 years ago
Metadata Files
Readme License

README.Rmd

---
output: github_document
---



```{r setup, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  fig.path = "man/figures/README-",
  out.width = "100%"
)
```

# unheadr 


[![](https://img.shields.io/badge/doi-10.4404/hystrix--00133--2018-red.svg)](https://doi.org/10.4404/hystrix-00133-2018)
[![](https://www.r-pkg.org/badges/version/unheadr?color=purple)](https://cran.r-project.org/package=unheadr)
[![](http://cranlogs.r-pkg.org/badges/last-month/unheadr?color=orange)](https://cran.r-project.org/package=unheadr)
[![](http://cranlogs.r-pkg.org/badges/grand-total/unheadr?color=blue)](https://cran.r-project.org/package=unheadr)
[![Codecov test coverage](https://codecov.io/gh/luisDVA/unheadr/branch/master/graph/badge.svg)](https://app.codecov.io/gh/luisDVA/unheadr?branch=master)


The goal of `unheadr` is to help wrangle data when it has embedded subheaders, or when values are wrapped across several rows. https://unheadr.liomys.mx/


## Installation


You can install the CRAN release or the development version with:

``` r
# Install unheadr from CRAN:
install.packages("unheadr")

# Or install the development version from GitHub with:
# install.packages("remotes")
remotes::install_github("luisDVA/unheadr")
```

The reasoning behind the package and some of the possible uses of `unheadr` are described in this publication:

Verde Arregoitia, L. D., Cooper, N., D'Elía, G. (2018). Good practices for sharing analysis-ready data in mammalogy and biodiversity research. _Hystrix, the Italian Journal of Mammalogy_, 29(2), 155-161. [Open Access, DOI 10.4404/hystrix-00133-2018](https://doi.org/10.4404/hystrix-00133-2018)

## Usage  

Load the package first.
```{r}
library(unheadr)
```

### Main functions  

**`untangle2()`**  
  
`untangle2()` puts embedded subheaders into their own variable, using regular expressions to identify them. 

In the data below (a subset of a bundled dataset which can be loaded with `data(primates2017)`), there are rows that correspond to values in grouping variables. These should be in their own column. Instead, they are embedded within the data rectangle. This is a common practice in many disciplines. This data presentation looks OK and is easy to read, but hard to work with (for example: calculating group-wise summaries). 

In this example, values for an implicit "geographic region" variable and an implicit "taxonomic family" variable are embedded in the column that contains the observational units (the scientific names of various primates).  

|scientific_name              |common_name                  |red_list_status | mass_kg|
|:----------------------------|:----------------------------|:---------------|-------:|
|Asia                         |NA                           |NA              |      NA|
|CERCOPITHECIDAE              |NA                           |NA              |      NA|
|Trachypithecus obscurus      |Dusky Langur                 |NT              |    7.13|
|Presbytis sumatra            |Black Sumatran Langur        |EN              |    6.00|
|Rhinopithecus roxellana      |Golden Snub-nosed Monkey     |EN              |      NA|
|HYLOBATIDAE                  |NA                           |NA              |      NA|
|Hylobates funereus           |East Bornean Gray Gibbon     |EN              |      NA|
|Hylobates klossii            |Kloss's Gibbon               |EN              |    5.80|
|Nomascus concolor            |Western Black Crested Gibbon |CR              |    7.71|


For a tidier structure, the subheaders embedded in the _scientific\_name_ column need to be plucked out and placed in their own variable. This was initially the main objective of `unheadr` and what `untangle2()` was made for. The function can be used with `magrittr` pipes as a `dplyr`-type verb.

If these subheaders can be matched in bulk with a regular expression because they share a prefix, suffix, or anything in common, we can save a lot of time. Otherwise, they can be matched by name. For more details, see the examples and vignette.

The 'untangled' version of the data:

|scientific_name              |common_name                  |red_list_status | mass_kg|family          |region     |
|:----------------------------|:----------------------------|:---------------|-------:|:---------------|:----------|
|Trachypithecus obscurus      |Dusky Langur                 |NT              |    7.13|CERCOPITHECIDAE |Asia       |
|Presbytis sumatra            |Black Sumatran Langur        |EN              |    6.00|CERCOPITHECIDAE |Asia       |
|Rhinopithecus roxellana      |Golden Snub-nosed Monkey     |EN              |      NA|CERCOPITHECIDAE |Asia       |
|Hylobates funereus           |East Bornean Gray Gibbon     |EN              |      NA|HYLOBATIDAE    |Asia       |
|Hylobates klossii            |Kloss's Gibbon               |EN              |    5.80|HYLOBATIDAE    |Asia       |
|Nomascus concolor            |Western Black Crested Gibbon |CR              |    7.71|HYLOBATIDAE    |Asia       |


Now we can easily perform grouping operations and summarize the data (e.g. calculating average body mass by Family).


**`unbreak_vals()`**

This function uses regex to fix values that are broken across two rows. This usually happens when we are formatting a table and we need to fit it on a page.

```{r}
# Set up a toy dataset
dogsDesc <-
  data.frame(
    stringsAsFactors = FALSE,
    dogs = c(
      "Retriever", "(Golden)",
      "Retriever", "(Labrador)", "Bulldog", "(French)"
    ),
    coat = c("long", NA, "short", NA, "short", NA)
  )

dogsDesc
```


We can match the opening brackets with regex.

```{r}
unbreak_vals(df = dogsDesc, regex = "^\\(", ogcol = dogs, newcol = dogs_unbroken)
```


**`unwrap_cols()`**

Use this function to unwrap and glue values that have been wrapped across multiple rows for presentation purposes, with an inconsistent number of empty or `NA` values padding out the columns.

```{r}
# Set up the data
nyk <-
  data.frame(
    stringsAsFactors = FALSE,
    player = c(
      "Marcus Camby", NA, NA,
      NA, NA, NA, NA, "Allan Houston", NA,
      "Latrell Sprewell", NA, NA
    ),
    listed_height_m. = c(
      2.11, NA, NA, NA, NA, NA,
      NA, 1.98, NA, 1.96, NA, NA
    ),
    teams_chronological = c(
      "Raptors", "Knicks",
      "Nuggets", "Clippers", "Trail Blazers",
      "Rockets", "Knicks", "Pistons",
      "Knicks", "Warriors", "Knicks",
      "Timberwolves"
    ),
    position = c(
      "Power forward", "Center",
      NA, NA, NA, NA, NA,
      "Shooting guard", NA, "Small forward", NA, NA
    )
  )
nyk
```



Unwrap the elements in the variable that defines the groups, separating with commas.

```{r}
unwrap_cols(nyk, groupingVar = player, separator = ", ")
```


**`unbreak_rows()`**

This function merges sets of two contiguous rows upwards by pasting the values of the lagging row to the values of the leading row (identified using regular expressions).

The following table of basketball records has two sets of header rows with values broken across two contiguous rows.

```{r}
bball <- data.frame(
  stringsAsFactors = FALSE,
  v1 = c(
    "Player", NA, "Sleve McDichael", "Dean Wesrey",
    "Karl Dandleton", "Player",
    NA,
    "Mike Sernandez",
    "Glenallen Mixon",
    "Rey McSriff"
  ),
  v2 = c(
    "Most points", "in a game", "55", "43", "41", "Most varsity",
    "games played", "111", "109",
    "104"
  ),
  v3 = c(
    "Season", "(year ending)", "2001", "2000", "2010", "Season",
    "(year ending)", "2005",
    "2004", "2002"
  )
)
```

`unbreak_rows()` merges these rows if we can match them with a common pattern.

```{r}
# Match with regex on variable v2
unbreak_rows(bball, regex = "^Most", ogcol = v2)
```


**`mash_colnames()`**  

When column names are broken up across the top _n_ rows of a data frame or tibble, `mash_colnames()` makes many header rows into column names. Existing names can be kept or ignored.  

```{r}
# Data with broken headers
babies <-
  data.frame(
    stringsAsFactors = FALSE,
    Baby = c(NA, NA, "Angie", "Yean", "Pierre"),
    Age = c("in", "months", "11", "9", "7"),
    Weight = c("kg", NA, "2", "3", "4"),
    Ward = c(NA, NA, "A", "B", "C")
  )

babies
```

```{r}
# Mash, including the object names
mash_colnames(babies, n_name_rows = 2, keep_names = TRUE)
```

For inputs with ragged column names (NA values in the first row), the first row can be filled row-wise before mashing.

```{r}
# Data with ragged headers
survey <-
  data.frame(
    stringsAsFactors = FALSE,
    X1 = c("Participant", NA, "12", "34", "45", "123"),
    X2 = c(
      "How did you hear about us?",
      "TV", "TRUE", "FALSE", "FALSE", "FALSE"
    ),
    X3 = c(NA, "Social Media", "FALSE", "TRUE", "FALSE", "FALSE"),
    X4 = c(NA, "Radio", "FALSE", "TRUE", "FALSE", "TRUE"),
    X5 = c(NA, "Flyer", "FALSE", "FALSE", "FALSE", "FALSE"),
    X6 = c("Age", NA, "31", "23", "19", "24")
  )
survey
```


``` {r}
# Ignoring names and using sliding headers
mash_colnames(survey,2,keep_names = FALSE,sliding_headers = TRUE, sep = "_")
```


**`annotate_mf()` and `annotate_mf_all()`**

Sometimes embedded subheaders can't be matched by content or context, but they share the same formatting in a spreadsheet file. 

`annotate_mf()` flattens four common approaches to confer meaningful formatting to cells and adds this as a character string to the target variable. 

``` r
example_spreadsheet <- system.file("extdata/dog_test.xlsx", package = "unheadr")
annotate_mf(example_spreadsheet,orig = Task, new=Task_annotated)
```

`annotate_mf_all()` applies the same approach to all values in the dataset.
  
``` r
example_spreadsheet_all <- system.file("extdata/boutiques.xlsx", package = "unheadr")
annotate_mf(example_spreadsheet_all)
```

Lastly, `regex_valign()` can adjust the whitespace (padding) within a character vector with one element per line, for easier parsing with `readr`.

```{r}
guests <- 
  unlist(strsplit(c("6     COAHUILA        20/03/2020
712        COAHUILA             20/03/2020"),"\n"))
guests
regex_valign(guests, "\\b(?=[A-Z])")
```

The inconsistent whitespace between the elements in each line can be adjusted after matching a position of interest through regular expressions.

Owner

  • Name: Luis Verde Arregoitia
  • Login: luisDVA
  • Kind: user

mammalogist

GitHub Events

Total
  • Issues event: 1
  • Watch event: 3
Last Year
  • Issues event: 1
  • Watch event: 3

Committers

Last synced: over 3 years ago

All Time
  • Total Commits: 182
  • Total Committers: 2
  • Avg Commits per committer: 91.0
  • Development Distribution Score (DDS): 0.423
Top Committers
Name Email Commits
Luis Verde Arregoitia l****d@c****x 105
Luis Verde Arregoitia l****s@l****x 77
Committer Domains (Top 20 + Academic)

Issues and Pull Requests

Last synced: 11 months ago

All Time
  • Total issues: 5
  • Total pull requests: 0
  • Average time to close issues: 2 months
  • Average time to close pull requests: N/A
  • Total issue authors: 4
  • Total pull request authors: 0
  • Average comments per issue: 2.2
  • Average comments per pull request: 0
  • Merged pull requests: 0
  • Bot issues: 0
  • Bot pull requests: 0
Past Year
  • Issues: 1
  • Pull requests: 0
  • Average time to close issues: N/A
  • Average time to close pull requests: N/A
  • Issue authors: 1
  • Pull request authors: 0
  • Average comments per issue: 0.0
  • Average comments per pull request: 0
  • Merged pull requests: 0
  • Bot issues: 0
  • Bot pull requests: 0
Top Authors
Issue Authors
  • luisDVA (2)
  • jebyrnes (1)
  • sfd99 (1)
  • JauntyJJS (1)
Pull Request Authors
Top Labels
Issue Labels
Pull Request Labels

Packages

  • Total packages: 1
  • Total downloads:
    • cran 279 last-month
  • Total dependent packages: 0
  • Total dependent repositories: 3
  • Total versions: 7
  • Total maintainers: 1
cran.r-project.org: unheadr

Handle Data with Messy Header Rows and Broken Values

  • Versions: 7
  • Dependent Packages: 0
  • Dependent Repositories: 3
  • Downloads: 279 Last month
Rankings
Stargazers count: 6.1%
Dependent repos count: 16.5%
Forks count: 17.1%
Average: 22.1%
Dependent packages count: 28.8%
Downloads: 42.2%
Maintainers (1)
Last synced: 11 months ago

Dependencies

DESCRIPTION cran
  • R >= 3.1.0 depends
  • dplyr >= 0.8.4 imports
  • forcats * imports
  • magrittr * imports
  • readxl * imports
  • rlang >= 0.2.1 imports
  • stringr * imports
  • tibble * imports
  • tidyr * imports
  • tidyxl * imports
  • covr * suggests
  • knitr * suggests
  • rmarkdown * suggests
  • testthat >= 2.1.0 suggests
.github/workflows/rhub.yaml actions
  • r-hub/actions/checkout v1 composite
  • r-hub/actions/platform-info v1 composite
  • r-hub/actions/run-check v1 composite
  • r-hub/actions/setup v1 composite
  • r-hub/actions/setup-deps v1 composite
  • r-hub/actions/setup-r v1 composite