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:
function_name(arguments) {...}
\(arguments) {``...``}
Optional arguments can be declared in the following way:
function_name(argument1, argument2_name = argument2)sqrt(six)
## [1] 2.44949
To check the manual on given function
?sqrt
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