├── .gitignore ├── Functional_Programming_with_purrr ├── customTests.R ├── dependson.txt ├── funcs.R ├── funcs.Rmd ├── funcs.html ├── initLesson.R └── lesson.yaml ├── Functions ├── customTests.R ├── initLesson.R ├── lesson.yaml └── scripts │ ├── bin_op-correct.R │ ├── bin_op.R │ ├── boring_function-correct.R │ ├── boring_function.R │ ├── evaluate-correct.R │ ├── evaluate.R │ ├── mad_libs-correct.R │ ├── mad_libs.R │ ├── my_mean-correct.R │ ├── my_mean.R │ ├── remainder-correct.R │ ├── remainder.R │ ├── telegram-correct.R │ └── telegram.R ├── MANIFEST └── Setting_Up_Swirl ├── customTests.R ├── dependson.txt ├── initLesson.R └── lesson.yaml /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /Functional_Programming_with_purrr/customTests.R: -------------------------------------------------------------------------------- 1 | keygen <- function(){ 2 | set.seed(sum(as.numeric(charToRaw("Functional_Programming_with_purrr")))) 3 | pran <- function(n = 1){ 4 | replicate(n, sample(c(LETTERS, letters, 0:9), 1)) 5 | } 6 | ks <- replicate(4, paste0(pran(4), collapse = "")) 7 | set.seed(NULL) 8 | pn <- sample(1:16, 1) 9 | kn <- sample(1:4, 1) 10 | sss <- paste(sample(c(LETTERS, letters, 0:9), 16-pn), collapse = "") 11 | eee <- paste(sample(c(LETTERS, letters, 0:9), pn), collapse = "") 12 | paste0(sss, ks[kn], eee) 13 | } 14 | 15 | # Get the swirl state 16 | getState <- function(){ 17 | # Whenever swirl is running, its callback is at the top of its call stack. 18 | # Swirl's state, named e, is stored in the environment of the callback. 19 | environment(sys.function(1))$e 20 | } 21 | 22 | # Get the value which a user either entered directly or was computed 23 | # by the command he or she entered. 24 | getVal <- function(){ 25 | getState()$val 26 | } 27 | 28 | # Get the last expression which the user entered at the R console. 29 | getExpr <- function(){ 30 | getState()$expr 31 | } 32 | 33 | coursera_on_demand <- function(){ 34 | selection <- getState()$val 35 | if(selection == "Yes"){ 36 | email <- readline("What is your email address? ") 37 | token <- readline("What is your assignment token? ") 38 | 39 | payload <- sprintf('{ 40 | "assignmentKey": "FMpWOI9XEeaT0w7BL4gjCA", 41 | "submitterEmail": "%s", 42 | "secret": "%s", 43 | "parts": { 44 | "ZP866": { 45 | "output": "correct" 46 | } 47 | } 48 | }', email, token) 49 | url <- 'https://www.coursera.org/api/onDemandProgrammingScriptSubmissions.v1' 50 | 51 | respone <- httr::POST(url, body = payload) 52 | if(respone$status_code >= 200 && respone$status_code < 300){ 53 | message("Grade submission succeeded!") 54 | } else { 55 | message("Grade submission failed.") 56 | message("Press ESC if you want to exit this lesson and you") 57 | message("want to try to submit your grade at a later time.") 58 | return(FALSE) 59 | } 60 | } else if(selection == "No"){ 61 | return(TRUE) 62 | } else { 63 | message("Submit the following code as the answer") 64 | message("to a quiz question on Coursera.\n") 65 | message("#########################\n") 66 | message(keygen(), "\n") 67 | message("#########################") 68 | return(TRUE) 69 | } 70 | } -------------------------------------------------------------------------------- /Functional_Programming_with_purrr/dependson.txt: -------------------------------------------------------------------------------- 1 | purrr -------------------------------------------------------------------------------- /Functional_Programming_with_purrr/funcs.R: -------------------------------------------------------------------------------- 1 | .viewer_question("funcs.html") -------------------------------------------------------------------------------- /Functional_Programming_with_purrr/funcs.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | output: html_document 3 | --- 4 | 5 | We'll use the following functions throughout this lesson: 6 | 7 | ```{r, echo=FALSE} 8 | int_to_string <- function(x){ 9 | c("one", "two", "three", "four", "five", 10 | "six", "seven", "eight", "nine", "ten")[x] 11 | } 12 | 13 | gt <- function(a, b){ 14 | a > b 15 | } 16 | 17 | is_even <- function(x){ 18 | x %% 2 == 0 19 | } 20 | 21 | square <- function(x){ 22 | x^2 23 | } 24 | 25 | add_talk <- function(x, y){ 26 | message("x is ", x) 27 | message("y is ", y, "\n") 28 | x + y 29 | } 30 | 31 | paste_talk <- function(x, y){ 32 | message("x is ", x) 33 | message("y is ", y, "\n") 34 | paste0(x, y) 35 | } 36 | ``` 37 | 38 | ## `int_to_string(x)` 39 | 40 | Covert a number into its string equivaluent. 41 | 42 | ```{r} 43 | int_to_string(4) 44 | ``` 45 | 46 | ## `gt(a, b)` 47 | 48 | Returns `TRUE` if `a` is greater than `b`, otherwise returns `FALSE`. 49 | 50 | ```{r} 51 | gt(3, 1) 52 | gt(2, 5) 53 | ``` 54 | 55 | ## `is_even(x)` 56 | 57 | Returns `TRUE` is `x` is even, otherwise returns `FALSE`. 58 | 59 | ```{r} 60 | is_even(34) 61 | is_even(55) 62 | ``` 63 | 64 | ## `square(x)` 65 | 66 | Computes the square of `x`. 67 | 68 | ```{r} 69 | square(4) 70 | ``` 71 | 72 | ## `add_talk(x, y)` 73 | 74 | Adds `x` and `y` and produces a message about which numbers are being added. 75 | 76 | ```{r} 77 | add_talk(5, 3) 78 | ``` 79 | 80 | ## `paste_talk(x, y)` 81 | 82 | Concatenates the strings `x` and `y` and produces a message about which stirngs 83 | are being concatenated. 84 | 85 | ```{r} 86 | paste_talk("red", "head") 87 | ``` -------------------------------------------------------------------------------- /Functional_Programming_with_purrr/initLesson.R: -------------------------------------------------------------------------------- 1 | # Code placed in this file fill be executed every time the 2 | # lesson is started. Any variables created here will show up in 3 | # the user's working directory and thus be accessible to them 4 | # throughout the lesson. 5 | 6 | int_to_string <- function(x){ 7 | c("one", "two", "three", "four", "five", 8 | "six", "seven", "eight", "nine", "ten")[x] 9 | } 10 | 11 | gt <- function(a, b){ 12 | a > b 13 | } 14 | 15 | is_even <- function(x){ 16 | x %% 2 == 0 17 | } 18 | 19 | square <- function(x){ 20 | x^2 21 | } 22 | 23 | add_talk <- function(x, y){ 24 | message("x is ", x) 25 | message("y is ", y, "\n") 26 | x + y 27 | } 28 | 29 | paste_talk <- function(x, y){ 30 | message("x is ", x) 31 | message("y is ", y, "\n") 32 | paste0(x, y) 33 | } 34 | 35 | random_ints <- sample(c(seq(21, 101, 2), c(6, 8, 10))) 36 | 37 | mark_antony <- c("Friends, Romans, countrymen,", 38 | "lend me your ears;", 39 | "I come to bury Caesar,", 40 | "not to praise him.") 41 | 42 | # For compatibility with 2.2.21 43 | .get_course_path <<- function(){ 44 | tryCatch(swirl:::swirl_courses_dir(), 45 | error = function(c) {file.path(find.package("swirl"),"Courses")} 46 | ) 47 | } 48 | 49 | .pathtofile <<- function(fileName){ 50 | mypath <- file.path(.get_course_path(), 51 | "Advanced_R_Programming", "Functional_Programming_with_purrr", 52 | fileName) 53 | } 54 | 55 | # @param html An html file. 56 | .viewer_question <<- function(html){ 57 | path <- .pathtofile(html) 58 | temp <- tempfile(fileext = ".html") 59 | file.copy(path, temp, overwrite = TRUE) 60 | 61 | viewer <- getOption("viewer") 62 | if (!is.null(viewer)) 63 | viewer(temp) 64 | else 65 | utils::browseURL(temp) 66 | } -------------------------------------------------------------------------------- /Functional_Programming_with_purrr/lesson.yaml: -------------------------------------------------------------------------------- 1 | - Class: meta 2 | Course: Advanced R Programming 3 | Lesson: Functional Programming with purrr 4 | Author: The Johns Hopkins Data Science Lab 5 | Type: Standard 6 | Organization: The Johns Hopkins Bloomberg School of Public Health 7 | Version: 2.4.2 8 | 9 | - Class: text 10 | Output: Functional programming is a programming philosophy based on lambda 11 | calculus. Lambda calculus was created by Alonzo Church, the PhD adviser to 12 | Alan Turing who is known for his role in cracking the encryption of the 13 | Nazi’s Enigma machine during World War Two. Functional programming has 14 | been a popular approach ever since it helped bring down the Third Reich. 15 | 16 | - Class: text 17 | Output: Functional programming concentrates on four constructs - Data 18 | (numbers, strings, etc), Variables (function arguments), Functions, and 19 | Function Applications (evaluating functions given arguments and/or data). 20 | 21 | - Class: text 22 | Output: There are groups of functions that are essential for functional 23 | programming. In most cases they take a function and a data structure as 24 | arguments, and that function is applied to that data structure in some way. 25 | The purrr library contains many of these functions and we’ll be using it 26 | throughout this lesson. Functional programming is concerned mostly with 27 | lists and vectors. I may refer to just lists or vectors, but you should 28 | know that what applies for lists generally applies for vectors and 29 | vice-versa. 30 | 31 | - Class: figure 32 | Output: I have defined a few functions that we are going to use throughout 33 | this lesson. Take a moment to familarize yourself with the documentation for 34 | these functions. 35 | Figure: funcs.R 36 | FigureType: new 37 | 38 | - Class: text 39 | Output: The first family of functions we'll be discussing are the Map 40 | functions. 41 | 42 | - Class: text 43 | Output: The map family of functions applies a function to the elements of a 44 | data structure, usually a list or a vector. The function is evaluated once 45 | for each element of the vector with the vector element as the first 46 | argument to the function. The return value is the same kind if data 47 | structure (a list or vector) but with every element replaced by the result 48 | of the function being evaluated with the corresponding element as the 49 | argument to the function. 50 | 51 | - Class: text 52 | Output: In the purrr package the map() function returns a list, while the 53 | map_lgl(), map_chr(), and map_dbl() functions return vectors of logical 54 | values, strings, or numbers respectively. 55 | 56 | - Class: cmd_question 57 | Output: Enter map_chr(c(5, 3, 4), int_to_string) into the R console to map the 58 | int_to_string() function to the vector c(5, 3, 4). 59 | CorrectAnswer: map_chr(c(5, 3, 4), int_to_string) 60 | AnswerTests: omnitest(correctExpr='map_chr(c(5, 3, 4), int_to_string)') 61 | Hint: Just enter map_chr(c(5, 3, 4), int_to_string) 62 | 63 | - Class: text 64 | Output: Think about evaluating the int_to_string() function with just one of 65 | the arguments in the specified numeric vector, and then combining all of 66 | those function results into one vector. That's essentially how the map 67 | functions work! 68 | 69 | - Class: cmd_question 70 | Output: Let's try using a function that has two arguments with a map function. 71 | Use map_lgl() to map the function gt() to vector c(1, 2, 3, 4, 5) to see 72 | which elements of that vector are greater than 3. Make sure to specify 73 | the last argument of map_lgl() as b = 3. 74 | CorrectAnswer: map_lgl(c(1, 2, 3, 4, 5), gt, b = 3) 75 | AnswerTests: omnitest(correctExpr='map_lgl(c(1, 2, 3, 4, 5), gt, b = 3)') 76 | Hint: Just enter map_lgl(c(1, 2, 3, 4, 5), gt, b = 3) 77 | 78 | - Class: text 79 | Output: The map_if() function takes as its arguments a list or vector 80 | containing data, a predicate function, and then a function to be applied. 81 | 82 | - Class: text 83 | Output: "A predicate function is a function that returns TRUE or FALSE for 84 | each element in the provided list or vector. In the case of map_if(): if 85 | the predicate functions evaluates to TRUE, then the function is applied to 86 | the corresponding vector element, however if the predicate function 87 | evaluates to FALSE then the function is not applied." 88 | 89 | - Class: cmd_question 90 | Output: Use map_if() to map square() to the even elements of the vector 91 | c(1, 2, 3, 4). Use the is_even() function as a predicate. 92 | CorrectAnswer: map_if(c(1, 2, 3, 4), is_even, square) 93 | AnswerTests: omnitest(correctExpr='map_if(c(1, 2, 3, 4), is_even, square)') 94 | Hint: Just enter map_if(c(1, 2, 3, 4), is_even, square) 95 | 96 | - Class: text 97 | Output: Take a look at the output - all of the even numbers were squared while 98 | the odd numbers were left alone! Notice that the map_if() function always 99 | returns a list. 100 | 101 | - Class: text 102 | Output: The map_at() function only applies the provided function to elements 103 | of a vector specified by their indexes. Like map_if(), map_at() always 104 | returns a list. 105 | 106 | - Class: cmd_question 107 | Output: Use the map_at() function to map square() to the first, third, and 108 | fourth element of the vector c(4, 6, 2, 3, 8). 109 | CorrectAnswer: map_at(c(4, 6, 2, 3, 8), c(1, 3, 4), square) 110 | AnswerTests: calculates_same_value("list(16, 6, 4, 9, 8)");expr_uses_func("map_at") 111 | Hint: Just enter map_at(c(4, 6, 2, 3, 8), c(1, 3, 4), square) 112 | 113 | - Class: text 114 | Output: In each of the previous examples we have only been mapping a 115 | function over one data structure, however you can map a function over two 116 | data structures with the map2() family of functions. The first two arguments 117 | should be two vectors of the same length, followed by a function which will 118 | be evaluated with an element of the first vector as the first argument and 119 | an element of the second vector as the second argument. 120 | 121 | - Class: cmd_question 122 | Output: Use map2_chr() to apply the paste() function to the sequence of 123 | integers from 1 to 26 and all the letters of the alphabet in lowercase. 124 | CorrectAnswer: map2_chr(letters, 1:26, paste) 125 | AnswerTests: calculates_same_value('c("a 1", "b 2", "c 3", "d 4", "e 5", "f 6", "g 7", "h 8", "i 9", "j 10", "k 11", "l 12", "m 13", "n 14", "o 15", "p 16", "q 17", "r 18", "s 19", "t 20", "u 21", "v 22", "w 23", "x 24", "y 25", "z 26")');expr_uses_func("map2_chr") 126 | Hint: Just type map2_chr(letters, 1:26, paste) 127 | 128 | - Class: text 129 | Output: Now we'll discuss the Reduce family of functions. 130 | 131 | - Class: text 132 | Output: List or vector reduction iteratively combines the first element of 133 | a vector with the second element of a vector, then that combined result 134 | is combined with the third element of the vector, and so on until the end 135 | of the vector is reached. The function to be applied should take at least 136 | two arguments. Where mapping returns a vector or a list, reducing should 137 | return a single value. 138 | 139 | - Class: cmd_question 140 | Output: Reduce the vector c(1, 3, 5, 7) with the function add_talk() using the 141 | reduce() function. 142 | CorrectAnswer: reduce(c(1, 3, 5, 7), add_talk) 143 | AnswerTests: omnitest(correctExpr='reduce(c(1, 3, 5, 7), add_talk)') 144 | Hint: Just enter reduce(c(1, 3, 5, 7), add_talk) 145 | 146 | - Class: text 147 | Output: On the first iteration x has the value 1 and y has the value 3, then 148 | the two values are combined (they’re added together). On the second 149 | iteration x has the value of the result from the first iteration (4) 150 | and y has the value of the third element in the provided numeric 151 | vector (5). This process is repeated for each iteration. 152 | 153 | - Class: cmd_question 154 | Output: Reduce the vector c("a", "b", "c", "d") into one string using the 155 | paste_talk() function and the reduce() function. 156 | CorrectAnswer: reduce(c("a", "b", "c", "d"), paste_talk) 157 | AnswerTests: omnitest(correctExpr='reduce(c("a", "b", "c", "d"), paste_talk)') 158 | Hint: Just enter reduce(c("a", "b", "c", "d"), paste_talk) 159 | 160 | - Class: text 161 | Output: By default reduce() starts with the first element of a vector and 162 | then the second element and so on. In contrast the reduce_right() function 163 | starts with the last element of a vector and then proceeds to the second 164 | to last element of a vector and so on. 165 | 166 | - Class: cmd_question 167 | Output: Reduce the vector c("a", "b", "c", "d") into one string using the 168 | paste_talk() function and the reduce_right() function. 169 | CorrectAnswer: reduce_right(c("a", "b", "c", "d"), paste_talk) 170 | AnswerTests: omnitest(correctExpr='reduce_right(c("a", "b", "c", "d"), paste_talk)') 171 | Hint: Just enter reduce_right(c("a", "b", "c", "d"), paste_talk) 172 | 173 | - Class: text 174 | Output: Next we'll discuss fuctions for searching a list or a vector. 175 | 176 | - Class: text 177 | Output: You can search for specific elements of a vector using the has_element() 178 | and detect() functions. has_element() will return TRUE if a specified element 179 | is present in a vector, otherwise it returns FALSE. 180 | 181 | - Class: cmd_question 182 | Output: Use the has_element() function to see if the vector random_ints 183 | contains the number 45. 184 | CorrectAnswer: has_element(random_ints, 45) 185 | AnswerTests: omnitest(correctExpr='has_element(random_ints, 45)') 186 | Hint: Just enter has_element(random_ints, 45) 187 | 188 | - Class: cmd_question 189 | Output: The detect() function takes a vector and a predicate function as 190 | arguments and it returns the first element of the vector for which the 191 | predicate function returns TRUE. Use detect() and is_even() to find the 192 | first element of random_ints that is an even number. 193 | CorrectAnswer: detect(random_ints, is_even) 194 | AnswerTests: omnitest(correctExpr='detect(random_ints, is_even)') 195 | Hint: Just enter detect(random_ints, is_even) 196 | 197 | - Class: cmd_question 198 | Output: The detect_index() function takes the same arguments as detect(), 199 | however it returns the index of the provided vector which contains the 200 | first element that satisfies the predicate function. Use detect_index() and 201 | is_even() to find the index of the first element of random_ints that is an 202 | even number. 203 | CorrectAnswer: detect_index(random_ints, is_even) 204 | AnswerTests: omnitest(correctExpr='detect_index(random_ints, is_even)') 205 | Hint: Just enter detect_index(random_ints, is_even) 206 | 207 | - Class: text 208 | Output: The group of functions that includes keep(), discard(), every(), and 209 | some() are known as filter functions. Each of these functions takes a 210 | vector and a predicate function as arguments. 211 | 212 | - Class: cmd_question 213 | Output: For keep() only the elements of the vector that satisfy the predicate 214 | function are returned while all other elements are removed. Use the keep() 215 | function with random_ints and is_even() to extract the even elements of 216 | random_ints. 217 | CorrectAnswer: keep(random_ints, is_even) 218 | AnswerTests: omnitest(correctExpr='keep(random_ints, is_even)') 219 | Hint: Just enter keep(random_ints, is_even) 220 | 221 | - Class: cmd_question 222 | Output: The discard() function works similarly, it only returns elements 223 | that don’t satisfy the predicate function. Use discard() to filter out the 224 | even elements of random_ints. 225 | CorrectAnswer: discard(random_ints, is_even) 226 | AnswerTests: omnitest(correctExpr='discard(random_ints, is_even)') 227 | Hint: Just type discard(random_ints, is_even) 228 | 229 | - Class: cmd_question 230 | Output: The every() function returns TRUE only if every element in the 231 | vector satisfies the predicate function, while the some() function returns 232 | TRUE if at least one element in the vector satisfies the predicate function. 233 | Use every() to see if every value of random_ints is less than 100. 234 | CorrectAnswer: every(random_ints, function(x){x < 100}) 235 | AnswerTests: calculates_same_value("FALSE");expr_uses_func("every") 236 | Hint: Just type every(random_ints, function(x){x < 100}) 237 | 238 | - Class: text 239 | Output: Finally let's talk about two functions - partial() and walk(). 240 | 241 | - Class: cmd_question 242 | Output: Partial application of functions can allow functions to behave a 243 | little like data structures. Using the partial() function from the purrr 244 | package you can specify some of the arguments of a function, and then 245 | partial() will return a function that only takes the unspecified arguments. 246 | Use partial() to create a new function caled gt_10 which returns TRUE if 247 | its only argument is greater than ten and FALSE otherwise. 248 | CorrectAnswer: gt_10 <- partial(gt, b = 10) 249 | AnswerTests: any_of_exprs('gt_10 <- partial(gt, b = 10)', 'gt_10 = partial(gt, b = 10)') 250 | Hint: Just enter gt_10 <- partial(gt, b = 10) 251 | 252 | - Class: cmd_question 253 | Output: Now test the new function out by entering gt_10(11) into the console. 254 | CorrectAnswer: gt_10(11) 255 | AnswerTests: omnitest(correctExpr='gt_10(11)') 256 | Hint: Just enter gt_10(11) 257 | 258 | - Class: text 259 | Output: Side effects of functions occur whenever a function interacts with 260 | the "outside world" - reading or writing data, printing to the console, 261 | and displaying a graph are all side effects. The results of side effects 262 | are one of the main motivations for writing code in the first place! Side 263 | effects can be tricky to handle though, since the order in which functions 264 | with side effects are executed often matters and there are variables that 265 | are external to the program (the relative location of some data). 266 | 267 | - Class: cmd_question 268 | Output: If you want to evaluate a function across a data structure you should 269 | use the walk() function from purrr. Use walk() across the vector called 270 | mark_antony with the message function. 271 | CorrectAnswer: walk(mark_antony, message) 272 | AnswerTests: omnitest(correctExpr='walk(mark_antony, message)') 273 | Hint: Just enter walk(mark_antony, message) 274 | 275 | - Class: mult_question 276 | Output: "Would you like to receive credit for completing this course on 277 | Coursera.org?" 278 | CorrectAnswer: NULL 279 | AnswerChoices: Yes;No;Generate Code 280 | AnswerTests: coursera_on_demand() 281 | Hint: "" 282 | -------------------------------------------------------------------------------- /Functions/customTests.R: -------------------------------------------------------------------------------- 1 | test_func1 <- function() { 2 | try({ 3 | func <- get('boring_function', globalenv()) 4 | t1 <- identical(func(9), 9) 5 | t2 <- identical(func(4), 4) 6 | t3 <- identical(func(0), 0) 7 | ok <- all(t1, t2, t3) 8 | }, silent = TRUE) 9 | exists('ok') && isTRUE(ok) 10 | } 11 | 12 | test_func2 <- function() { 13 | try({ 14 | func <- get('my_mean', globalenv()) 15 | t1 <- identical(func(9), mean(9)) 16 | t2 <- identical(func(1:10), mean(1:10)) 17 | t3 <- identical(func(c(-5, -2, 4, 10)), mean(c(-5, -2, 4, 10))) 18 | ok <- all(t1, t2, t3) 19 | }, silent = TRUE) 20 | exists('ok') && isTRUE(ok) 21 | } 22 | 23 | test_func3 <- function() { 24 | try({ 25 | func <- get('remainder', globalenv()) 26 | t1 <- identical(func(9, 4), 9 %% 4) 27 | t2 <- identical(func(divisor = 5, num = 2), 2 %% 5) 28 | t3 <- identical(func(5), 5 %% 2) 29 | ok <- all(t1, t2, t3) 30 | }, silent = TRUE) 31 | exists('ok') && isTRUE(ok) 32 | } 33 | 34 | test_func4 <- function() { 35 | try({ 36 | func <- get('evaluate', globalenv()) 37 | t1 <- identical(func(sum, c(2, 4, 7)), 13) 38 | t2 <- identical(func(median, c(9, 200, 100)), 100) 39 | t3 <- identical(func(floor, 12.1), 12) 40 | ok <- all(t1, t2, t3) 41 | }, silent = TRUE) 42 | exists('ok') && isTRUE(ok) 43 | } 44 | 45 | test_func5 <- function() { 46 | try({ 47 | func <- get('telegram', globalenv()) 48 | t1 <- identical(func("Good", "morning"), "START Good morning STOP") 49 | t2 <- identical(func("hello", "there", "sir"), "START hello there sir STOP") 50 | t3 <- identical(func(), "START STOP") 51 | ok <- all(t1, t2, t3) 52 | }, silent = TRUE) 53 | exists('ok') && isTRUE(ok) 54 | } 55 | 56 | test_func6 <- function() { 57 | try({ 58 | func <- get('mad_libs', globalenv()) 59 | t1 <- identical(func(place = "Baltimore", adjective = "smelly", noun = "Roger Peng statue"), "News from Baltimore today where smelly students took to the streets in protest of the new Roger Peng statue being installed on campus.") 60 | t2 <- identical(func(place = "Washington", adjective = "angry", noun = "Shake Shack"), "News from Washington today where angry students took to the streets in protest of the new Shake Shack being installed on campus.") 61 | ok <- all(t1, t2) 62 | }, silent = TRUE) 63 | exists('ok') && isTRUE(ok) 64 | } 65 | 66 | test_func7 <- function() { 67 | try({ 68 | func <- get('%p%', globalenv()) 69 | t1 <- identical(func("Good", "job!"), "Good job!") 70 | t2 <- identical(func("one", func("two", "three")), "one two three") 71 | ok <- all(t1, t2) 72 | }, silent = TRUE) 73 | exists('ok') && isTRUE(ok) 74 | } 75 | 76 | test_eval1 <- function(){ 77 | try({ 78 | e <- get("e", parent.frame()) 79 | expr <- e$expr 80 | t1 <- identical(expr[[3]], 6) 81 | expr[[3]] <- 7 82 | t2 <- identical(eval(expr), 8) 83 | ok <- all(t1, t2) 84 | }, silent = TRUE) 85 | exists('ok') && isTRUE(ok) 86 | } 87 | 88 | test_eval2 <- function(){ 89 | try({ 90 | e <- get("e", parent.frame()) 91 | expr <- e$expr 92 | t1 <- identical(expr[[3]], quote(c(8, 4, 0))) 93 | t2 <- identical(expr[[1]], quote(evaluate)) 94 | expr[[3]] <- c(5, 6) 95 | t3 <- identical(eval(expr), 5) 96 | ok <- all(t1, t2, t3) 97 | }, silent = TRUE) 98 | exists('ok') && isTRUE(ok) 99 | } 100 | 101 | test_eval3 <- function(){ 102 | try({ 103 | e <- get("e", parent.frame()) 104 | expr <- e$expr 105 | t1 <- identical(expr[[3]], quote(c(8, 4, 0))) 106 | t2 <- identical(expr[[1]], quote(evaluate)) 107 | expr[[3]] <- c(5, 6) 108 | t3 <- identical(eval(expr), 6) 109 | ok <- all(t1, t2, t3) 110 | }, silent = TRUE) 111 | exists('ok') && isTRUE(ok) 112 | } 113 | 114 | keygen <- function(){ 115 | set.seed(sum(as.numeric(charToRaw("Functions")))) 116 | pran <- function(n = 1){ 117 | replicate(n, sample(c(LETTERS, letters, 0:9), 1)) 118 | } 119 | ks <- replicate(4, paste0(pran(4), collapse = "")) 120 | set.seed(NULL) 121 | pn <- sample(1:16, 1) 122 | kn <- sample(1:4, 1) 123 | sss <- paste(sample(c(LETTERS, letters, 0:9), 16-pn), collapse = "") 124 | eee <- paste(sample(c(LETTERS, letters, 0:9), pn), collapse = "") 125 | paste0(sss, ks[kn], eee) 126 | } 127 | 128 | # Get the swirl state 129 | getState <- function(){ 130 | # Whenever swirl is running, its callback is at the top of its call stack. 131 | # Swirl's state, named e, is stored in the environment of the callback. 132 | environment(sys.function(1))$e 133 | } 134 | 135 | # Get the value which a user either entered directly or was computed 136 | # by the command he or she entered. 137 | getVal <- function(){ 138 | getState()$val 139 | } 140 | 141 | # Get the last expression which the user entered at the R console. 142 | getExpr <- function(){ 143 | getState()$expr 144 | } 145 | 146 | coursera_on_demand <- function(){ 147 | selection <- getState()$val 148 | if(selection == "Yes"){ 149 | email <- readline("What is your email address? ") 150 | token <- readline("What is your assignment token? ") 151 | 152 | payload <- sprintf('{ 153 | "assignmentKey": "PL3Db49VEea2YhJ0DzyiSg", 154 | "submitterEmail": "%s", 155 | "secret": "%s", 156 | "parts": { 157 | "Vv9SG": { 158 | "output": "correct" 159 | }, 160 | "NGfmh": { 161 | "output": "correct" 162 | } 163 | } 164 | }', email, token) 165 | url <- 'https://www.coursera.org/api/onDemandProgrammingScriptSubmissions.v1' 166 | 167 | respone <- httr::POST(url, body = payload) 168 | if(respone$status_code >= 200 && respone$status_code < 300){ 169 | message("Grade submission succeeded!") 170 | } else { 171 | message("Grade submission failed.") 172 | message("Press ESC if you want to exit this lesson and you") 173 | message("want to try to submit your grade at a later time.") 174 | return(FALSE) 175 | } 176 | } else if(selection == "No"){ 177 | return(TRUE) 178 | } else { 179 | message("Submit the following code as the answer") 180 | message("to a quiz question on Coursera.\n") 181 | message("#########################\n") 182 | message(keygen(), "\n") 183 | message("#########################") 184 | return(TRUE) 185 | } 186 | } -------------------------------------------------------------------------------- /Functions/initLesson.R: -------------------------------------------------------------------------------- 1 | # Put initialization code in this file. 2 | -------------------------------------------------------------------------------- /Functions/lesson.yaml: -------------------------------------------------------------------------------- 1 | - Class: meta 2 | Course: R Programming 3 | Lesson: Functions 4 | Author: Sean Kross 5 | Type: Standard 6 | Organization: swirlstats 7 | Version: 2.2.14 8 | 9 | - Class: text 10 | Output: Functions are one of the fundamental building blocks of the R language. They are small 11 | pieces of reusable code that can be treated like any other R object. 12 | 13 | - Class: text 14 | Output: "If you've worked through any other part of this course, you've probably 15 | used some functions already. Functions are usually characterized by the name 16 | of the function followed by parentheses." 17 | 18 | - Class: cmd_question 19 | Output: "Let's try using a few basic functions just for fun. The Sys.Date() 20 | function returns a string representing today's date. Type Sys.Date() below 21 | and see what happens." 22 | CorrectAnswer: Sys.Date() 23 | AnswerTests: omnitest(correctExpr='Sys.Date()') 24 | Hint: "Display today's date by typing: Sys.Date()" 25 | 26 | - Class: text 27 | Output: "Most functions in R return a value. Functions like Sys.Date() return a 28 | value based on your computer's environment, while other functions manipulate 29 | input data in order to compute a return value." 30 | 31 | - Class: cmd_question 32 | Output: "The mean() function takes a vector of numbers as input, and returns 33 | the average of all of the numbers in the input vector. Inputs to functions 34 | are often called arguments. Providing arguments to a function is also 35 | sometimes called passing arguments to that function. Arguments you want to 36 | pass to a function go inside the function's parentheses. Try passing the argument 37 | c(2, 4, 5) to the mean() function." 38 | CorrectAnswer: mean(c(2, 4, 5)) 39 | AnswerTests: omnitest(correctExpr='mean(c(2, 4, 5))') 40 | Hint: "Compute the average of 2, 4, and 5 by typing: mean(c(2, 4, 5))" 41 | 42 | - Class: text 43 | Output: Functions usually take arguments which are variables that the function operates on. For example, 44 | the mean() function takes a vector as an argument, like in the case of mean(c(2,6,8)). The mean() 45 | function then adds up all of the numbers in the vector and divides that sum by the 46 | length of the vector. 47 | 48 | - Class: text 49 | Output: In the following question you will be asked to modify a script that will 50 | appear as soon as you move on from this question. When you have finished modifying 51 | the script, save your changes to the script and type submit() and the script 52 | will be evaluated. There will be some comments in the script that opens up, so be 53 | sure to read them! 54 | 55 | - Class: script 56 | Output: The last R expression to be evaluated in a function will become the 57 | return value of that function. We want this function to take one argument, 58 | x, and return x without modifying it. Delete the pound 59 | sign so that x is returned without any modification. Make sure to save your 60 | script before you type submit(). 61 | AnswerTests: test_func1() 62 | Hint: Make sure to delete the pound sign so the last expression in the function is just x. 63 | Script: boring_function.R 64 | 65 | - Class: cmd_question 66 | Output: "Now that you've created your first function let's test it! Type: 67 | boring_function('My first function!'). If your function works, it should 68 | just return the string: 'My first function!'" 69 | CorrectAnswer: "boring_function('My first function!')" 70 | AnswerTests: omnitest(correctExpr="boring_function('My first function!')") 71 | Hint: "Test boring_function by typing: boring_function('My first function!')" 72 | 73 | - Class: text 74 | Output: "Congratulations on writing your first function. By writing functions, 75 | you can gain serious insight into how R works. As John Chambers, the creator 76 | of R once said:\n\n To understand computations in R, two slogans are helpful: 77 | 1. Everything that exists is an object. 2. Everything that happens is a function call." 78 | 79 | - Class: cmd_question 80 | Output: "If you want to see the source code for any function, just type the 81 | function name without any arguments or parentheses. Let's try this out with 82 | the function you just created. Type: boring_function to view its source code." 83 | CorrectAnswer: boring_function 84 | AnswerTests: omnitest(correctExpr='boring_function') 85 | Hint: "To see the source code for boring_function just type: boring_function" 86 | 87 | - Class: text 88 | Output: "Time to make a more useful function! We're going to replicate the 89 | functionality of the mean() function by creating a function called: my_mean(). 90 | Remember that to calculate the average of all of the numbers in a vector you 91 | find the sum of all the numbers in the vector, and then divide that sum by the 92 | number of numbers in the vector." 93 | 94 | - Class: script 95 | Output: Make sure to save your script before you type submit(). 96 | AnswerTests: test_func2() 97 | Hint: "Use the sum() function to find the sum of all the numbers in the vector. Use 98 | the length() function to find the size of the vector." 99 | Script: my_mean.R 100 | 101 | - Class: cmd_question 102 | Output: "Now test out your my_mean() function by finding the mean of the vector 103 | c(4, 5, 10)." 104 | CorrectAnswer: my_mean(c(4, 5, 10)) 105 | AnswerTests: omnitest(correctExpr='my_mean(c(4, 5, 10))') 106 | Hint: "Run the command my_mean(c(4, 5, 10)) to test out your new function." 107 | 108 | - Class: text 109 | Output: "Next, let's try writing a function with default arguments. You can set 110 | default values for a function's arguments, and this can be useful if you think 111 | someone who uses your function will set a certain argument to the same value 112 | most of the time." 113 | 114 | - Class: script 115 | Output: Make sure to save your script before you type submit(). 116 | AnswerTests: test_func3() 117 | Hint: "Remember to set the appropriate default values!" 118 | Script: remainder.R 119 | 120 | - Class: cmd_question 121 | Output: "Let's do some testing of the remainder function. Run remainder(5) 122 | and see what happens." 123 | CorrectAnswer: remainder(5) 124 | AnswerTests: omnitest(correctExpr='remainder(5)') 125 | Hint: "Let's test your remainder function by running: remainder(5)" 126 | 127 | - Class: text 128 | Output: "Let's take a moment to examine what just happened. You provided one 129 | argument to the function, and R matched that argument to 'num' since 'num' 130 | is the first argument. The default value for 'divisor' is 2, so the function 131 | used the default value you provided." 132 | 133 | - Class: cmd_question 134 | Output: "Now let's test the remainder function by providing two arguments. 135 | Type: remainder(11, 5) and let's see what happens." 136 | CorrectAnswer: remainder(11, 5) 137 | AnswerTests: omnitest(correctExpr='remainder(11, 5)') 138 | Hint: "Let's test your remainder function by running: remainder(11, 5)" 139 | 140 | - Class: text 141 | Output: "Once again, the arguments have been matched appropriately." 142 | 143 | - Class: cmd_question 144 | Output: "You can also explicitly specify arguments in a function. When you 145 | explicitly designate argument values by name, the ordering of the arguments 146 | becomes unimportant. You can try this out by typing: 147 | remainder(divisor = 11, num = 5)." 148 | CorrectAnswer: remainder(divisor = 11, num = 5) 149 | AnswerTests: omnitest(correctExpr='remainder(divisor = 11, num = 5)') 150 | Hint: "Order no longer matters when you explicity state argument values! Test 151 | this out by typing: remainder(divisor = 11, num = 5)" 152 | 153 | - Class: text 154 | Output: "As you can see, there is a significant difference between 155 | remainder(11, 5) and remainder(divisor = 11, num = 5)!" 156 | 157 | - Class: cmd_question 158 | Output: "R can also partially match arguments. Try typing remainder(4, div = 2) 159 | to see this feature in action." 160 | CorrectAnswer: remainder(4, div = 2) 161 | AnswerTests: omnitest(correctExpr='remainder(4, div = 2)') 162 | Hint: "Test out partial matching by typing: remainder(4, div = 2)" 163 | 164 | - Class: text 165 | Output: "A word of warning: in general you want to make your code as easy to 166 | understand as possible. Switching around the orders of arguments by 167 | specifying their names or only using partial argument names can be 168 | confusing, so use these features with caution!" 169 | 170 | - Class: cmd_question 171 | Output: "With all of this talk about arguments, you may be wondering if there 172 | is a way you can see a function's arguments (besides looking at the 173 | documentation). Thankfully, you can use the args() function! Type: 174 | args(remainder) to examine the arguments for the remainder function." 175 | CorrectAnswer: args(remainder) 176 | AnswerTests: omnitest(correctExpr='args(remainder)') 177 | Hint: "Look at the arguments of the remainder function by typing: 178 | args(remainder)" 179 | 180 | - Class: text 181 | Output: "You may not realize it but I just tricked you into doing something 182 | pretty interesting! args() is a function, remainder() is a function, yet 183 | remainder was an argument for args(). Yes it's true: you can pass functions 184 | as arguments! This is a very powerful concept. Let's write a script to see 185 | how it works." 186 | 187 | - Class: script 188 | Output: Make sure to save your script before you type submit(). 189 | AnswerTests: test_func4() 190 | Hint: "Make sure that when you pass a function as an argument you pass the 191 | name of the function without parentheses!" 192 | Script: evaluate.R 193 | 194 | - Class: cmd_question 195 | Output: "Let's take your new evaluate() function for a spin! Use evaluate to 196 | find the standard deviation of the vector c(1.4, 3.6, 7.9, 8.8)." 197 | CorrectAnswer: evaluate(sd, c(1.4, 3.6, 7.9, 8.8)) 198 | AnswerTests: omnitest(correctExpr='evaluate(sd, c(1.4, 3.6, 7.9, 8.8))') 199 | Hint: "The function for standard deviation is called sd(). Make sure that when 200 | you pass a function as an argument you pass the 201 | name of the function without parentheses!" 202 | 203 | - Class: text 204 | Output: "The idea of passing functions as arguments to other functions is an 205 | important and fundamental concept in programming." 206 | 207 | - Class: text 208 | Output: "You may be surprised to learn that you can pass a function as an 209 | argument without first defining the passed function. Functions that are not 210 | named are appropriately known as anonymous functions." 211 | 212 | - Class: text 213 | Output: "Let's use the evaluate function to explore how anonymous functions 214 | work. For the first argument of the evaluate function we're going to write a 215 | tiny function that fits on one line. In the second argument we'll pass some 216 | data to the tiny anonymous function in the first argument." 217 | 218 | - Class: cmd_question 219 | Output: "Type the following command and then we'll discuss how it works: 220 | evaluate(function(x){x+1}, 6)" 221 | CorrectAnswer: evaluate(function(x){x+1}, 6) 222 | AnswerTests: test_eval1() 223 | Hint: "Just type the command evaluate(function(x){x+1}, 6)" 224 | 225 | - Class: text 226 | Output: "The first argument is a tiny anonymous function that takes one argument 227 | `x` and returns `x+1`. We passed the number 6 into this function so the entire 228 | expression evaluates to 7." 229 | 230 | - Class: cmd_question 231 | Output: "Try using evaluate() along with an anonymous function to return the 232 | first element of the vector c(8, 4, 0). Your anonymous function should only 233 | take one argument which should be a variable `x`." 234 | CorrectAnswer: evaluate(function(x){x[1]}, c(8, 4, 0)) 235 | AnswerTests: test_eval2() 236 | Hint: "You may need to recall how to index vector elements. Remember that your 237 | anonymous function should only have one argument, and that argument should 238 | be named `x`." 239 | 240 | - Class: cmd_question 241 | Output: "Now try using evaluate() along with an anonymous function to return the 242 | last element of the vector c(8, 4, 0). Your anonymous function should only 243 | take one argument which should be a variable `x`." 244 | CorrectAnswer: evaluate(function(x){x[length(x)]}, c(8, 4, 0)) 245 | AnswerTests: test_eval3() 246 | Hint: "You may need to recall how to index vector elements. Remember that your 247 | anonymous function should only have one argument, and that argument should 248 | be named `x`. Using the length() function in your anonymous function may 249 | help you." 250 | 251 | - Class: cmd_question 252 | Output: "For the rest of the course we're going to use the paste() function 253 | frequently. Type ?paste so we can take a look at the documentation for the 254 | paste function." 255 | CorrectAnswer: ?paste 256 | AnswerTests: omnitest(correctExpr='?paste') 257 | Hint: "Just type: ?paste" 258 | 259 | - Class: text 260 | Output: "As you can see the first argument of paste() is `...` which is referred 261 | to as an ellipsis or simply dot-dot-dot. The ellipsis allows an indefinite 262 | number of arguments to be passed into a function. In the case of paste() any 263 | number of strings can be passed as arguments and paste() will return all of 264 | the strings combined into one string." 265 | 266 | - Class: cmd_question 267 | Output: 'Just to see how paste() works, type paste("Programming", "is", "fun!")' 268 | CorrectAnswer: paste("Programming", "is", "fun!") 269 | AnswerTests: omnitest(correctExpr='paste("Programming", "is", "fun!")') 270 | Hint: 'Just type: paste("Programming", "is", "fun!")' 271 | 272 | - Class: text 273 | Output: "Time to write our own modified version of paste()." 274 | 275 | - Class: script 276 | Output: Make sure to save your script before you type submit(). 277 | AnswerTests: test_func5() 278 | Hint: "Remember that arguments can come after ..." 279 | Script: telegram.R 280 | 281 | - Class: cmd_question 282 | Output: "Now let's test out your telegram function. Use your new telegram 283 | function passing in whatever arguments you wish!" 284 | CorrectAnswer: telegram() 285 | AnswerTests: expr_uses_func('telegram') 286 | Hint: 'Use the telegram function with whatever arguments you want to use.' 287 | 288 | - Class: script 289 | Output: Make sure to save your script before you type submit(). 290 | AnswerTests: test_func6() 291 | Hint: "Your function should have three sections: capture the ellipsis in a 292 | list(), unpack the arguments from the ellipsis and assign them to variables, 293 | then pass those variables to paste()." 294 | Script: mad_libs.R 295 | 296 | - Class: cmd_question 297 | Output: "Time to use your mad_libs function. Make sure to name the place, 298 | adjective, and noun arguments in order for your function to work." 299 | CorrectAnswer: mad_libs(adjective = "", place = "", noun = "") 300 | AnswerTests: expr_uses_func('mad_libs') 301 | Hint: 'Use the mad_libs function and be sure to name place, adjective, and 302 | noun arguments.' 303 | 304 | - Class: text 305 | Output: "We're coming to the end of this lesson, but there's still one more 306 | idea you should be made aware of." 307 | 308 | - Class: text 309 | Output: "You're familiar with adding, subtracting, multiplying, and dividing 310 | numbers in R. To do this you use the +, -, *, and / symbols. These symbols 311 | are called binary operators because they take two inputs, an input from the 312 | left and an input from the right." 313 | 314 | - Class: text 315 | Output: "In R you can define your own binary operators. In the next script 316 | I'll show you how." 317 | 318 | - Class: script 319 | Output: Make sure to save your script before you type submit(). 320 | AnswerTests: test_func7() 321 | Hint: "Remember: 'Hello' %p% 'student!' is how you use the binary operator." 322 | Script: bin_op.R 323 | 324 | - Class: cmd_question 325 | Output: "You made your own binary operator! Let's test it out. Paste together 326 | the strings: 'I', 'love', 'R!' using your new binary operator." 327 | CorrectAnswer: "'I' %p% 'love' %p% 'R!'" 328 | AnswerTests: omnitest(correctExpr="'I' %p% 'love' %p% 'R!'") 329 | Hint: 'Use %p% in between each string.' 330 | 331 | - Class: text 332 | Output: "We've come to the end of our lesson! Go out there and write some 333 | great functions!" 334 | 335 | - Class: mult_question 336 | Output: "Would you like to receive credit for completing this course on 337 | Coursera.org?" 338 | CorrectAnswer: NULL 339 | AnswerChoices: Yes;No;Generate Code 340 | AnswerTests: coursera_on_demand() 341 | Hint: "" 342 | -------------------------------------------------------------------------------- /Functions/scripts/bin_op-correct.R: -------------------------------------------------------------------------------- 1 | # The syntax for creating new binary operators in R is unlike anything else in 2 | # R, but it allows you to define a new syntax for your function. I would only 3 | # recommend making your own binary operator if you plan on using it often! 4 | # 5 | # User-defined binary operators have the following syntax: 6 | # %[whatever]% 7 | # where [whatever] represents any valid variable name. 8 | # 9 | # Let's say I wanted to define a binary operator that multiplied two numbers and 10 | # then added one to the product. An implementation of that operator is below: 11 | # 12 | # "%mult_add_one%" <- function(left, right){ # Notice the quotation marks! 13 | # left * right + 1 14 | # } 15 | # 16 | # I could then use this binary operator like `4 %mult_add_one% 5` which would 17 | # evaluate to 21. 18 | # 19 | # Write your own binary operator below from absolute scratch! Your binary 20 | # operator must be called %p% so that the expression: 21 | # 22 | # "Good" %p% "job!" 23 | # 24 | # will evaluate to: "Good job!" 25 | 26 | "%p%" <- function(left, right){ # Remember to add arguments! 27 | paste(left, right) 28 | } 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /Functions/scripts/bin_op.R: -------------------------------------------------------------------------------- 1 | # The syntax for creating new binary operators in R is unlike anything else in 2 | # R, but it allows you to define a new syntax for your function. I would only 3 | # recommend making your own binary operator if you plan on using it often! 4 | # 5 | # User-defined binary operators have the following syntax: 6 | # %[whatever]% 7 | # where [whatever] represents any valid variable name. 8 | # 9 | # Let's say I wanted to define a binary operator that multiplied two numbers and 10 | # then added one to the product. An implementation of that operator is below: 11 | # 12 | # "%mult_add_one%" <- function(left, right){ # Notice the quotation marks! 13 | # left * right + 1 14 | # } 15 | # 16 | # I could then use this binary operator like `4 %mult_add_one% 5` which would 17 | # evaluate to 21. 18 | # 19 | # Write your own binary operator below from absolute scratch! Your binary 20 | # operator must be called %p% so that the expression: 21 | # 22 | # "Good" %p% "job!" 23 | # 24 | # will evaluate to: "Good job!" 25 | 26 | "%p%" <- function(){ # Remember to add arguments! 27 | 28 | } 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /Functions/scripts/boring_function-correct.R: -------------------------------------------------------------------------------- 1 | boring_function <- function(x) { 2 | x 3 | } 4 | -------------------------------------------------------------------------------- /Functions/scripts/boring_function.R: -------------------------------------------------------------------------------- 1 | # You're about to write your first function! Just like you would assign a value 2 | # to a variable with the assignment operator, you assign functions in the following 3 | # way: 4 | # 5 | # function_name <- function(arg1, arg2){ 6 | # # Manipulate arguments in some way 7 | # # Return a value 8 | # } 9 | # 10 | # The "variable name" you assign will become the name of your function. arg1 and 11 | # arg2 represent the arguments of your function. You can manipulate the arguments 12 | # you specify within the function. After sourcing the function, you can use the 13 | # function by typing: 14 | # 15 | # function_name(value1, value2) 16 | # 17 | # Below we will create a function called boring_function. This function takes 18 | # the argument `x` as input, and returns the value of x without modifying it. 19 | # Delete the pound sign in front of the x to make the function work! Be sure to 20 | # save this script and type submit() in the console after you make your changes. 21 | 22 | boring_function <- function(x) { 23 | #x 24 | } 25 | -------------------------------------------------------------------------------- /Functions/scripts/evaluate-correct.R: -------------------------------------------------------------------------------- 1 | # You can pass functions as arguments to other functions just like you can pass 2 | # data to functions. Let's say you define the following functions: 3 | # 4 | # add_two_numbers <- function(num1, num2){ 5 | # num1 + num2 6 | # } 7 | # 8 | # multiply_two_numbers <- function(num1, num2){ 9 | # num1 * num2 10 | # } 11 | # 12 | # some_function <- function(func){ 13 | # func(2, 4) 14 | # } 15 | # 16 | # As you can see we use the argument name "func" like a function inside of 17 | # "some_function()." By passing functions as arguments 18 | # some_function(add_two_numbers) will evaluate to 6, while 19 | # some_function(multiply_two_numbers) will evaluate to 8. 20 | # 21 | # Finish the function definition below so that if a function is passed into the 22 | # "func" argument and some data (like a vector) is passed into the dat argument 23 | # the evaluate() function will return the result of dat being passed as an 24 | # argument to func. 25 | # 26 | # Hints: This exercise is a little tricky so I'll provide a few example of how 27 | # evaluate() should act: 28 | # 1. evaluate(sum, c(2, 4, 6)) should evaluate to 12 29 | # 2. evaluate(median, c(7, 40, 9)) should evaluate to 9 30 | # 3. evaluate(floor, 11.1) should evaluate to 11 31 | 32 | evaluate <- function(func, dat){ 33 | # Write your code here! 34 | # Remember: the last expression evaluated will be returned! 35 | func(dat) 36 | } 37 | -------------------------------------------------------------------------------- /Functions/scripts/evaluate.R: -------------------------------------------------------------------------------- 1 | # You can pass functions as arguments to other functions just like you can pass 2 | # data to functions. Let's say you define the following functions: 3 | # 4 | # add_two_numbers <- function(num1, num2){ 5 | # num1 + num2 6 | # } 7 | # 8 | # multiply_two_numbers <- function(num1, num2){ 9 | # num1 * num2 10 | # } 11 | # 12 | # some_function <- function(func){ 13 | # func(2, 4) 14 | # } 15 | # 16 | # As you can see we use the argument name "func" like a function inside of 17 | # "some_function()." By passing functions as arguments 18 | # some_function(add_two_numbers) will evaluate to 6, while 19 | # some_function(multiply_two_numbers) will evaluate to 8. 20 | # 21 | # Finish the function definition below so that if a function is passed into the 22 | # "func" argument and some data (like a vector) is passed into the dat argument 23 | # the evaluate() function will return the result of dat being passed as an 24 | # argument to func. 25 | # 26 | # Hints: This exercise is a little tricky so I'll provide a few example of how 27 | # evaluate() should act: 28 | # 1. evaluate(sum, c(2, 4, 6)) should evaluate to 12 29 | # 2. evaluate(median, c(7, 40, 9)) should evaluate to 9 30 | # 3. evaluate(floor, 11.1) should evaluate to 11 31 | 32 | evaluate <- function(func, dat){ 33 | # Write your code here! 34 | # Remember: the last expression evaluated will be returned! 35 | } 36 | -------------------------------------------------------------------------------- /Functions/scripts/mad_libs-correct.R: -------------------------------------------------------------------------------- 1 | # Let's explore how to "unpack" arguments from an ellipses when you use the 2 | # ellipses as an argument in a function. Below I have an example function that 3 | # is supposed to add two explicitly named arguments called alpha and beta. 4 | # 5 | # add_alpha_and_beta <- function(...){ 6 | # # First we must capture the ellipsis inside of a list 7 | # # and then assign the list to a variable. Let's name this 8 | # # variable `args`. 9 | # 10 | # args <- list(...) 11 | # 12 | # # We're now going to assume that there are two named arguments within args 13 | # # with the names `alpha` and `beta.` We can extract named arguments from 14 | # # the args list by used the name of the argument and double brackets. The 15 | # # `args` variable is just a regular list after all! 16 | # 17 | # alpha <- args[["alpha"]] 18 | # beta <- args[["beta"]] 19 | # 20 | # # Then we return the sum of alpha and beta. 21 | # 22 | # alpha + beta 23 | # } 24 | # 25 | # Have you ever played Mad Libs before? The function below will construct a 26 | # sentence from parts of speech that you provide as arguments. We'll write most 27 | # of the function, but you'll need to unpack the appropriate arguments from the 28 | # ellipses. 29 | 30 | mad_libs <- function(...){ 31 | # Do your argument unpacking here! 32 | args <- list(...) 33 | place <- args[["place"]] 34 | adjective <- args[["adjective"]] 35 | noun <- args[["noun"]] 36 | 37 | # Don't modify any code below this comment. 38 | # Notice the variables you'll need to create in order for the code below to 39 | # be functional! 40 | paste("News from", place, "today where", adjective, "students took to the streets in protest of the new", noun, "being installed on campus.") 41 | } -------------------------------------------------------------------------------- /Functions/scripts/mad_libs.R: -------------------------------------------------------------------------------- 1 | # Let's explore how to "unpack" arguments from an ellipses when you use the 2 | # ellipses as an argument in a function. Below I have an example function that 3 | # is supposed to add two explicitly named arguments called alpha and beta. 4 | # 5 | # add_alpha_and_beta <- function(...){ 6 | # # First we must capture the ellipsis inside of a list 7 | # # and then assign the list to a variable. Let's name this 8 | # # variable `args`. 9 | # 10 | # args <- list(...) 11 | # 12 | # # We're now going to assume that there are two named arguments within args 13 | # # with the names `alpha` and `beta.` We can extract named arguments from 14 | # # the args list by using the name of the argument and double brackets. The 15 | # # `args` variable is just a regular list after all! 16 | # 17 | # alpha <- args[["alpha"]] 18 | # beta <- args[["beta"]] 19 | # 20 | # # Then we return the sum of alpha and beta. 21 | # 22 | # alpha + beta 23 | # } 24 | # 25 | # Have you ever played Mad Libs before? The function below will construct a 26 | # sentence from parts of speech that you provide as arguments. We'll write most 27 | # of the function, but you'll need to unpack the appropriate arguments from the 28 | # ellipses. 29 | 30 | mad_libs <- function(...){ 31 | # Do your argument unpacking here! 32 | 33 | # Don't modify any code below this comment. 34 | # Notice the variables you'll need to create in order for the code below to 35 | # be functional! 36 | paste("News from", place, "today where", adjective, "students took to the streets in protest of the new", noun, "being installed on campus.") 37 | } 38 | -------------------------------------------------------------------------------- /Functions/scripts/my_mean-correct.R: -------------------------------------------------------------------------------- 1 | # You're free to implement the function my_mean however you want, as long as it 2 | # returns the average of all of the numbers in `my_vector`. 3 | # 4 | # Hint #1: sum() returns the sum of a vector. 5 | # Ex: sum(c(1, 2, 3)) evaluates to 6 6 | # 7 | # Hint #2: length() returns the size of a vector. 8 | # Ex: length(c(1, 2, 3)) evaluates to 3 9 | # 10 | # Hint #3: The mean of all the numbers in a vector is equal to the sum of all of 11 | # the numbers in the vector divided by the size of the vector. 12 | # 13 | # Note for those of you feeling super clever: Please do not use the mean() 14 | # function while writing this function. We're trying to teach you something 15 | # here! 16 | # 17 | # Be sure to save this script and type submit() in the console after you make 18 | # your changes. 19 | 20 | my_mean <- function(my_vector) { 21 | # Write your code here! 22 | # Remember: the last expression evaluated will be returned! 23 | sum(my_vector)/length(my_vector) 24 | } 25 | -------------------------------------------------------------------------------- /Functions/scripts/my_mean.R: -------------------------------------------------------------------------------- 1 | # You're free to implement the function my_mean however you want, as long as it 2 | # returns the average of all of the numbers in `my_vector`. 3 | # 4 | # Hint #1: sum() returns the sum of a vector. 5 | # Ex: sum(c(1, 2, 3)) evaluates to 6 6 | # 7 | # Hint #2: length() returns the size of a vector. 8 | # Ex: length(c(1, 2, 3)) evaluates to 3 9 | # 10 | # Hint #3: The mean of all the numbers in a vector is equal to the sum of all of 11 | # the numbers in the vector divided by the size of the vector. 12 | # 13 | # Note for those of you feeling super clever: Please do not use the mean() 14 | # function while writing this function. We're trying to teach you something 15 | # here! 16 | # 17 | # Be sure to save this script and type submit() in the console after you make 18 | # your changes. 19 | 20 | my_mean <- function(my_vector) { 21 | # Write your code here! 22 | # Remember: the last expression evaluated will be returned! 23 | } 24 | -------------------------------------------------------------------------------- /Functions/scripts/remainder-correct.R: -------------------------------------------------------------------------------- 1 | # Let me show you an example of a function I'm going to make up called 2 | # increment(). Most of the time I want to use this function to increase the 3 | # value of a number by one. This function will take two arguments: "number" and 4 | # "by" where "number" is the digit I want to increment and "by" is the amount I 5 | # want to increment "number" by. I've written the function below. 6 | # 7 | # increment <- function(number, by = 1){ 8 | # number + by 9 | # } 10 | # 11 | # If you take a look in between the parentheses you can see that I've set 12 | # "by" equal to 1. This means that the "by" argument will have the default 13 | # value of 1. 14 | # 15 | # I can now use the increment function without providing a value for "by": 16 | # increment(5) will evaluate to 6. 17 | # 18 | # However if I want to provide a value for the "by" argument I still can! The 19 | # expression: increment(5, 2) will evaluate to 7. 20 | # 21 | # You're going to write a function called "remainder." remainder() will take 22 | # two arguments: "num" and "divisor" where "num" is divided by "divisor" and 23 | # the remainder is returned. Imagine that you usually want to know the remainder 24 | # when you divide by 2, so set the default value of "divisor" to 2. Please be 25 | # sure that "num" is the first argument and "divisor" is the second argument. 26 | # 27 | # Hint #1: You can use the modulus operator %% to find the remainder. 28 | # Ex: 7 %% 4 evaluates to 3. 29 | # 30 | # Remember to set appropriate default values! Be sure to save this 31 | # script and type submit() in the console after you write the function. 32 | 33 | remainder <- function(num, divisor = 2) { 34 | # Write your code here! 35 | # Remember: the last expression evaluated will be returned! 36 | num %% divisor 37 | } 38 | -------------------------------------------------------------------------------- /Functions/scripts/remainder.R: -------------------------------------------------------------------------------- 1 | # Let me show you an example of a function I'm going to make up called 2 | # increment(). Most of the time I want to use this function to increase the 3 | # value of a number by one. This function will take two arguments: "number" and 4 | # "by" where "number" is the digit I want to increment and "by" is the amount I 5 | # want to increment "number" by. I've written the function below. 6 | # 7 | # increment <- function(number, by = 1){ 8 | # number + by 9 | # } 10 | # 11 | # If you take a look in between the parentheses you can see that I've set 12 | # "by" equal to 1. This means that the "by" argument will have the default 13 | # value of 1. 14 | # 15 | # I can now use the increment function without providing a value for "by": 16 | # increment(5) will evaluate to 6. 17 | # 18 | # However if I want to provide a value for the "by" argument I still can! The 19 | # expression: increment(5, 2) will evaluate to 7. 20 | # 21 | # You're going to write a function called "remainder." remainder() will take 22 | # two arguments: "num" and "divisor" where "num" is divided by "divisor" and 23 | # the remainder is returned. Imagine that you usually want to know the remainder 24 | # when you divide by 2, so set the default value of "divisor" to 2. Please be 25 | # sure that "num" is the first argument and "divisor" is the second argument. 26 | # 27 | # Hint #1: You can use the modulus operator %% to find the remainder. 28 | # Ex: 7 %% 4 evaluates to 3. 29 | # 30 | # Remember to set appropriate default values! Be sure to save this 31 | # script and type submit() in the console after you write the function. 32 | 33 | remainder <- function(num, divisor) { 34 | # Write your code here! 35 | # Remember: the last expression evaluated will be returned! 36 | } 37 | -------------------------------------------------------------------------------- /Functions/scripts/telegram-correct.R: -------------------------------------------------------------------------------- 1 | # The ellipses can be used to pass on arguments to other functions that are 2 | # used within the function you're writing. Usually a function that has the 3 | # ellipses as an argument has the ellipses as the last argument. The usage of 4 | # such a function would look like: 5 | # 6 | # ellipses_func(arg1, arg2 = TRUE, ...) 7 | # 8 | # In the above example arg1 has no default value, so a value must be provided 9 | # for arg1. arg2 has a default value, and other arguments can come after arg2 10 | # depending on how they're defined in the ellipses_func() documentation. 11 | # Interestingly the usage for the paste function is as follows: 12 | # 13 | # paste (..., sep = " ", collapse = NULL) 14 | # 15 | # Notice that the ellipses is the first argument, and all other arguments after 16 | # the ellipses have default values. This is a strict rule in R programming: all 17 | # arguments after an ellipses must have default values. Take a look at the 18 | # simon_says function below: 19 | # 20 | # simon_says <- function(...){ 21 | # paste("Simon says:", ...) 22 | # } 23 | # 24 | # The simon_says function works just like the paste function, except the 25 | # begining of every string is prepended by the string "Simon says:" 26 | # 27 | # Telegrams used to be peppered with the words START and STOP in order to 28 | # demarcate the beginning and end of sentences. Write a function below called 29 | # telegram that formats sentences for telegrams. 30 | # For example the expression `telegram("Good", "morning")` should evaluate to: 31 | # "START Good morning STOP" 32 | 33 | telegram <- function(...){ 34 | paste("START", ..., "STOP") 35 | } -------------------------------------------------------------------------------- /Functions/scripts/telegram.R: -------------------------------------------------------------------------------- 1 | # The ellipses can be used to pass on arguments to other functions that are 2 | # used within the function you're writing. Usually a function that has the 3 | # ellipses as an argument has the ellipses as the last argument. The usage of 4 | # such a function would look like: 5 | # 6 | # ellipses_func(arg1, arg2 = TRUE, ...) 7 | # 8 | # In the above example arg1 has no default value, so a value must be provided 9 | # for arg1. arg2 has a default value, and other arguments can come after arg2 10 | # depending on how they're defined in the ellipses_func() documentation. 11 | # Interestingly the usage for the paste function is as follows: 12 | # 13 | # paste (..., sep = " ", collapse = NULL) 14 | # 15 | # Notice that the ellipses is the first argument, and all other arguments after 16 | # the ellipses have default values. This is a strict rule in R programming: all 17 | # arguments after an ellipses must have default values. Take a look at the 18 | # simon_says function below: 19 | # 20 | # simon_says <- function(...){ 21 | # paste("Simon says:", ...) 22 | # } 23 | # 24 | # The simon_says function works just like the paste function, except the 25 | # begining of every string is prepended by the string "Simon says:" 26 | # 27 | # Telegrams used to be peppered with the words START and STOP in order to 28 | # demarcate the beginning and end of sentences. Write a function below called 29 | # telegram that formats sentences for telegrams. 30 | # For example the expression `telegram("Good", "morning")` should evaluate to: 31 | # "START Good morning STOP" 32 | 33 | telegram <- function(...){ 34 | 35 | } -------------------------------------------------------------------------------- /MANIFEST: -------------------------------------------------------------------------------- 1 | Setting_Up_Swirl 2 | Functions 3 | Functional_Programming_with_purrr 4 | -------------------------------------------------------------------------------- /Setting_Up_Swirl/customTests.R: -------------------------------------------------------------------------------- 1 | # Get the swirl state 2 | getState <- function(){ 3 | # Whenever swirl is running, its callback is at the top of its call stack. 4 | # Swirl's state, named e, is stored in the environment of the callback. 5 | environment(sys.function(1))$e 6 | } 7 | 8 | # Get the value which a user either entered directly or was computed 9 | # by the command he or she entered. 10 | getVal <- function(){ 11 | getState()$val 12 | } 13 | 14 | # Get the last expression which the user entered at the R console. 15 | getExpr <- function(){ 16 | getState()$expr 17 | } 18 | 19 | coursera_on_demand <- function(){ 20 | selection <- getState()$val 21 | if(selection == "Yes"){ 22 | email <- readline("What is your email address? ") 23 | token <- readline("What is your assignment token? ") 24 | 25 | payload <- sprintf('{ 26 | "assignmentKey": "PL3Db49VEea2YhJ0DzyiSg", 27 | "submitterEmail": "%s", 28 | "secret": "%s", 29 | "parts": { 30 | "Vv9SG": { 31 | "output": "correct" 32 | }, 33 | "NGfmh": { 34 | "output": "incorrect" 35 | } 36 | } 37 | }', email, token) 38 | url <- 'https://www.coursera.org/api/onDemandProgrammingScriptSubmissions.v1' 39 | 40 | respone <- httr::POST(url, body = payload) 41 | if(respone$status_code >= 200 && respone$status_code < 300){ 42 | message("Grade submission succeeded!") 43 | } else { 44 | message("Grade submission failed.") 45 | message("Press ESC if you want to exit this lesson and you") 46 | message("want to try to submit your grade at a later time.") 47 | return(FALSE) 48 | } 49 | } else if(selection == "No"){ 50 | return(TRUE) 51 | } else { 52 | message("Submit the following code as the answer") 53 | message("to a quiz question on Coursera.\n") 54 | message("#########################\n") 55 | message(keygen(), "\n") 56 | message("#########################") 57 | return(TRUE) 58 | } 59 | } -------------------------------------------------------------------------------- /Setting_Up_Swirl/dependson.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/swirldev/Advanced_R_Programming/e66abb0aa434acc1d7742660e8f580c6734c1f7b/Setting_Up_Swirl/dependson.txt -------------------------------------------------------------------------------- /Setting_Up_Swirl/initLesson.R: -------------------------------------------------------------------------------- 1 | # Code placed in this file fill be executed every time the 2 | # lesson is started. Any variables created here will show up in 3 | # the user's working directory and thus be accessible to them 4 | # throughout the lesson. -------------------------------------------------------------------------------- /Setting_Up_Swirl/lesson.yaml: -------------------------------------------------------------------------------- 1 | - Class: meta 2 | Course: The R Programming Environment 3 | Lesson: Setting Up Swirl 4 | Author: Sean Kross 5 | Type: Standard 6 | Organization: The Johns Hopkins Data Science Lab 7 | Version: 2.4.2 8 | 9 | - Class: text 10 | Output: Welcome to the swirl component of The R Programming Environment course 11 | on Coursera. This will be a very short lesson designed to test swirl's 12 | connection to Coursera's servers. 13 | 14 | - Class: text 15 | Output: At the end of every lesson you will be given a choice to submit to 16 | Coursera or to have a code generated. If this test succeeds then you should 17 | continue to submit your progress to Coursera. However if this test fails 18 | you should always choose to have a code generated. 19 | 20 | - Class: text 21 | Output: Copy the generated code and then paste it into the quiz question on 22 | Coursera that corresponds to the lesson you're working on in swirl in 23 | order to get credit. 24 | 25 | - Class: text 26 | Output: Let's test submitting to Coursera now. In the next question choose 27 | Yes. If you are not able to connect, then you know that you should always 28 | ask for a code at the end of the lesson. If you are able to connect then 29 | you should be able to submit your progress to swirl easily in the future! 30 | 31 | - Class: mult_question 32 | Output: "Would you like to receive credit for completing this course on 33 | Coursera.org?" 34 | CorrectAnswer: NULL 35 | AnswerChoices: Yes;No 36 | AnswerTests: coursera_on_demand() 37 | Hint: "" 38 | 39 | 40 | --------------------------------------------------------------------------------