---
title: "Introduktion til R"
author: "The ASTA team"
# output: html_document
output:
  learnr::tutorial:
    progressive: true
    allow_skip: true
runtime: shiny_prerendered
description: "This tutorial introduces some of the most basic R syntax, and it scratches the surface of the mosaic package. The intention of the tutorial merely is to give students (who might never have touched programming before) a chance to see some R, such that it doesn't feel to intimidating at course start where they also have a lot of other new things to learn. The tutorial assumes that the actual course is also going to introduce R."
---

```{r setup, include=FALSE}
## BEWARE: Package `gradethis` is silently assumed below. It must be installed from GitHub.
knitr::opts_chunk$set(echo = TRUE)
inst_pkg <- installed.packages()[,"Package"]
if(!("mosaic" %in% inst_pkg)){
  install.packages("mosaic", repos = "https://cloud.r-project.org")
}
if(!("palmerpenguins" %in% inst_pkg)){
  install.packages("palmerpenguins", repos = "https://cloud.r-project.org")
}
library(mosaic)
library(palmerpenguins)
library(learnr)
tutorial_options(exercise.timelimit = 5)
if(require(gradethis)){
  gradethis::gradethis_setup()
}
```


## Vejledningens formål

I denne vejledning gennemgår vi lidt flere detaljer om R, og det er ikke strengt nødvendigt at gennemgå dette.
Det er tænkt som ekstra materiale til dem der gerne vil forstå R lidt bedre og det er rigtig god træning i forskellige R-kommandoer og tankegange.

Det antages her at man har gennemgået den introducerende tutorial før man starter på nærværende tutorial.

Denne tutorial har fokus på R objekter. 
Alt vi arbejder med i R kaldes objekter, men der er forskellige typer og klasser af objekter. 
Disse programmeringstekniske begreber vil vi ikke uddybe yderliger. 
Det er dog godt at være opmærksom på mulighederne og begrænsningerne for de objekter, man gemmer sit data i.

## Dataeksempel: Pingviner

Vi bruger datasættet `penguins` fra pakken `palmerpenguins` som eksempel.
Vi gemmer datasættet med navnet `pingviner` og ser starten af datasættet:
```{r pingviner}
pingviner <- palmerpenguins::penguins
head(pingviner)
```

```{r echo=FALSE}
pingviner <- palmerpenguins::penguins
```

## Vektorer
Vi kan oprette vektorer på flere måder, og en vektor kan bestå af **enten** decimaltal, af heltal eller sågar af tekst:
```{r}
v <- c(5.4, 3, 7/5)
typeof(v)
x <- 3:11
typeof(x)
fruits <- c("mango", "pineapple", "banana")
typeof(fruits)
```
I funktionen `c()` står c'et for *combine*, men bemærk at et enkelt tal også betragtes som en vektor - altså en vektor med ét element.

Vi kan *ikke* både have heltal og decimaltal i samme vektor og ej heller både tekst og tal. Forsøger vi dette vil R automatisk konvertere hele vektoren til decimaltal hhv. tekst.
```{r autovektorkonvertering}
(v2 <- c(v, x))
typeof(v2)
(v3 <- c(v, fruits))
typeof(v3)
```
Bemærk: Når vi tildeler en værdi til et objekt, f.eks. `x <- 3:11`, så printes værdien af objektet ikke umiddelbart på vores skærm, men vi kan få objektets værdi/indhold at se ved at sætte et parantes om linjen - altså ved f.eks. at skrive `(x <- 3:11)`.

```{r bogstavvektor, echo=FALSE}
question("Hvilken type vektor vil vi få ud ved at skrive `c('1', '2', '3')`",
  answer("En tekstvektor (`character` i R-sprog)", correct = TRUE, message = "Korrekt! Tal i apostrof eller anførselstegn opfattes som tekst."),
  answer("En heltalsvektor (`integer` i R-sprog).", message = "Tal i apostrof eller anførselstegn opfattes som tekst."),
  answer("En decimaltalsvektor (`double` i R-sprog)", message = "Tal i apostrof eller anførselstegn opfattes som tekst."), allow_retry = TRUE
)
```

## Vektorindgange
Når vi har oprettet en vektor, kan vi tilgå dens elementer på flere måder:
```{r elementudvaelgelse}
# Vi oprettede tidligere vektoren x med følgende elementer:
print(x)
# Herunder er seks måder, hvormed man kan udvælge elementer fra x
# Vi udvælger element nummer 2
x[2]
# Vi udvælger alle elementer pånær nummer 2
x[-2]
# Vi udvælger element nummer 3, 4, 5, 6 og 7
x[3:7]
# Vi udvælger element nummer 5 og 9
x[c(5,9)]
# Vi udvælger alle elementer pånær element nummer 5 og 9
x[-c(5,9)]
# Vi udvælger alle elementer i x, der er lig med 5
x[x == 5]
```
I det sidste eksempel ovenfor brugte vi den logiske operator `==` til at udvælge alle elementer i `x`, der er lig med 5. Der findes også andre logiske operatorer, bl.a. `<`, `<=`, `>`, `>=`. Brug en af disse til at udvælge elementerne `r x[x < 10]` fra vektoren `x`.
```{r vaelg_x, exercise=TRUE}
# Vi definerer x igen for en sikkerheds skyld:
x <- 3:11
# Udvælg de ovenfor angivne elementer fra x:

```
<div id="vaelg_x-hint">
**Tip:** Opgaven løses nemmest med `<` eller `<=`.
</div>
```{r vaelg_x-check}
# FIXME: Opgaven burde kunne løses med både x[x < 10] og x[x <= 9], men det er
# ikke pt. tilfældet, da kun x[x < 10] godtages. Burde nedenstående kode ikke
# kun teste resultaterne mod hinanden? (det kan jo ikke være det, der sker, når
# nu x[x <= 9] ikke godtages)
# Jeg har nu fjernet solution-chunken, der angav x[x < 10] som svar. Måske det
# løser problemet, så denne check-chunk nu får magten...
x <- 3:11
grade_result(
  pass_if(~identical(.result, x[x < 10]))
)
```


## Logiske vektorer
I R opfattes `TRUE` og `FALSE` samt `T` og `F` som såkaldte logiske værdier (`T` og `F` er blot forkortelser for `TRUE` og `FALSE`) og er således af typen `logical`.
Opstiller man et udsagn i R, vil man som resultat få den logiske vektor, der udgør sandhedsværdien for udsagnet:
```{r vektorlogik}
# Vi oprettede tidligere vektoren x med følgende elementer:
print(x)
# Vi spørger hvilke elementer i x, der er lig 10
x == 10
# Findes elementerne 1 hhv. 8 i x?
c(1, 8) %in% x
# Hvilke elementer i x er større end eller lig med 7?
x >= 7
# Man kan negere et udsagn med et udråbstegn !
# En negering vender så at sige sandhedsværdierne om
# Hvilke elementer i x er IKKE større end eller lig med 7?
!(x >= 7)
# Vi kan sammensætte udsagn med | (læs: ELLER) samt med & (læs: OG)
# x mindre end 4 eller x større end eller lig 8?
x < 4 | x >= 8
# x større end 5 og x mindre end 9?
x > 5 & x < 9
```
```{r logikudvaelgelse, echo=FALSE}
question("Man benytter ofte logiske vektorer uden at tænke over det. Kan du komme i tanke om et eksempel?",
  answer("Der ligger en masse logik til grund for denne vejledning, så computeren regner hele tiden på logiske vektorer.", message = "Tip: Du har brugt en logisk vektor i vejledningens forrige opgave."),
  answer("Til at udvælge elementer i vektorer", correct = TRUE, message = "Korrekt! Bemærk at vi faktisk brugte en logisk vektor, da vi tidligere udvalgte alle vektorelementer, der var mindre end 10, dvs. da vi skrev `x[x < 10]` (eller `x[x <= 9]`)"),
  answer("Når man læser eller hører diverse udtalelser i forskellige nyhedsmedier, så kan man med logik afgøre, om en udtalelse er logisk sammenhængende.", message = "Tip: Du har brugt en logisk vektor i vejledningens forrige opgave."), allow_retry = TRUE
)
```


## Lister
Hvor en vektor kun kan indeholde **enten** decimaltal, heltal eller tekst, så er lister mere fleksible. Elementerne i en liste kan være forskellige typer af objekter:
```{r liste}
# Vi opretter en matrix
M <- matrix(seq(from=2, by=3, length.out = 4), nrow = 2)
# Vi kommer nogle af vores tidligere oprettede objekter ind i to lister
(L1 <- list(v, fruits))
(L2 <- list(M, x))
# Man kan sågar have lister i lister
(L <- list(L1, L2))
```
Syntaksen for at tilgå elementer i en liste er lidt anderledes end for vektorer, da man skriver to sæt kantede paranteser:
```{r listeelement}
# Vi udtager text-vektoren fruits fra listen L2
L1[[2]]
# Vi udtager elementet "banana" fra tekst-vektoren i liste L2
L1[[2]][3]
```
Udtag elementet `r M[1,2]` fra matricen `M` i listen `L2` i listen `L`:
```{r listeudvaelg, exercise=TRUE, eval=FALSE}
# Indtast den nødvendige kode for at udtage ovennævnte element:
```
<div id="listeudvaelg-hint">
**Tip:** Hold tungen lige i munden og tænk over, hvad du ville skrive, hvis du skulle udvælge én ting af gangen. Hvordan vil du udvælge `L2` fra `L`? Hvordan vil du udvælge `M` fra `L2`? Et element i en matrix udvælges med syntaksen `M[i,j]`, hvor `i` er rækkenummeret og `j` er søjlenummeret.
</div>
```{r listeudvaelg-solution}
L[[2]][[1]][1,2]
```
```{r listeudvaelg-code-check}
grade_this_code()
```


## Dataframes
Når vi læser vores data ind i R, gemmer vi det i en `dataframe`, hvilket er en særlig type liste, hvor alle elementer har samme længde, og hver især har et navn tilknyttet. Dette betyder, at vi kan stille elementerne i vores `dataframe` op i søjler ved siden af hinanden, hvor hver søjle vil have lige mange rækker (samt have sit eget navn). Søjlerne i en `dataframe` kalder vi for variable.
Typisk vil vi gerne sætte vores `dataframe` op, så hver række svarer til en observation, mens søjlerne er de egenskaber (variable), vi måler på (f.eks. højde, vægt, køn).
Da hver søjle (variabel) har tilknyttet sit eget navn, så kan vi tilgå elementerne (variablene) på en mere intuitiv måde:
Vi indlæste tidligere datasættet `penguins` fra pakken `palmerpenguins`, og da vi brugte funktionen `head()`, så vi at det bestod af variablene `species`, `island`, `bill_length_mm`, `bill_depth_mm`, `flipper_length_mm`, `body_mass_g`, `sex`, `year`.
Hvis vi har gemt dette datasæt som `pingviner`, så kan vi f.eks. udvælge variablen `island` med følgende syntaks:
```{r dataframe-display, eval=FALSE}
pingviner$island
```
```{r dataframe-run, echo=FALSE}
head(pingviner$island, n = 35)
```

Brug funktionen `mean()` samt hvad du har lært indtil nu til at udregne den gennemsnitlige kropsmasse for pingvinarten `Chinstrap`:
```{r pingvinmasse, exercise=TRUE, exercise.setup="pingviner"}
# Udregn den gennemsnitlige kropsmasse for pingvinarten Chinstrap:
```
<div id="pingvinmasse-hint">
**Tip:** Udvælg variablen `species` og brug hvad du har lært om logiske vektorer til at spørge efter arten `Chinstrap`. Dette kan nu bruges til at udvælge de relevante elementer fra variablen `body_mass_g`.
</div>
```{r pingvinmasse-solution}
mean(pingviner$body_mass_g[pingviner$species == 'Chinstrap'])
```
```{r pingvinmasse-check}
grade_result(
  pass_if(~identical(.result, mean(pingviner$body_mass_g[pingviner$species == 'Chinstrap'])))
)
```

Dette kan på elegant vis gøres for alle arterne på én gang med koden:
```{r pingvinmasse_all}
dplyr::group_by(pingviner, species) %>%
  dplyr::summarize(mean_mass = mean(body_mass_g, na.rm = TRUE))
```
Bliv ikke frustreret, hvis du ikke forstår disse to linjers kode - det er ikke forventeligt på nuværende, men man kan lære om det i bogen https://r4ds.had.co.nz/transform.html#grouped-summaries-with-summarise
