---
title: "Data Classes"
output:
  ioslides_presentation:
    css: ../styles.css
    widescreen: yes
---

```{r, echo = FALSE, message=FALSE}
# library(dplyr)
suppressPackageStartupMessages(library(dplyr))
library(readr)
library(forcats)
```


# One dimensional types ("vectors")

## Data Types
    * Character: strings or individual characters, quoted
    * Numeric: any real number(s)
    * Integer: any integer(s)/whole numbers
    * Factor: categorical/qualitative variables
    * Logical: variables composed of TRUE or FALSE
    * Date/POSIXct: represents calendar dates and times

## Character and numeric

We have already covered `character` and `numeric` types.

```{r numChar}
class(c("tree", "cloud", "stars_&_sky"))
class(c(1, 4, 7))
```

## Character and numeric

This can also be a bit tricky.

```{r numChar2}
class(c(1, 2, "tree"))
class(c("1", "4", "7"))
```

## Numeric Subclasses

There are two major numeric subclasses

1) Integer
2) Double


## Integer

`Integer` is a special subset of `numeric` that contains only whole numbers

A sequence of numbers is an example of the integer type. You can use the `seq()` function to create a sequence of integers.

```{r seq}
x = c(1, 2, 3, 4, 5)
x
x = seq(1:5)
x
class(x)
typeof(x)
```

## Double

`Double` is a special subset of `numeric` that contains fractional values.

`Double` stands for [double-precision](https://en.wikipedia.org/wiki/Double-precision_floating-point_format)

```{r double}
y = c(1.1, 2.0, 3.2, 4.5, 5.6)
y
class(y)
typeof(y)
```

## Checking double vs integar

A `tibble` will show the difference (as does `glimpse()`)

```{r}
tibble(xvar = x, yvar = y)

```

## Logical

`logical` is a type that only has two possible elements: `TRUE` and `FALSE`

```{r logical1}
x = c(TRUE, FALSE, TRUE, TRUE, FALSE)
class(x)
```

Note that `logical` elements are NOT in quotes. 
```{r logical2}
z = c("TRUE", "FALSE", "TRUE", "FALSE")
class(z)
```


## General Class Information

There are two useful functions associated with practically all R classes: 

- `is.CLASS_NAME(x)` to **logically check** whether or not `x` is of certain  class 
- `as.CLASS_NAME(x)` to **coerce between classes** `x` from current `x` class into a certain class 



## General Class Information: Checking


```{r logical_coercion}
is.character(c(1, 4, 7))
is.numeric(c(1, 4, 7))
is.character(c("tree", "cloud"))
is.numeric(c("tree", "cloud"))
```



## General Class Information: coercing

In some cases the coercing is seamless 

```{r logical_coercion3s}
as.character(c(1, 4, 7))
as.numeric(c("1", "4", "7"))
as.logical(c("TRUE", "FALSE", "FALSE"))
as.integer(c(1.2, 3.7))
as.double(c(1, 2, 3))
```

## General Class Information: coercing

In some cases the coercing is not possible; if executed, will return `NA` (an R constant representing "**N**ot **A**vailable" i.e. missing value)

```{r logical_coercions4}
as.numeric(c("1", "4", "7a"))
as.logical(c("TRUE", "FALSE", "UNKNOWN"))
as.Date(c("2021-06-15", "2021-06-32"))
```


## Factors

A `factor` is a special `character` vector where the elements have pre-defined groups or 'levels'. You can think of these as qualitative or categorical variables. Use the `factor()` function to create factors.

```{r factor1}
x <- c("small", "mediam", "large", "medium", "large")
class(x)

x_fact = factor(x)  # factor() is a function
class(x_fact)
x_fact
```

Note that levels are, by default, in **alphanumerical** order!

## Factors

You can learn what are the unique levels of a `factor` vector

```{r factor1b}
levels(x_fact)
```

More on how to change the levels ordering in a lecture coming up! 


## Factors

Factors can be converted to `numeric` or `character` very easily

```{r factor3}
x_fact

as.character(x_fact)
as.numeric(x_fact)
```


## Useful functions to create vectors 

For character: `rep()` can create very long vectors. 

The `each` argument specifies how many of each item you want repeated.
The `times` argument specifies how many times you want the vector repeated.

```{r}
rep(c("black", "white"), each = 3)
rep(c("black", "white"), times = 3)
rep(c("black", "white"), each = 2, times = 2)
```

## Useful functions to create vectors 

For numeric: `seq()` can be very useful.
The `from` argument says what number to start on.
The `to` argument says what number to not go above.
The `by` argument says how much to increment by.
The `length.out` argument says how long the vector should be overall.

```{r}
seq(from = 0, to = 1, by = 0.2)
seq(from = -5, to = 5, length.out = 10)
```

## Lab Part 1

Lab document: http://jhudatascience.org//intro_to_r/Data_Classes/lab/Data_Classes_Lab.Rmd



# Two-dimensional data classes

## Two-dimensional data classes

Two-dimensional classes are those we would often use to store data read from a file 

* a data frame (`data.frame` or `tibble` class)

* a matrix (`matrix` class)

    * also composed of rows and columns
    * unlike `data.frame` or `tibble`, the entire matrix is composed of one R class
    * for example: all entries are `numeric`, or all entries are `character`


## Matrices

```{r,}
head(iris)
class(iris)
iris_mat <-head(tibble(select(iris, -Species)))
as.matrix(iris_mat)
matrix(1:4, ncol = 2)
```


## Lists

* One other data type that is the most generic are `lists
* Can be created using `list()`
* Can hold vectors, strings, matrices, models, list of other list!

```{r makeList}
mylist <- list(c("A", "b", "c"), c(1,2,3), matrix(1:4, ncol = 2))
mylist
class(mylist)
```

## Lists

List elements can be named

```{r makeListv}
mylist_named <- list(letters = c("A", "b", "c"), 
                     numbers = c(1,2,3), 
                     one_matrix = matrix(1:4, ncol = 2))
mylist_named
```



## Dates

There are two most popular R classes used when working with dates and times: 

- `Date` class representing a calendar date
- `POSIXct` class representing a calendar date with hours, minutes, seconds

We convert data from character to `Date`/`POSIXct` to use functions to manipulate date/date and time

`lubridate` is a powerful, widely used R package from "tidyverse" family to work with `Date` / `POSIXct` class objects 

## Creating `Date` class object  

```{r, message = FALSE}
class("2021-06-15")

library(lubridate)

ymd("2021-06-15")             # lubridate package         
class(ymd("2021-06-15"))      # lubridate package    
```

Note for  function `ymd`: **y**year **m**onth **d**ay  



## Creating `Date` class object 

```{r, error = TRUE}
mdy("06/15/2021")  

mdy("06/15/21")  
```

Note for  function `mdy`: **m**onth **d**ay  **y**year


## Lab Part 2

Lab document: http://jhudatascience.org//intro_to_r/Data_Classes/lab/Data_Classes_Lab.Rmd


# Extra Slides


## Creating `POSIXct` class object  

```{r}
class("2013-01-24 19:39:07")
ymd_hms("2013-01-24 19:39:07")             # lubridate package 
class(ymd_hms("2013-01-24 19:39:07"))      # lubridate package 
```

UTC represents time zone, by default: Coordinated Universal Time

Note for  function `ymd_hms`: **y**year **m**onth **d**ay **h**our **m**inute **s**econd. 

There are functions in case your data have only date, hour and minute (`ymd_hm()`) or only  date and hour (`ymd_h()`). 

## Some useful functions from `lubridate` to manipulate `Date` objects

```{r}
x <- ymd(c("2021-06-15", "2021-07-15"))
x
day(x)   # see also: month(x) , year(x)
x + days(10)
x + months(1) + days(10)
wday(x, label = TRUE)
```

## Some useful functions from `lubridate` to manipulate `POSIXct` objects

```{r}
x <- ymd_hms("2013-01-24 19:39:07")
x
date(x)
x + hours(3)
floor_date(x, "1 hour")  # see also: ceiling_date()
```

## Differences in dates 

```{r}
x1 <- ymd(c("2021-06-15"))
x2 <- ymd(c("2021-07-15"))

difftime(x2, x1, units = "weeks")
as.numeric(difftime(x2, x1, units = "weeks"))
```

Similar can be done with time (e.g. difference in hours). 

# Data Selection

## Matrices

```{r matrix}
n = 1:9 
n
mat = matrix(n, nrow = 3)
mat
```

## Vectors: data selection

To get element(s) of a vector (one-dimensional object): 

- Type the name of the variable and open the rectangular brackets `[ ]`
- In the rectangular brackets, type index (/vector of indexes) of element (/elements) you want to pull. **In R, indexes start from 1** (not: 0)

```{r}
x <- c("a", "b", "c", "d", "e", "f", "g", "h")
x
x[2]
x[c(1, 2, 100)]
```



## Matrices: data selection

Note you cannot use `dplyr` functions (like `select`) on matrices. To subset matrix rows and/or columns, use `matrix[row_index, column_index]`.

```{r subset3}
mat
mat[1, 1] # individual entry: row 1, column 1
mat[1, 2] # individual entry: row 1, column 2
mat[1, ]  # first row
mat[, 1]  # first column

mat[c(1,2), c(2,3)]   # subset of original matrix: two rows and two columns
```


## Lists: data selection

You can reference data from list using `$` (if elements are named) or using `[[ ]]`

```{r}
mylist_named[[1]]
mylist_named[["letters"]]     # works only for a list with elements' names 
mylist_named$letters          # works only for a list with elements' names 
```

