### Functions
Being designed for statistics and data analysis, `R` has powerful built-in functions for data manipulation. However, you can dramatically extend `R`'s functionality by writing your own functions.
`R` functions are objects just like the vectors and data frames we've worked with, so we create them using an assignment.
```{r}
times_2 <- function(x) x * 2
times_2(6)
times_2(1:5)
```
For longer functions, it's necessary to use curly braces `{}`. We can also input multiple objects into a function, and return more complex objects, such as a vector or list.
```{r}
two_numbers <- function(x, y) {
my_sum <- x + y
my_product <- x * y
my_ratio <- x / y
return(c(my_sum, my_product, my_ratio))
}
two_numbers(4, 11.93)
```
### Loops
We use loops whenever we need to run the same function (or chunk of code) across different units. For example, we may use a loop whenever we have multiple Twitter accounts and we want to run sentiment analysis for tweets posted by each of them.
"For" loops are probably the most common type of loop and are easily implemented in R
```{r}
for (i in 1:10) {
print(i)
}
```
Note the structure:
```{r, eval = FALSE}
for (i in VECTOR) {
# do something with i
}
```
In each iteration, i takes a different value of the VECTOR; "i" can be anything!
```{r}
for (number in 1:10) {
print(number)
}
```
The nice feature of loops is that it can use values from the previous iteration. For instance, we can get the first 40 terms in the Fibonacci sequence using a for loop.
```{r}
fib <- c(0, 1, rep(NA, 38)) # initialize fib sequence
for (i in 3:40) {
fib[i] <- fib[i - 1] + fib[i - 2]
}
```
Note that here we created an empty vector to store the output of each iteration. A simpler example:
```{r}
values <- rep(NA, 10)
for (i in 1:10) {
values[i] <- i
}
```
A structure that we will use often in this workshop is a loop that stores some data in different elements within a list. This will be very useful when the output from each iteration is a data frame. For example:
```{r}
# create empty list
grades <- list()
# loop over 5 students
for (i in 1:5) {
# create data frame with grade/info for this student
student <- data.frame(id = i,
initial = sample(LETTERS, 1),
grade = runif(n = 1, min = 0, max = 100),
stringsAsFactors = FALSE)
grades[[i]] <- student
}
# now we have a list...
class(grades)
# but we can turn it into a data frame
grades <- do.call(rbind, grades)
grades
```
### If statements
Depending on whether a condition is true or false, we might want to execute different chunks of code.
```{r}
compare_xy <- function(x, y) {
if (x < y) {
print("y is greater than x")
} else if (x > y) {
print("x is greater than y")
} else {
print("x and y are equal")
}
}
compare_xy(3, 4)
compare_xy(4, 3)
compare_xy(1, 1)
```
A slightly different type of if statement is the `ifelse` function:
```{r}
numbers <- c(-2, -1, 0, 1, 2)
# converting them to absolute numbers
abs_numbers <- ifelse(numbers > 0, numbers, -numbers)
abs_numbers
```