---
title: 'Why "R for Data Science"?'
author: "Rian DeFaccio, for BH Analytics LLC"
date: "`r Sys.Date()`"
format: pdf
---

## Overview

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

In this section we will get a brief history of R, learn about the basic data types, and get familiar with a couple of data structures we will use throughout the rest of the course.

## A BRIEF History of R

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

The R programming language has been around for a while, and is considered somewhat old compared to other languages used for data science. This has many perks however!

![<https://www.mdpi.com/2075-1729/12/5/648>](images/history_of_r-01.png)

## Data Types

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

There are several main types of atomic R objects that we will use:

-   numbers (integers and floating point values)
-   character strings
-   Boolean
-   factors (more on these later...)
-   dates and times (more on these later...)

First we will save and manipulate some numbers.

```{r}
num1 <- 5
num2 <- 10
num1 + num2
num1 * num2
```

We can learn a little bit about our variables by using the `str()` function.

```{r}
str(num1)
```

Next are a couple of strings which we create by wrapping our characters in quotation marks.

```{r}
str1 <- "Hello"
str2 <- "World!"

# the paste() function combines strings
paste(str1, str2)

# check the class
str(str1)
```

We can also save Boolean (TRUE/FALSE) values. We generally will use these with logical tests.

```{r}
bool1 <- TRUE
bool2 <- FALSE
 
## some logical tests
# & is the 'and' operator
bool1 & bool2
```

```{r}
## | is the 'or' operator
bool1 | bool2
```

```{r}
# check the class
str(bool1)
```

```{r}
(1 == 1) & (2 != 1)
```

There is one more operator that is quite useful, which is the `%in%` operator. This checks whether each element of the first vector is in the set of unique values in a second vector.

```{r}
1:10 %in% 1:5
```

Notice how the `%in%` operator behaves differently than the `==`.

```{r}
# this one checks whether each element is in the set of a and b
c('a', 'b', 'b', 'c') %in% c('a', 'b')

# this one is just "recycling" the vector of a and b
c('a', 'b', 'b', 'c') == c('a', 'b')
```

And finally, we can often convert certain data types into other data types as in the following examples:

```{r}
as.character(999)
```

```{r}
as.integer('999')
```

## Introduction to Vectors

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

In most statistics and analysis contexts we need to do more than work with single values, we need to work with collections of values!

### Creating Vectors

The basic R collection is called a vector.

-   We use the `c()` function which stands for "combine" or "concatenate".
-   We can collect objects of any data type into a vector.
-   A colon can be used as a shorthand to create a sequence of numbers.

Lets collect information about 4 subjects in a hypothetical experiment into vectors.

```{r, echo=TRUE}
## data input 
height <- 60:63 
weight <- c(135, 155, 145, 155)   
location  <- c("Urban", "Urban", "Rural", "Rural") 
```

There is also one twist on vectors we'd like you to be aware of: named vectors.

```{r}
height_named <- c("Bob"=60, "Tom"=61, "Sue"=62, "Joe"=63)
height_named
```

### Vectorized Operations

We will now use our vectors to find the BMI for each subject.

```{r, echo=TRUE}
# bmi = weight (lb) per height (inches) squared 
constant <- 703 
bmi <- (weight  * constant )/ height^2 
bmi
```

Note the differences in the length of the vectors `weight` and `height` compared to `constant`.

```{r, echo=TRUE}
length(bmi) 
length(constant) 
```

R *recycled* the constant term in the vector operations!

We can also check on information about our vectors using `str()`.

```{r}
str(height)
```

### Indexing and Sub-setting Vectors

We can subset a portion of our vector by using square brackets:

-   You can specify a single index or a range of indexes.
-   R begins indexing at 1, this is different than many other programming langues like Python.
-   Base R indexing is end-inclusive.

What was the height of the first person?

```{r}
height[1]
```

To subset several values, put a vector of desired indices inside the square brackets.

What are the weights of the first three subjects?

```{r}
weight[c(1,2,3)]
weight[1:3]
```

Indexing by logical vectors is possible too, where only TRUE values are returned.

```{r, echo=TRUE}
Rural <- location == "Rural" 
Rural 
```

```{r}
height[Rural] 
```

A common syntax is to combine the previous steps into one line:

```{r}
height[location == "Rural"] 
```

### 🛠️ Coding Practice: Subsetting Vectors

What is/are the BMI(s) of rural subjects over 61" tall?

```{r}
# ANSWER HERE

```

What is/are the BMI(s) of subjects that are urban or under 61"?

```{r}
# ANSWER HERE

```

**END OF EXERCISE**

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

If you have named vectors, you can also subset by the names.

```{r}
height_named['Bob']
height_named[c('Bob','Sue')]
```

### Summarizing Functions

There are many built-in R functions that will summarize vectors.

Most work on numeric vectors:

```{r, echo=TRUE}
mean(weight)
```

```{r}
median(height)
```

```{r}
quantile(bmi)
```

If you try to pass a vector of strings to a function that expects numbers, you will get an empty output (no error though!).

```{r, echo=TRUE}
mean(location)
```

We can create simple plots to summarize our data like in the following example.

```{r, echo=TRUE}
## simple scatterplot
plot(height, weight)
```

## Introduction to Data Frames

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

### Creating Data Frames

The primary data analysis object in R is the data frame

-   A data frame is a list of vectors (columns).
-   You may think of this like an Excel spreadsheet for now.
-   We can extract the columns of a data frame using the dollar sign `$`, what we get back is a vector.
-   The columns are now locked together into one object.

Data Frame:

| Height | Weight | Location |
|--------|--------|----------|
| 60     | 135    | Urban    |
| 62     | 155    | Urban    |
| 61     | 145    | Rural    |
| 65     | 155    | Rural    |

We use the `data.frame()` function to build a data frame.

```{r, echo=TRUE}
## build a data frame from individual vectors
my_df <- data.frame(weight, height)

## print my_df
my_df
```

Getting summaries for a column of data is the same as with vectors, since a single column of a data frame is basically a vector.

```{r}
## Calculate the mean height from the data frame
mean(my_df$height)
```

### 🛠️ Coding Practice: Summarizing a Data Frame

Use three different summary statistics to understand the distribution of weight of participants in your new data frame.

```{r, echo=TRUE}
# ANSWER HERE

```

**END OF EXERCISE**

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

### Adding Data

We can also add a new variable by simple assignment using the `$` operator.

Lets add `location` to our data frame.

```{r, echo=TRUE}
my_df$rurality <- location
```

### 🛠️ Coding Practice: Make a New Column

Can you figure out how to create a BMI column in the Data Frame? Use only the data from inside the Data Frame to do this (ie. try not to use the old vectors).

```{r}
# ANSWER HERE

```

This time make a new column called `overweight` which equals `TRUE` if the BMI was greater than 25, and `FALSE` otherwise.

```{r}
# ANSWER HERE

```

**END OF EXERCISE**

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

### Indexing and Sub-setting

Indexing and sub-setting data frames also uses square brackets in a way that is similar to vectors:

-   However, use a comma to separate row and column conditions.
-   Subset rows by index or Boolean values.
-   Subset columns by column names.
-   Leave an empty space in the row or column spot to keep all instances.

```{r}
## show all columns for anyone who weighs less than or equal to 145 lbs
my_df[my_df$weight <= 145, ]
```

```{r}
## show just the height column for anyone who weighs more than 145 lbs
my_df[my_df$weight > 145, "height"]
```

### ✍️ Your Turn! Interpret Data Frame Output

What type of object was returned when you used the square brackets sub setting and requested just a single column?

**Answer here:**

There are also convenience functions for viewing the first and last rows of a data frame.

```{r}
head(my_df, 2)
tail(my_df, 3)
```

We can also use the square bracket indexing method to re-assign values in a data frame. See below for the syntax.

```{r}
## original df
my_df
```

```{r}
## change first row second column
my_df[1, 2] <- 70
my_df
```

```{r}
## change a couple of values in the first column
my_df[c(1, 3), 1] <- c(195, 205)
my_df
```

Finally, we can also convert (aka *"coerce"*) a column of a data frame into another data type.

```{r}
my_df$height <- as.character(my_df$height)
my_df

# let's put that back as a numeric now...
my_df$height <- as.numeric(my_df$height)
```

### More Data Frame Functions

There are a couple of more very useful functions for working with data frames. Can you guess what they do?

```{r}
nrow(my_df)
ncol(my_df)
```

## Conclusion

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

That wraps up our discussion of the atomic data types two of the most common R data structures. Now that you understand how vectors and Data Frames work, we can start to do many common data analytic tasks!

## Answers to Questions

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

### 🛠️ Coding Practice: Subsetting Vectors

```{r}
bmi[location == "Rural" & height > 61]
```

```{r}
bmi[location == "Urban" | height < 61]
```

### 🛠️ Coding Practice: Summarizing a Data Frame

```{r}
min(my_df$weight) 
max(my_df$weight) 
mean(my_df$weight) 
median(my_df$weight) 
sd(my_df$weight) 
summary(my_df$weight) 
fivenum(my_df$weight) 
```

### 🛠️ Coding Practice: Make a New Column

```{r}
my_df
my_df$bmi <- (my_df$weight * constant) / my_df$height^2 
```

```{r}
my_df$overweight <- my_df$bmi > 25 
```

### ✍️ Your Turn! Interpret Data Frame Output

What type of object was returned when you used the square brackets sub setting and requested just a single column? **The output was a vector.**
