# Tidy data {#tidyr}

## Learning Objectives

It this chapter we'll get into detail about what _tidy_ means. Tidy data is defined as:

- One observation per row,
- One variable per column, and
- One observational unit per data frame.

## Example

Consider the following data frames:

```{r PGorg, echo = FALSE}
PlantGrowth %>%
  head() %>% 
  knitr::kable(caption = "The long, tidy data frame.")
```


```{r PGwide, echo = FALSE}

PlantGrowth %>% 
  mutate(id = rep(1:10,3)) %>% 
  pivot_wider(names_from = group, values_from = weight) %>% 
  select(-id) %>% 
  knitr::kable(caption = "A wide, messy data frame.")

```


Data should be arranged in a format that makes downstream analysis easier, instead of forcing functions to work on poorly formatted data. We can see this with the `PlantGrowth` data set (table \@ref(tab:PGorg)). The long, tidy format allows us to carry out easy commands like making plots, defining linear models and even calculating group-wise descriptive statistics. A more typical way to store this data would be like table \@ref(tab:PGwide). But this would make it much more difficult to work with. Can you imagine how to draw the same box plot if your data was in this format? It's possible, but not nice!

Some statisticians, bioinformaticians and data scientists estimate that about three-quarters of their time is spent on "data munging", that is, getting data cleaned-up and tidy so that they can actually analyse it.

```{exercise}
Create the wide format of the PlantGrowth data set using the commands given below
```

This will switch from long to wide format:

```{r echo = TRUE}
library(tidyverse)

PG_wide <- PlantGrowth %>% 
  mutate(id = rep(1:10,3)) %>% 
  pivot_wider(names_from = group, values_from = weight) %>% 
  select(-id)

glimpse(PG_wide)
```

Now that we have some _messy_ data, let's try to complete the following exercises using `PG_wide`:

```{exercise}
Draw a jittered dot plot of the weight described by each treatment type. We did this earlier in the course. The result should look like below. How would you go about doing this with `PG_wide`?
```

```{r tidy = F, echo = FALSE, eval = TRUE}
ggplot(PlantGrowth, aes(group, weight)) +
  geom_jitter(width = 0.2, shape = 16, alpha = 0.75) +
  theme_classic() +
  theme(axis.line.x = element_blank(),
        axis.title.x = element_blank())
```

```{exercise}
Calculate the group-wise mean and standard deviation for all 10 observations in each treatment group using `PG_wide` instead of `PlantGrowth`. What functions would you use for this?
```

```{r tidy = F, echo = FALSE, eval = TRUE}
PlantGrowth %>%
  group_by(group) %>%
  summarise(avg = mean(weight),
            stdev = sd(weight)) %>% 
  knitr::kable()
```

```{exercise}
Perform a z-score transformation within each treatment in the `PG_wide` data frame type using the `scale()` function. Your results should look like below.
```

```{r tidy = F, echo = FALSE, eval = TRUE}
PlantGrowth %>%
  group_by(group) %>%
  mutate(Z_score = scale(weight)) %>% 
  select(-weight) %>% 
  mutate(ID = 1:10) %>% 
  pivot_wider(names_from = "group", values_from = "Z_score") %>% 
  select(-ID) %>% 
  knitr::kable()
```

```{exercise}
Calculate a 1-way ANOVA of each plant's weight described by it's treatment using the `PG_wide` data frame. Do you think this is easy in this case? The results we received previously look like:
```

```{r tidy = FALSE, echo = FALSE}
Plant.lm <- lm(weight ~ group, data=PlantGrowth)
Plant.anova <- anova(Plant.lm)
```

```{r comment="", prompt = TRUE, eval = TRUE, echo = FALSE}
Fvalue <- round(Plant.anova$`F value`[1],2)
p <- round(Plant.anova$`Pr(>F)`[1],3)
DF <- Plant.anova$Df
knitr::kable(Plant.anova, caption = 'The results of a one-way ANOVA on the plant growth data set.')
```

## The pipe operator - %>% {#dplyrpipe}

We've seen all the great bits of the tidyverse in action already. Here, we'll review some fundamentals. First, the _punctuation_: `%>%`, aka _the forward-pipe operator_. The forward-pipe operator is a shorthand for calling functions, such that:

`function(x) == x %>% function()` (When speaking the commands say _and then_.)

This is not specific to `dplyr` functions. It can be used with any `R` functions:

```{r tidy = FALSE}
aa <- 1:10

# The usual way
mean(aa)

# or with the pipe operator
aa %>% 
  mean()

```

The advantage here is that we can string together a long series of functions that would be very difficult to read in the regular `R` nomenclature, which we'll see in a minute as our functions get more complex.


## Tidy Data with the `tidyr` Package

To understand tidy data, we'll consider a generic example with a data frame, `PlayData` (see figure \@ref(tab:playdata)).

```{r message=FALSE}
# Create a new play dataset to work on:
PlayData <- read_tsv("data/PlayData.txt")

```

To work with our data in R, we want all variables in their own columns. To achieve this, we will _gather_ our data into a long, tidy form. To understand what this means, we need to realize that there are essentially two different types of variables:

**ID Variables** are all the possible grouping variables which were measured. These include both independent and dependent categorical variables. ID variables are used to group, i.e. _identify_, our measurement variables. Our ID variables are _type_ and _time_. 

**Measurement Variables** are _what_ was measured, here that's the _height_ and _width_.

## Pivot to longer

Until recently the go-to function to get tidy data was `tidyr::gather()`. However, this has been supplanted by the much more flexible `tidyr::pivot_longer()`. This function takes two arguments:

1. The wide data frame to make long (i.e. tidy).
1. The ID (specified with `-`) or MEASURE variables (simply named as such).

I usually also specify the:

1. The name of the output column for the KEY, using the `names_to` argument.
1. The name of the output column for the VALUE using the `values_to` argument.

```{r}
PlayData %>% 
  pivot_longer(-c(type, time), names_to = "key", values_to = "value") -> PlayData_t
```

```{r echo = FALSE}
PlayData_t %>% 
  knitr::kable()
```

This will convert the remaining column headers into the 3rd ID variable, `key`, and produce the _tidy_ data frame, shown above. HINT: If you want to select all columns in a data frame, i.e. all columns are MEASURE columns, you can use `everything()`.

```{exercise}
Starting with `PG_wide`, use the `pivot_longer()` to produce `PG_tidy
```

```{r}
PG_wide %>% 
  pivot_longer(cols = everything(), names_to = "weight", values_to = "group") -> PG_long
```

<!-- <div class="column-left"> -->

<!-- ```{r echo = FALSE} -->
<!-- PG_long %>%  -->
<!--   # head() %>%  -->
<!--   knitr::kable(caption = "PG_long, a long, tidy data frame.") -->
<!-- ``` -->

<!-- </div> -->

Now that you have long _tidy_ data. Revisit the exercises from above for `PG_wide`. They are much easier using a tidy data version of the data frame!

```{exercise}
Using `PlantGrowth`, draw a jittered dot plot of the weight described by each treatment type.
```

```{exercise}
Using `PlantGrowth`, calculate the group-wise mean and standard deviation for all 10 observations in each treatment group.
```

```{exercise}
Using `PlantGrowth`, perform a z-score transformation within each treatment type.
```

```{exercise}
Using `PlantGrowth`, calculate a 1-way ANOVA of each plant's weight described by it's treatment.
```

Now that you have an idea about pivoting, let's look at the other direction

## Pivot to Wider

We can re-arrange our data and make it _wider_. e.g. to return to our original data frame, we can use:

```{r eval = FALSE}
PlayData_t %>%
  pivot_wider(names_from = "key", values_from = "value")
```

```{r echo = FALSE}
PlayData_t %>%
  pivot_wider(names_from = "key", values_from = "value") %>% 
  knitr::kable()
```

We saw this in the code above to get the `PG_wide`.

Likewise, we can _pivot_wider_ so that each category of _time_ is now a separate variable.

```{r eval = FALSE}
PlayData_t %>%
  pivot_wider(names_from = "time", values_from = "value")
```

```{r echo = FALSE}
PlayData_t %>%
  pivot_wider(names_from = "time", values_from = "value") %>% 
  knitr::kable()
```

Or so that _type_ is defined in separate variables

```{r eval = FALSE}
PlayData_t %>%
  pivot_wider(names_from = "type", values_from = "value")
```

```{r echo = FALSE}
PlayData_t %>%
  pivot_wider(names_from = "type", values_from = "value") %>% 
  knitr::kable()
```

The three transformation function scenarios are straight-forward, if our starting point is tidy data! But the power of tidy data becomes apparent when grouping our data according to a factor variable. This allows us to apply not only transformation functions, but aggregation functions as well. For this we turn to the `dplyr` package.

