Use functional programming tools in base R to repeat multiple functional calls.
Use the purrr package for easily mapping and reducing functions.
What is functional programming?
All of our code is functional if it does its job?
Yes, but we are using the technical definition of functional programming: programming that is based on functions.
Specifically, we want to be able to compose functions, which you might remember hating in precalculus.
\[g \circ f = g(f(x))\]
In computer science, a functional is a function that accepts a function as an argument.
Functional vs. imperative programming
So far, we’ve been using imperative programming: we save variables, and we update them with new commands. Our code is structured as a list of instructions.
In functional programming, we write everything as a function, and we get the results we want by composing many functions.
But we’re just going to show you some useful parts of functional programming that you can include in your regular code.
Ok, but why?
Recall our function from the previous Module.
get_country_stats <-function(df, iso3_code){ country_data <-subset(df, iso3c == iso3_code)# Get the summary statistics for this country country_cases <- country_data$measles_cases country_quart <-quantile( country_cases, na.rm =TRUE, probs =c(0.25, 0.5, 0.75) ) country_range <-range(country_cases, na.rm =TRUE) country_name <-unique(country_data$country) country_summary <-data.frame(country = country_name,min = country_range[[1]],Q1 = country_quart[[1]],median = country_quart[[2]],Q3 = country_quart[[3]],max = country_range[[2]] )return(country_summary)}
We could write a loop to get stats for many countries.
[[1]]
country min Q1 median Q3 max
1 India 3305 31135.5 47109.5 80797.25 252940
[[2]]
country min Q1 median Q3 max
1 Pakistan 386 2065.5 4075.5 17422 55543
[[3]]
country min Q1 median Q3 max
1 Bangladesh 203 2193.75 5270.5 9889.5 27327
[[4]]
country min Q1 median Q3 max
1 Nepal 59 190 1268 3100 13344
But if we use a functional programming tool called lapply, look how easy it is!
[[1]]
country min Q1 median Q3 max
1 India 3305 31135.5 47109.5 80797.25 252940
[[2]]
country min Q1 median Q3 max
1 Pakistan 386 2065.5 4075.5 17422 55543
[[3]]
country min Q1 median Q3 max
1 Bangladesh 203 2193.75 5270.5 9889.5 27327
[[4]]
country min Q1 median Q3 max
1 Nepal 59 190 1268 3100 13344
Functional programming techniques can help us avoid writing messy loops and clean up our code.
Ok, but why?
R is a functional programming language at its core.
In R, functions are objects like everything else.
You never have to use FP, but it can help you write neater code.
More information: https://adv-r.hadley.nz/fp.html.
Next use apply with the correct choice of MARGIN and FUN to get the proportion of cases that resulted in death at all three time points in one function call.
Hint:
apply( d_matrix,MARGIN = (1 or 2),FUN = some_function)
Another hint: you can tell if you chose the correct MARGIN argument by counting the number of elements in the output. There should be 3, one for each column.
Solution:
apply( d_matrix,MARGIN =2,FUN = mean)
Died 30D_Mortality 60D_Mortality
0.3402778 0.3263889 0.3333333
You try it!
Load the measles dataset. Filter the dataset so you only have records from 2005, and only have complete cases.
Then, use split to split the dataframe into a list by region.
Now, use lapply() to fit a Poisson glm for each region separately that includes effects of MCV1 and MCV2 coverage.
Find a way, using lapply() or sapply(), coef(), and do.call() to make a nice matrix of the coefficients.
Functional programming tools like *apply() take a function as an input and use the same function multiple times.
In R, functions are objects like everything else and manipulating them like objects can help us write readable, fast code.
Side note: purrr is a modern version of *apply() with a more consistent interface. It’s worth learning and covered in the Advanced R book, but most people still use *apply().
This book also covers more standard FP tools like reduction and filtering that we didn’t have time to talk about.