Download RMarkdown file

Basic operations

Four elementary operations: -, +, *, and /

2 + 3
## [1] 5
2 * 3
## [1] 6

Beware of the order according to mathematical rules

2 + 2 * 3
## [1] 8

is not the same as

(2 + 2) * 3
## [1] 12

Assignment operator: object_name <- object_contents

four <- 2 + 2
four
## [1] 4

The value can be updated

four <- four + 1
four
## [1] 5

or be assigned to a new variable

six <- four + 1
six
## [1] 6

The assignment can be done with different types

hello <- "hi"
hello
## [1] "hi"

however, you need to be careful: do not to forget quotes when declaring a new character variable

hello <- hi
## Error in eval(expr, envir, enclos): object 'hi' not found

or do not sum oranges and apples

hello + six
## Error in hello + six: non-numeric argument to binary operator

Special values in R include: TRUE, FALSE, NA, and NULL. TRUE and FALSE can be shortcut with T and F, respectively.

An R function: takes input(s) -> performs action(s) with the input(s) -> produces output. Functions can be defined in two ways:

Optional arguments can be declared in the following way:

sqrt(six)
## [1] 2.44949

To check the manual on given function

?sqrt

Task 1: create columns of heights and weights

Generate 10 randomly distributed values:

rnorm(10, mean=0, sd=1)
##  [1] -1.10981214 -0.08046997  0.89192013 -0.47616078  0.16893506  0.43395159
##  [7]  1.29614587  0.11571502  0.62179435  1.48932521

Suppose we identify the range of BMIs as the one with the mean 22 and standard deviation (SD) 2

bmi_mean <- 22.0
bmi_sd <- 2.0

While heights are normally distributed with the mean 170 cm and SD 20 cm

generate_heights = \(n, mean_height, sd_height) {
  rnorm(n, mean_height, sd_height)
}
(cohort <- generate_heights(100, 170, 20))
##   [1] 190.9436 212.7006 193.7911 190.5387 192.1663 174.7653 162.9202 180.4062
##   [9] 173.3551 172.5341 154.9083 188.2076 191.4947 179.3254 170.2149 169.3631
##  [17] 161.7553 161.8240 169.4751 195.4938 161.7097 196.4338 165.6924 172.6685
##  [25] 181.8979 152.2038 118.5496 144.2531 182.2086 144.0797 163.1300 193.4160
##  [33] 155.2885 174.7740 179.0590 184.3504 186.8569 189.4040 159.9947 162.0093
##  [41] 200.9551 157.3379 203.1100 141.6345 180.3013 154.1453 165.6398 169.8366
##  [49] 164.6866 144.1644 182.4280 184.3301 165.1185 147.7014 184.4587 187.8846
##  [57] 208.1769 177.4183 191.3891 182.4402 169.4355 173.6870 166.1910 158.0807
##  [65] 231.3196 165.0004 151.2883 184.3529 185.0045 146.2439 157.0499 171.6436
##  [73] 172.9844 175.5709 169.8199 146.3143 183.0455 185.6896 150.8915 192.2298
##  [81] 171.1042 152.3997 159.8315 168.6579 195.4881 194.1492 165.2834 140.3463
##  [89] 163.1024 178.0314 175.0218 144.0922 202.4935 141.6400 191.2959 163.8037
##  [97] 151.7444 185.4735 202.2356 192.8023

Note that if I embed the expression in the parenthesis, R will automatically printout the output.

We can quickly display the histogram of the heights in our cohort

hist(cohort)

One of the key components of R is data frame

df <- as.data.frame(cohort)
tail(df, 10)
df$dummy <- 1
head(df)

Let’s create a new column with IDs from 1 to the number of rows in our data frame

df$ID <- 1:nrow(df)
head(df)

Now we create a column with BMIs

df$bmi <- rnorm(nrow(df), mean = 22, sd = 2)
head(df)

We know that bmi = weight / square(height), so that weight = square(height) * bmi, where the height is in meters

We will use the package dplyr, specially designed to work with data frames

library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union

It allows to use native pipes |>

cm_in_one_meter = 100
df |>
  # rename the column cohort to height
  rename(height = cohort) |> 
  # drop the column dummy
  select(-dummy) |> 
  # we can either reorder the columns by citing all of them
  select(ID, height, bmi) |> 
  # or we can simply write that IDs should be first
  select(ID, everything()) |> 
  # create a column weight based on bmi and height
  # !! denotes an external variable respectively to the data frame
  # + reassign the outcome to a new variable df1
  mutate(weight = bmi * (height / !!cm_in_one_meter)^2) -> df1 

df1
hist(df1$weight)

Suppose that BMIs are linearly distributed according to the age between bmi(age=12) = 18 and bmi(age=30)=22 with the error sigma=0.5

generate_BMI <- \(ages, age0 = 12, bmi0 = 18, age1 = 30, bmi1 = 22, sigma=0.5) {
  bmi0 + (ages - age0) * (bmi1 - bmi0) / (age1 - age0) + rnorm(1, 0, sigma)
}
generate_BMI(c(20,25))
## [1] 20.36331 21.47442

Now let’s create a column of BMIs based on this function

df2 <- df1
df2$age <- runif(nrow(df2), 18, 40) # create a column of ages
df2 |> mutate(bmi = generate_BMI(age), weight = bmi * (height / 100)^2) -> df2
df2

Here we can double check that indeed the bmi is linearly distributed by the age using linear regression model lm

lm(bmi ~ age, data = df2)
## 
## Call:
## lm(formula = bmi ~ age, data = df2)
## 
## Coefficients:
## (Intercept)          age  
##     15.3236       0.2222

or in order to better interpret the intercept

lm(bmi ~ age_relative, data = df2 |> mutate(age_relative = age - 12))
## 
## Call:
## lm(formula = bmi ~ age_relative, data = mutate(df2, age_relative = age - 
##     12))
## 
## Coefficients:
##  (Intercept)  age_relative  
##      17.9903        0.2222

as you can see the intercept is close to 18, which means bmi(age_relative = age - 12 = 0) = 18

lm(weight ~ age_relative, data = df2 |> mutate(age_relative = age - 12))
## 
## Call:
## lm(formula = weight ~ age_relative, data = mutate(df2, age_relative = age - 
##     12))
## 
## Coefficients:
##  (Intercept)  age_relative  
##       48.646         1.043

which is indeed close to what we could expect

18 * (170 / 100) ^ 2
## [1] 52.02