forked from swirldev/swirl_courses
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
break ground on rprog alt version for email support
- Loading branch information
Showing
35 changed files
with
7,896 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,245 @@ | ||
- Class: meta | ||
Course: R Programming | ||
Lesson: Basic Building Blocks | ||
Author: Nick Carchedi | ||
Type: Standard | ||
Organization: JHU Biostat | ||
Version: 2.2.0 | ||
|
||
- Class: text | ||
Output: In this lesson, we will explore some basic building blocks of the R programming | ||
language. | ||
|
||
- Class: text | ||
Output: If at any point you'd like more information on a particular topic related | ||
to R, you can type help.start() at the prompt, which will open a menu of resources | ||
(either within RStudio or your default web browser, depending on your setup). | ||
Alternatively, a simple web search often yields the answer you're looking for. | ||
|
||
- Class: cmd_question | ||
Output: In its simplest form, R can be used as an interactive calculator. Type | ||
5 + 7 and press Enter. | ||
CorrectAnswer: 5 + 7 | ||
AnswerTests: omnitest(correctExpr='5 + 7') | ||
Hint: Type 5 + 7 and press Enter. | ||
|
||
- Class: text | ||
Output: R simply prints the result of 12 by default. However, R is a programming | ||
language and often the reason we use a programming language as opposed to a calculator | ||
is to automate some process or avoid unnecessary repetition. | ||
|
||
- Class: text | ||
Output: In this case, we may want to use our result from above in a second calculation. | ||
Instead of retyping 5 + 7 every time we need it, we can just create a new variable | ||
that stores the result. | ||
|
||
- Class: text | ||
Output: 'The way you assign a value to a variable in R is by using the assignment | ||
operator, which is just a ''less than'' symbol followed by a ''minus'' sign. It | ||
looks like this: <-' | ||
|
||
- Class: text | ||
Output: Think of the assignment operator as an arrow. You are assigning the value | ||
on the right side of the arrow to the variable name on the left side of the arrow. | ||
|
||
- Class: cmd_question | ||
Output: To assign the result of 5 + 7 to a new variable called x, you type x <- | ||
5 + 7. This can be read as 'x gets 5 plus 7'. Give it a try now. | ||
CorrectAnswer: x <- 5 + 7 | ||
AnswerTests: any_of_exprs('x <- 5 + 7', 'x <- 7 + 5') | ||
Hint: Type x <- 5 + 7. It's important to include a single space on each side of | ||
the assignment operator, but do NOT put a space between the `<` and the `-` that | ||
form the arrow. | ||
|
||
- Class: text | ||
Output: You'll notice that R did not print the result of 12 this time. When you | ||
use the assignment operator, R assumes that you don't want to see the result immediately, | ||
but rather that you intend to use the result for something else later on. | ||
|
||
- Class: cmd_question | ||
Output: To view the contents of the variable x, just type x and press Enter. Try | ||
it now. | ||
CorrectAnswer: x | ||
AnswerTests: omnitest(correctExpr='x') | ||
Hint: Type x and press Enter. This will automatically print the value of x. | ||
|
||
- Class: cmd_question | ||
Output: Now, store the result of x - 3 in a new variable called y. | ||
CorrectAnswer: y <- x - 3 | ||
AnswerTests: omnitest(correctExpr='y <- x - 3') | ||
Hint: Type y <- x - 3 and press Enter. Whether you use x - 3 or x-3 is personal | ||
preference, but it's good habit to include a space on either side of the assignment | ||
operator. | ||
|
||
- Class: cmd_question | ||
Output: What is the value of y? Type y to find out. | ||
CorrectAnswer: 'y' | ||
AnswerTests: omnitest(correctExpr='y') | ||
Hint: Type y and press Enter. | ||
|
||
- Class: text | ||
Output: Now, let's create a small collection of numbers called a vector. Any object | ||
that contains data is called a data structure and numeric vectors are the simplest | ||
type of data structure in R. In fact, even a single number is considered a vector | ||
of length one. | ||
|
||
- Class: cmd_question | ||
Output: The easiest way to create a vector is with the c() function, which stands | ||
for 'concatenate' or 'combine'. To create a vector containing the numbers 1.1, | ||
9, and 3.14, type c(1.1, 9, 3.14). Try it now and store the result in a variable | ||
called z. | ||
CorrectAnswer: z <- c(1.1, 9, 3.14) | ||
AnswerTests: omnitest(correctExpr='z <- c(1.1, 9, 3.14)') | ||
Hint: Inputting z <- c(1.1, 9, 3.14) will assign the vector (1.1, 9, 3.14) to a | ||
new variable called z. Including single spaces after the commas in the vector | ||
is not required, but helps make your code less cluttered and more readable. | ||
|
||
- Class: cmd_question | ||
Output: Anytime you have questions about a particular function, you can access R's | ||
built-in help files via the `?` command. For example, if you want more information | ||
on the c() function, type ?c without the parentheses that normally follow a function | ||
name. Give it a try. | ||
CorrectAnswer: ?c | ||
AnswerTests: omnitest(correctExpr='?c') | ||
Hint: Type ?c and press Enter. This will bring up the help file for the c() function. | ||
|
||
- Class: cmd_question | ||
Output: Type z to view its contents. Notice that there are no commas separating | ||
the values in the output. | ||
CorrectAnswer: z | ||
AnswerTests: omnitest(correctExpr='z') | ||
Hint: Type z and press Enter to view its contents. | ||
|
||
- Class: cmd_question | ||
Output: You can combine vectors to make a new vector. Create a new vector that contains | ||
z, 555, then z again in that order. Don't assign this vector to a new variable, | ||
so that we can just see the result immediately. | ||
CorrectAnswer: c(z, 555, z) | ||
AnswerTests: omnitest(correctExpr='c(z, 555, z)') | ||
Hint: Type c(z, 555, z). Don't create a new variable. We just want to view the result. | ||
|
||
- Class: cmd_question | ||
Output: 'Numeric vectors can be used in arithmetic expressions. Type the following | ||
to see what happens: z * 2 + 100.' | ||
CorrectAnswer: z * 2 + 100 | ||
AnswerTests: omnitest(correctExpr='z * 2 + 100') | ||
Hint: Enter z * 2 + 100, without assigning the result to a variable. The `*` symbol | ||
is used for multiplication and shares a key with the number 8 on many keyboards. | ||
|
||
- Class: text | ||
Output: First, R multiplied each of the three elements in z by 2. Then it added | ||
100 to each element to get the result you see above. | ||
|
||
- Class: text | ||
Output: Other common arithmetic operators are `+`, `-`, `/`, and `^` (where x^2 | ||
means 'x squared'). To take the square root, use the sqrt() function and to take | ||
the absolute value, use the abs() function. | ||
|
||
- Class: cmd_question | ||
Output: Take the square root of z - 1 and assign it to a new variable called my_sqrt. | ||
CorrectAnswer: my_sqrt <- sqrt(z - 1) | ||
AnswerTests: omnitest(correctExpr='my_sqrt <- sqrt(z - 1)') | ||
Hint: Assign the result of sqrt(z - 1) to a variable called my_sqrt. | ||
|
||
- Class: mult_question | ||
Output: Before we view the contents of the my_sqrt variable, what do you think it | ||
contains? | ||
CorrectAnswer: a vector of length 3 | ||
AnswerChoices: a vector of length 3; a single number (i.e a vector of length 1); | ||
a vector of length 0 (i.e. an empty vector) | ||
AnswerTests: omnitest(correctVal='a vector of length 3') | ||
Hint: 'Think about how R handled the other ''vectorized'' operations: element-by-element.' | ||
|
||
- Class: cmd_question | ||
Output: Print the contents of my_sqrt. | ||
CorrectAnswer: my_sqrt | ||
AnswerTests: omnitest(correctExpr='my_sqrt') | ||
Hint: Just type my_sqrt and press Enter to view its value. | ||
|
||
- Class: text | ||
Output: As you may have guessed, R first subtracted 1 from each element of z, then | ||
took the square root of each element. This leaves you with a vector of the same | ||
length as the original vector z. | ||
|
||
- Class: cmd_question | ||
Output: Now, create a new variable called my_div that gets the value of z divided | ||
by my_sqrt. | ||
CorrectAnswer: my_div <- z / my_sqrt | ||
AnswerTests: omnitest(correctExpr='my_div <- z / my_sqrt') | ||
Hint: Enter my_div <- z / my_sqrt. The spaces on either side of the `/` sign are not | ||
required, but can often improve readability by making code appear less cluttered. | ||
In the end, it's personal preference. | ||
|
||
- Class: mult_question | ||
Output: Which statement do you think is true? | ||
CorrectAnswer: The first element of my_div is equal to the first element of z divided | ||
by the first element of my_sqrt, and so on... | ||
AnswerChoices: The first element of my_div is equal to the first element of z divided | ||
by the first element of my_sqrt, and so on...; my_div is a single number (i.e a | ||
vector of length 1); my_div is undefined | ||
AnswerTests: omnitest(correctVal='The first element of my_div is equal to the first | ||
element of z divided by the first element of my_sqrt, and so on...') | ||
Hint: Think about how R handled the other 'vectorized' operations like `+` and `*`. | ||
|
||
- Class: cmd_question | ||
Output: Go ahead and print the contents of my_div. | ||
CorrectAnswer: my_div | ||
AnswerTests: omnitest(correctExpr='my_div') | ||
Hint: Type my_div and press Enter to see its contents. | ||
|
||
- Class: text | ||
Output: When given two vectors of the same length, R simply performs the specified | ||
arithmetic operation (`+`, `-`, `*`, etc.) element-by-element. If the vectors | ||
are of different lengths, R 'recycles' the shorter vector until it is the same | ||
length as the longer vector. | ||
|
||
- Class: text | ||
Output: When we did z * 2 + 100 in our earlier example, z was a vector of length | ||
3, but technically 2 and 100 are each vectors of length 1. | ||
|
||
- Class: text | ||
Output: 'Behind the scenes, R is ''recycling'' the 2 to make a vector of 2s and | ||
the 100 to make a vector of 100s. In other words, when you ask R to compute z | ||
* 2 + 100, what it really computes is this: z * c(2, 2, 2) + c(100, 100, 100).' | ||
|
||
- Class: cmd_question | ||
Output: To see another example of how this vector 'recycling' works, try adding | ||
c(1, 2, 3, 4) and c(0, 10). Don't worry about saving the result in a new variable. | ||
CorrectAnswer: c(1, 2, 3, 4) + c(0, 10) | ||
AnswerTests: omnitest(correctExpr='c(1, 2, 3, 4) + c(0, 10)') | ||
Hint: Enter c(1, 2, 3, 4) + c(0, 10) in the console to see how R adds two vectors | ||
of different length. Don't assign the result to a variable. | ||
|
||
- Class: text | ||
Output: If the length of the shorter vector does not divide evenly into the length | ||
of the longer vector, R will still apply the 'recycling' method, but will throw | ||
a warning to let you know something fishy might be going on. | ||
|
||
- Class: cmd_question | ||
Output: Try c(1, 2, 3, 4) + c(0, 10, 100) for an example. | ||
CorrectAnswer: c(1, 2, 3, 4) + c(0, 10, 100) | ||
AnswerTests: omnitest(correctExpr='c(1, 2, 3, 4) + c(0, 10, 100)') | ||
Hint: Type c(1, 2, 3, 4) + c(0, 10, 100) to see how R handles adding two vectors, | ||
when the shorter vector's length does not divide evenly into the longer vector's | ||
length. Don't worry about assigning the result to a variable. | ||
|
||
- Class: text | ||
Output: Before concluding this lesson, I'd like to show you a couple of time-saving tricks. | ||
|
||
- Class: text | ||
Output: Earlier in the lesson, you computed z * 2 + 100. Let's pretend that you made a mistake and that you meant to add 1000 instead of 100. You could either re-type the expression, or... | ||
|
||
- Class: cmd_question | ||
Output: In many programming environments, the up arrow will cycle through previous commands. Try hitting the up arrow on your keyboard until you get to this command (z * 2 + 100), then change 100 to 1000 and hit Enter. If the up arrow doesn't work for you, just type the corrected command. | ||
CorrectAnswer: z * 2 + 1000 | ||
AnswerTests: omnitest(correctExpr='z * 2 + 1000') | ||
Hint: If your environment does not support the up arrow feature, then just type the corrected command to move on. | ||
|
||
- Class: text | ||
Output: Finally, let's pretend you'd like to view the contents of a variable that you created earlier, but you can't seem to remember if you named it my_div or myDiv. You could try both and see what works, or... | ||
|
||
- Class: cmd_question | ||
Output: You can type the first two letters of the variable name, then hit the Tab key (possibly more than once). Most programming environments will provide a list of variables that you've created that begin with 'my'. This is called auto-completion and can be quite handy when you have many variables in your workspace. Give it a try. (If auto-completion doesn't work for you, just type my_div and press Enter.) | ||
CorrectAnswer: my_div | ||
AnswerTests: omnitest(correctExpr='my_div') | ||
Hint: If your programming environment doesn't support auto-completion, just type my_div and hit Enter to move on. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
# Put custom tests in this file. | ||
|
||
# Uncommenting the following line of code will disable | ||
# auto-detection of new variables and thus prevent swirl from | ||
# repeating execution of printing and plotting commands. | ||
|
||
# AUTO_DETECT_NEWVAR <- FALSE | ||
|
||
match_call <- function(correct_call = NULL) { | ||
e <- get("e", parent.frame()) | ||
# Trivial case | ||
if(is.null(correct_call)) return(TRUE) | ||
# Get full correct call | ||
full_correct_call <- expand_call(correct_call) | ||
# Expand user's expression | ||
expr <- deparse(e$expr) | ||
full_user_expr <- expand_call(expr) | ||
# Compare function calls with full arg names | ||
identical(full_correct_call, full_user_expr) | ||
} | ||
|
||
# Utility function for match_call answer test | ||
# Fills out a function call with full argument names | ||
expand_call <- function(call_string) { | ||
# Quote expression | ||
qcall <- parse(text=call_string)[[1]] | ||
# If expression is not greater than length 1... | ||
if(length(qcall) <= 1) return(qcall) | ||
# See if it's an assignment | ||
is_assign <- is(qcall, "<-") | ||
# If assignment, process righthandside | ||
if(is_assign) { | ||
# Get righthand side | ||
rhs <- qcall[[3]] | ||
# Get function from function name | ||
fun <- match.fun(rhs[[1]]) | ||
# match.call() does not support primitive functions | ||
if(is.primitive(fun)) return(qcall) | ||
# Get expanded call | ||
full_rhs <- match.call(fun, rhs) | ||
# Full call | ||
qcall[[3]] <- full_rhs | ||
} else { # If not assignment, process whole thing | ||
# Get function from function name | ||
fun <- match.fun(qcall[[1]]) | ||
# match.call() does not support primitive functions | ||
if(is.primitive(fun)) return(qcall) | ||
# Full call | ||
qcall <- match.call(fun, qcall) | ||
} | ||
# Return expanded function call | ||
qcall | ||
} |
Oops, something went wrong.