Workshop overview:

-   For loops
-   Conditional (if/else) statements
-   Additional practice problems

# 0. GETTING STARTED

```{r}
library(openintro) #includes practice dataset
library(gapminder) #includes practice dataset 
library(tidyverse) #data manipulation

```

We will be using three datasets in this workshop:

(1) 'countries' from the gapminder package - Macroeconomic (e.g. GDP per capita) and demographic (e.g. population) data for every country in the world, by year

```{r}
countries <- gapminder # create a data frame
head(countries) #see the first six rows of the dataframe
```

(2) 'storms' from the dplyr package - Location and weather data for hurricanes in the US

```{r}
head(storms)
```

(3) 'midterms' from the openintro package - midterm election results by year, party, and unemployment rate

```{r}
midterms <- midterms_house
head(midterms)
```

# 1. FOR LOOPS

For loop's basic structure

for (i in vector/list/matrix/dataframe){ some operation with i }

one step in a loop = one 'iteration'

numeric vector example:

```{r}
#a simple loop: 

numbers <- 1:10 #creating a vector of numbers 1 through 10 

for (i in numbers){
  print(i)
}


for (i in numbers){
  print(i)
  Sys.sleep(0.5) #this staggers each output by 0.5 seconds
}

```
In this illustrative example, you need to include print, or the loop will run without producing output. 

Why include print? It is helpful to see how many iterations of the loop have been completed to see if
1. The loop is still going and not stuck. 
2. To calculate the amount of time left for the code to finish running. 


```{r}
matrix <- matrix(nrow = 3, ncol = 5, c(1:15))
matrix

for (i in matrix){
  print(i)
}
```

dataframe example:

```{r}
###looping through the unique political parties in our midterms dataset
for (i in unique(midterms$party)){
  print(i)
}

#note i is an object and never in quotes. i is commonly-used 
#but arbitrary. You can make it more meaningful to you if thats easier, e.g.: 

for (Parties in unique(midterms$party)){
  print(Parties)
}
```

Applying an operation by looping through the parties in the midterms dataset

```{r}
###finding the maximum value of house_change for each party
#if we wanted to do this for ONE party, e.g. Republican 

max(midterms$house_change[midterms$party == 'Republican'])

#uses square brackets to subset, will be using this throughout the workshop
```

individual components we need to build our for loop:

1.  unique(midterms\$party)
2.  max(midterms$house_change[midterms$party == Party])
3.  for loop struture:

for (i in vector){ operation }

```{r}
#building this into a for loop, for all parties
for (i in unique(midterms$party)){
  x <- max(midterms$house_change[midterms$party == i])
  print(x)
}

#can save as an object or embed max within print , i.e 
#print(max(countries$gdpPercap[countries$country == i]))

#besides, as it is not clear which value correspond to which party
#you can print i as well
for (i in unique(midterms$party)){
  x <- max(midterms$house_change[midterms$party == i])
  print(c(i, x))
}
```

## 1.1 PRACTICE TOGETHER

Another example, with a different dataset: finding the average latitude for each storm in the 'storms' dataset

individual components we need to build our for loop:

1.  unique(storms\$name)
2.  mean(storms$lat[storms$name == Storm name])
3.  for loop struture:

for (i in vector){ operation }

```{r}
#storms dataset, from dplyr
head(storms)

#finding the average latitude for each storm in the dataset 
for (i in unique(storms$name)){
  print(i)
  x <- mean(storms$lat[storms$name == i])
  print(x)
}

```

### 1.1.1PRACTICE:

Using the 'countries' dataset, use a for loop to find the maximum value of GDP per capita (gdpPercap) for each country

```{r}
#answer: 

```

Saving the output of your for loop:

lets create a new dataset called 'country_sum', of summary variables by country, with country as one column and max gdp per capita as another

```{r}
#creating empty vectors for the values we want to store
country <- 0
maxgdp <- 0

#to store values in a vector, we need to create a count, to add values to a vector as we move through each iteration of the loop 
index <- 1

#vector[x] points to position x in the vector

for (i in unique(countries$country)){
  maxgdp[index] <- max(countries$gdpPercap[countries$country == i])
    #create vector of max gdpPercap values by country 
  country[index] <- i #create vectors of countries
  print(index) #print index at each iteration (not required)
  index <- index + 1 #add one to the index to avoid replacement
}

#look at our new vectors
head(maxgdp)
head(country)

#combine vectors into a dataframe
country_sum <- data.frame(country, maxgdp)
head(country_sum)

#there are other ways of doing this, by creating a dataframe and using that directly in the for-loop, but I think this format is more beginner-friendly 
```

### 1.1.2 PRACTICE:

modify the code below to create a new dataframe with two columns: Party, and max midterms house change (x in the example code). Name your columns however you'd like.

```{r}

#original code:
for (i in unique(midterms$party)){
  x <- max(midterms$house_change[midterms$party == i])
  print(x)
}

#answer: 

```

# 2. IF/ELSE STATEMENTS

Basic structure of an if statement:

if (logical statement){ operation true}

can be expanded to an if/else statement:

if (logical statement){ operation if true} else{ operation if false}

examples of logical statements:

x > 5 
x == 4 
x == "cat" 
x != 0 
x %in% c("cat", "dog", "mouse")

Note: an empty else statement "else{}" means "do nothing" 

Simple example:

```{r}

x = 6 #set x to 6 

if (x > 5){
  print("x is greater than 5")
}

x = 4 #set x to 4 

#add an else statement 
if (x > 5){
  print("x is greater than 5")
} else {
  print("x is less than 5")
}
```
Multiple if statements can be joined together 

```{r}
## try different values of a
a=3

if (a > 5) {
  print("a is greater than 5")
} else if (a == 5) {  ## Note the space between "else" and "if" here. 
  print("a = 5")
} else {
  print("a is smaller than 5")
}

```

if/else statement become very useful when embedded within a for loop:

```{r}

#e.g., create a binary variable for Republican (1) and Democrat (0)

midterms$binary <- NA

for (i in 1:nrow(midterms)) {
  if (midterms$party[i] == 'Republican') {
    midterms$binary[i] = 1
  } else {
    midterms$binary[i] = 0
  }
}

head(midterms)
```

Note: for loops will stop running if they produce an error. To keep a for loop going, add tryCatch inside the loop. This is advanced, so we don't go into it, but it may be useful for you as your loops become more advanced https://cran.r-project.org/web/packages/tryCatchLog/vignettes/tryCatchLog-intro.html 

## 2.1 PRACTICE

```{r}
#e.g., create a binary variable/column in the countries dataset called eurasia_bin, with values of 'Eurasia' and 'Elsewhere', based on this list (it is not totally accurate, but suitable for the purpose of practice): 

eurasia <- c("Europe", "Asia")

#(hint: you need to use %in%)

#answer:
```

# 3. BONUS QUESTION

Loop through the storms dataset and calculate mean latitude for each storm. Store this in a new dataframe with storm name.

Then, create a new grouping variable for latitude, with three levels: 'North' (>30), 'Central' (>=20, <=30), 'South' (<20).

```{r}
#answer: 

```


# 4. Tips for how to build loops

Build parts of the loop individually.
- Check that the loop cycles correctly, this is why we use print!
- If saving output, make sure that each iteration of the loop have a unique identifier to link the output with each data subset. For example, if your ANOVA is for different metrics, you would want to know what data each ANOVA output links to. 
- Does the code inside the loop work? For example, if you have code for an ANOVA inside the loop, can you use that code to run an ANOVA outside of the loop.
- To troubleshoot the loop, you can run the lines inside the {} individually. Lets say the structure of the loop for the example in section 1.1.2 PRACTICE (line 207), we can set i = "Democrat" and run the lines 208 and 209 one by one. This technique is helpful to find where exactly in the loop the issues arise. 





