# 5 map()

Groupmates present: __________

By the end of this assignment, you should be able to:

- Explain what an anonymous function is and why we use it.
- Use `ggplot() + stat_function()` with anonymous functions as a "graphing calculator."
- Use `map()` to repeat a task many times and combine the results into a tidy dataset.
- Run a OLS simulation and interpret what changes when the sample size changes.

Run this code to attach the tidyverse to your current session and get started.
```{r, message = F}
library(tidyverse)
```

## Anonymous Functions

An anonymous function is a function without a name. You write it when you want a quick "one-time" function.

```{r, eval = F}
# do not run

function(input) {
  # do something with input
}
```

### Example: Apply a function immediately

This creates a function `function(x) {3 * x}` and immediately calls it with `x = 9`.

```{r}
(function(x){3 * x})(9)
```

### Question 1

Write an anonymous function that divides the input by 3, and call it on the vector `c(1, 3, 9)`.

```{r}

```

## R as a Graphing Calculator

You can graph functions with ggplot by using `stat_function()` paired with an anonymous function.

```{r}
ggplot() +
  stat_function(fun = function(x) 2 * x + 1, color = "red")
```

Zoom in or out using xlim() and ylim().

```{r}
ggplot() +
  stat_function(fun = function(x) 2 * x + 1, color = "red") +
  xlim(0, 3) +
  ylim(0, 6)
```

### Question 2

Use ggplot to graph the function $y = x^2 + 4x - 1$ in blue. Set x and y limits appropriately.

```{r}

```

## map() for a Simple Task

### Why `map()`?

Sometimes you want to do the same task many times, once for each element of a list or vector. `map()` forms a mapping from the inputs to outputs, as defined by the anonymous function you use. `map()` takes two arguments:

- `.x`: a list of inputs
- `.f`: the function you want to call on each element of those inputs.

```{r, eval = F}
# do not run
map(.x = <vector_or_list>, .f = <function>)
```

### Example: square a bunch of numbers

A silly example: use `map()` to square every number from 1 to 5. `.x` is the vector `1:5`; `.f` is a function that squares a number.

```{r}
map(
  .x = 1:5,
  .f = function(number) {
    number^2
  }
)
```

Notice that `map()` returns a **list**: similar to a vector, but much more flexible. Lists can be nested and lists can contain different data types (like a character string as one element and a number as the next). If you want to return a vector at the end, just pipe the result into `as_vector()`.

The example above is silly because many operations, including the square, is vectorized in R. A much simpler way to do this task is just:

```{r}
(1:5)^2
```

### Question 3

Use `map()` to divide every number from 1 to 100 by 2. Make sure that the output is a vector.

```{r}

```

Of course, division is also vectorized. So a much simpler way to do this is:

```{r}
(1:100)/2
```

## `map()` OLS Simulation

Now we'll explore a more useful way to use `map()`, on functions that are not vectorized.

In Econometrics, you probably proved that, under exogeneity, OLS is *consistent*: as the sample size increases, the distribution of OLS estimates will collapse around the true value. Let's show this in a simulation using `map()`.

We'll build this up step-by-step, because this will end up getting fairly complicated.

### Question 4

First, I'll generate some random data using `rnorm()`, which generates random numbers from the normal distribution. It takes `n` (number of observations to generate), `mean`, and `sd` (standard deviation). My `x` is pure noise around a mean of 50, and `y` depends partially on `x` and partially on its own random noise (we'd call this "u" or epsilon in econometrics).

Read the code closely: what are the true values for $\beta_0$ and $\beta_1$?

```{r}
tibble(
      x = rnorm(n = 100, mean = 50, sd = 10),
      y = 50 + 5 * x + rnorm(n = 100, mean = 0, sd = 100)
    )
```

### Question 5

Take my data set and pipe it into lm() to estimate the line of best fit. Observe: do you get estimates that are close to the true values for $\beta_0$ and $\beta_1$. Run the code several times: you'll get new estimates because `rnorm()` keeps on generating random numbers.

```{r}
# tibble(
#   ___
#     ) %>%
#   lm(___) %>%
#   broom::tidy()
```

### Question 6

Now use `map()` to run your code above 100 times, recording the estimate for $\beta_1$ each time. Let your `.x` be 1:100 so we run the simulation 100 times. Let your `.f` take as an input the variable `s`, but don't do anything with `s` in the body of your function because we don't want anything about the simulation to change each time we run it. Use `slice()` and `select()` to only save the estimate for $\beta_1$. After `map()`, pipe the result into `bind_rows()` to return a tibble instead of a list.

(Answer:)

```{r}
# map(
#   .x = ___,
#   .f = function(s) {
#     tibble(
#       ___
#     ) %>%
#       lm(___) %>%
#       broom::tidy() %>%
#       slice(___) %>%
#       select(___)
#   }
# ) %>%
#   bind_rows()
```

### Question 7

Copy-paste everything you did in question 6, and pipe the resulting tibble into a ggplot histogram to visualize the distribution of one variable: the distribution of $\beta_1$ estimates you found.

```{r}
# map(
#   .x = ___,
#   .f = function(___) {
#     tibble(
#       ___
#     ) %>%
#       lm(___) %>%
#       broom::tidy() %>%
#       slice(___) %>%
#       select(___)
#   }
# ) %>%
#   bind_rows() %>%
#   ggplot(___) +
#   geom_histogram()
```

### Question 8

Finally, let's do a consistency simulation. Consistency says that as the sample size increases, the distribution of OLS estimates collapses to the true value.

You'll use `map()`. Your `.x` will be the vector `c(100, 800, 1600)`: these are the sample sizes. That is, we want to:

- Take a sample size of 100 and find the OLS estimate for $\beta_1$
- Take a sample size of 800 and find the OLS estimate for $\beta_1$
- Take a sample size of 1600 and find the OLS estimate for $\beta_1$

And compare whether OLS gets better at finding the true value for $\beta_1$ the larger the sample size gets.

Your `.f` will be a function that takes as an input `s` (the sample size). In the body of the function, there will be another `map()`. It will take a `.x` that is `rep(s, 100)` to do the experiment 100 times for each sample size. The `.f` will generate data, run `lm`, pick out the estimate for $\beta_1$, and output a tibble with the sample size `s` and the estimate. Finally, use `bind_rows()` to output a tibble instead of a list, and visualize the results using `geom_density()` where `fill` is set to `sample_size`. Play with the `alpha` parameter so you can see all three distributions.

```{r}
# map(
#   .x = ___,
#   .f = function(s) {
#     map(
#       .x = ___,
#       .f = function(___) {
#             tibble(
#               ___
#               ) %>%
#           lm(___) %>%
#           broom::tidy() %>%
#           slice(___) %>%
#           select(___) %>%
#           mutate(sample_size = as.factor(s))
#       }
#     )
#   }
# ) %>%
#   bind_rows() %>%
#   ggplot(___) +
#   geom_density(alpha = ___)
```

You did it! To submit this assignment, make sure your names are typed at the top, compile to html (File > Render Document), and upload the resulting html file to Canvas. There is no autograder for this one.
