Values
Basic “things” in R (“scalars”):
Numeric values: 10, 3.14, 0.0002, 1.234e5, 3 + 4i
R distinguishes between integer and numeric / double but you don’t need to
Character values: "Baruch", "Michael Weylandt",
Arbitrary length - matched quotes (double or single)
Mix quotes to put quotes inside a string: "He said to me: 'Code is great!'"
Logical values: TRUE, FALSE (no quotes)
Values
Use the class() function to see types:
Variables and Assignment
We can assign a name to a value:
Now anywhere we use x, the value 3 automatically is introduced:
Variables and Assignment
Variable names must be:
One word (no spaces)
All alpha, numeric, or underscores
Start with a letter
Avoid special “reserved words”: if, else, for, etc
Variables and Assignment
Assignment (<-) is the last operation, so can use to save results for later use
five_factorial <- 5 * 4 * 3 * 2 * 1
five_factorial
Then
six_factorial <- 6 * five_factorial
six_factorial
Vectors
An ordered collection of the same type is called a vector :
Create with c (“concatenate”):
Vectors
Vectors are everywhere in R:
The “single” values we saw earlier are just vectors of length 1
Vectors
Access specific elements of a vector with []:
x <- c ("a" , "b" , "c" )
x[2 ]
Or give a vector of indices:
[1] "b" "a" "b" "a" "c" "c"
Vectors
Negative indices drop :
This is different from Python: not count backwards!
Functions
Functions take input (“arguments”) and produce results and side-effects:
x <- c (1 , 4 , 9 , 16 )
sqrt (x)
x is an input to the function sqrt
sqrt doesn’t “see” the name x; it sees the vector 1, 4, 9, 16
Not 100% true, but close enough!
Functions
Some examples:
Print to screen with some formatting: print
“Pure” print to screen (no formatting): cat
Combine strings: paste
Math: sin, sqrt
Load a package: library
Vectorization
Where possible, functions are vectorized :
x <- c (1 , 2 , 3 )
y <- c (4 , 5 , 6 )
x * y
Operations occur “in parallel” on matched elements
Control Flow
Two useful operations for small code snippets:
if (condition){
do_if_true
} else { # Optional - can omit this 'side'
do_if_false
}
This is a conditional operator:
Used to run code sometimes
Download a missing file, but not a file already present
Throw an error if something bad happens
Turn off parts of code with (if(FALSE){})
Everything between { and } is handled
else branch is optional
Compound Conditions
Can do ‘compound’ or nested if/else:
if (x > 10 ){
cat ("x is very positive." )
} else if (x > 0 ) {
cat ("x is a little positive. \n " )
} else {
cat ("x is negative. \n " )
}
Control Flow
Two useful operations for small code snippets:
for (element in vector){
process_one_at_a_time (element)
}
Goes through vector taking out one element at a time:
nums <- c (1 , 2 , 3 , 4 , 5 )
for (n in nums){
cat (n, "squared is" , n^ 2 , " \n " )
}
1 squared is 1
2 squared is 4
3 squared is 9
4 squared is 16
5 squared is 25
Don’t focus on these too much - better alternatives coming soon!
Control Flow
By default, the last line of a function is the returned value:
my_absolute_value <- function (x){
if (x > 0 ){
x
} else {
- x
}
}
my_absolute_value (- 3 )
Control Flow
Can override with return statement - instantly returns and ‘exits’ function:
say_hello <- function (name, scream= FALSE , quiet= FALSE ){
text <- paste ("Hello" , name)
if (scream){
text <- paste (toupper (text), "!!!" )
}
if (quiet){return (text)} # Stop here if quiet and skip print
print (text)
}
say_hello ("Michael" , scream= TRUE )
say_hello ("Michael" , quiet= TRUE )
Control Flow
Overly complicated \(\text{sign}(x)\) function:
sign <- function (x){
if (x > 0 ){
1
} else {
if (x < 0 ){
- 1
} else {
0
}
}
}
Control Flow
Somewhat better \(\text{sign}(x)\) function:
sign <- function (x){
if (x > 0 ){
1
} else if (x < 0 ){
- 1
} else {
0
}
}
Control Flow
Decent \(\text{sign}(x)\) function:
sign <- function (x){
if (x > 0 ) return (1 ) # Use 'return' to stop function here
if (x < 0 ) return (- 1 )
return (0 )
}
Would be even better to vectorize
Optional Review
Programming exercises to practice these concepts
Exercise #01
Q: Write a function f that does the following:
The vector has 3 elements and is of type numeric
The vector has 3 elements and is of type character
The vector has 5 elements and is of type integer
Hint : Use the cat function to print to screen.
f <- function (x){
cat ("The vector has" , length (x), "elements and is of type" , class (x))
}
Exercise #02
Q: Write a vectorized function to tell if numbers are even.
[1] FALSE TRUE FALSE TRUE FALSE TRUE FALSE TRUE FALSE TRUE
Hint : Use the %% operator to get remainders from division
is_even <- function (x) (x %% 2 ) == 0
Exercise #03
Q: Write a function to count the even elements of a vector:
Hint : Combine Q2 with the “sum of logical = count” trick.
count_even <- function (x) sum (is_even (x))
Exercise #04
Q: The seq() function lets us construct sequences. What is the average (mean) of the first 23 odd numbers?
Hint : Read the documentation for ?seq before trying this question
mean (seq (from= 1 , by= 2 , length.out= 23 ))
Exercise #05
Q: The alternating harmonic series is defined as:
\[1 - \frac{1}{2} + \frac{1}{3} - \frac{1}{4} + \frac{1}{5} + \dots\]
Show that this series converges to \(\ln(2)\) by taking a partial sum of the first one million elements.
Hint : Use recycling to get the signs right:
sum (1 / seq (1 , 1e6 ) * c (1 , - 1 ))
Compare to:
Exercise #06
Q: Write a function that computes the mean of a vector (Don’t use the built-in mean function)
Hint : Use the sum and length functions
my_mean <- function (x){
sum (x) / length (x)
}
my_mean (8 )
Exercise #07
Q: Write a vectorized function that returns \(\sqrt{x}\) if \(x\) is positive and 0 otherwise.
pos_sqrt (c (- 4 , - 1 , 1 , 4 , 9 , - 9 ))
Hint : The pmax (“parallel max”) function may be useful here:
x <- c (1 , 3 , 5 , 7 )
y <- c (5 , 3 , 10 , 1 )
pmax (x, y)
pos_sqrt <- function (x) sqrt (pmax (0 , x))
Alternative - use the ifelse function for vectorized conditionals (but this has a warning because it tries to do both conditions)
Exercise #08
Q: Write a function that takes in a vector of characters and returns the longest.
long_string (c ("a" , "bc" , "def" ))
long_string (c ("My" , "name" , "is" , "Michael" ))
Hint : The nchar and which.max functions may be helpful here.
long_string <- function (x) x[which.max (nchar (x))]
Exercise #09
Q: Write a function that computes the factorial of a value. (Don’t use the built-in factorial function)
Hint : Use the seq and prod functions
my_factorial <- function (n){
return (prod (seq (1 , n)))
}
my_factorial (8 )
Exercise #10
Q: Write a function that computes the factorial of a value using a loop (instead of the prod function).
my_factorial <- function (n){
fact <- 1
for (x in seq (1 , n)){
fact <- fact * x
}
return (fact)
}
my_factorial (8 )
Exercise #11
Q: Show that: \[\sum_{k=0}^{\infty} \frac{1}{k!} = e\]
Use the built-in factorial function since it is vectorized.
sum (1 / factorial (seq (0 , 10000 )))
Exercise #12
Q: Write a function that takes a vector and returns the maximum element. (Don’t use the built-in max function.)
Hint : You will need to use a loop and a conditional here.
Hint : We started factorial at 1; start max at -Inf (why?)
my_max <- function (x){
max_val <- - Inf
for (v in x){
if (v > max_val) max_val <- v
}
return (max_val)
}
my_max (c (1 , - 1 , 3 , - 4 , 10 , - 3 ))