Part 1: R Basics - Getting StartedTeil 1: R Grundlagen - Los geht’s

Welcome to R! In this section, you’ll learn the fundamental building blocks of R programming. Take your time with each exercise - understanding these basics thoroughly will make everything else easier.

How to use these exercises:

  • Replace each ____ with the correct code
  • Run each chunk to see if it works
  • Read the hints if you get stuck

Willkommen bei R! In diesem Abschnitt lernst du die grundlegenden Bausteine der R-Programmierung. Nimm dir Zeit für jede Übung - wenn du diese Grundlagen gut verstehst, wird alles andere einfacher.

So verwendest du diese Übungen:

  • Ersetze jedes ____ mit dem richtigen Code
  • Führe jeden Chunk aus um zu sehen ob er funktioniert
  • Lies die Hinweise wenn du nicht weiterkommst

Exercise 1: Your First VariablesÜbung 1: Deine ersten Variablen

Concept: Variables are containers that store values. In R, we use <- to assign values to variables.

Konzept: Variablen sind Behälter, die Werte speichern. In R benutzen wir <- um Werte zuzuweisen.

1a: Creating simple variables1a: Einfache Variablen erstellen

# Store the number 42 in a variable called "answer"
# Speichere die Zahl 42 in einer Variable namens "answer"
answer <- ____
print(answer)

# Store your age in a variable
# Speichere dein Alter in einer Variable
my_age <- ____
print(my_age)

# Store a decimal number (height in meters)
# Speichere eine Dezimalzahl (Größe in Metern)
my_height <- ____
print(my_height)

1b: Text variables (strings)1b: Text-Variablen (Strings)

# Text variables - use quotes!
# Text-Variablen - benutze Anführungszeichen!

# Store your name (text needs quotes)
# Speichere deinen Namen (Text braucht Anführungszeichen)
my_name <- "____"
print(my_name)

# Store a species name
# Speichere einen Artnamen
species <- "____"
print(species)

1c: Logical (TRUE/FALSE) variables1c: Logische (TRUE/FALSE) Variablen

# Logical variables - TRUE or FALSE
# Logische Variablen - TRUE oder FALSE

# Is it raining? (answer TRUE or FALSE, no quotes!)
# Regnet es? (antworte TRUE oder FALSE, keine Anführungszeichen!)
is_raining <- ____

# Is 5 greater than 3? (R can calculate this!)
# Ist 5 größer als 3? (R kann das berechnen!)
five_greater_three <- 5 > 3
print(five_greater_three)

# Is 10 equal to 10? (use == for comparison)
# Ist 10 gleich 10? (benutze == für Vergleich)
ten_equals_ten <- 10 ____ 10
print(ten_equals_ten)

# Is "oak" equal to "Oak"? (R is case-sensitive!)
# Ist "oak" gleich "Oak"? (R unterscheidet Groß/Kleinschreibung!)
oak_equals_Oak <- "oak" == "Oak"
print(oak_equals_Oak)

1d: Basic math with variables1d: Grundrechenarten mit Variablen

# Create two number variables
# Erstelle zwei Zahlen-Variablen
a <- 10
b <- 3

# Addition
sum_ab <- a ____ b
print(sum_ab)  # Should be 13 / Sollte 13 sein

# Subtraction / Subtraktion
diff_ab <- a ____ b
print(diff_ab)  # Should be 7 / Sollte 7 sein

# Multiplication / Multiplikation
prod_ab <- a ____ b
print(prod_ab)  # Should be 30 / Sollte 30 sein

# Division
div_ab <- a ____ b
print(div_ab)  # Should be 3.333... / Sollte 3.333... sein

# Power (10 to the power of 3) / Potenz (10 hoch 3)
power_ab <- a ____ b
print(power_ab)  # Should be 1000 / Sollte 1000 sein

1e: Updating variables1e: Variablen aktualisieren

# Variables can change!
# Variablen können sich ändern!

# Start with a count of species
# Starte mit einer Artenanzahl
species_count <- 0
print(species_count)

# Found 5 species / 5 Arten gefunden
species_count <- species_count + ____
print(species_count)  # Should be 5 / Sollte 5 sein

# Found 3 more / 3 weitere gefunden
species_count <- species_count + ____
print(species_count)  # Should be 8 / Sollte 8 sein

# Oops, 2 were misidentified (subtract)
# Ups, 2 waren falsch bestimmt (subtrahieren)
species_count <- species_count - ____
print(species_count)  # Should be 6 / Sollte 6 sein

Hint: Math operators are + - * / and ^ for power. Use == for “equals” comparison! Hinweis: Rechenoperatoren sind + - * / und ^ für Potenz. Benutze == für “gleich” Vergleich!


Exercise 2: Vectors - Lists of ValuesÜbung 2: Vektoren - Listen von Werten

Concept: A vector is a list of values of the same type. We use c() to combine values into a vector.

Konzept: Ein Vektor ist eine Liste von Werten des gleichen Typs. Wir benutzen c() um Werte zu kombinieren.

2a: Creating vectors2a: Vektoren erstellen

# Create a vector of numbers
# Erstelle einen Vektor von Zahlen
species_counts <- c(5, 3, 7, 2, 4)
print(species_counts)

# Your turn - create a vector of 4 tree heights
# Du bist dran - erstelle einen Vektor mit 4 Baumhöhen
tree_heights <- c(____, ____, ____, ____)
print(tree_heights)

# Create a vector of species names
# Erstelle einen Vektor von Artnamen
tree_species <- c("Oak", "Beech", "Pine", "Maple")
print(tree_species)

2b: Vector functions2b: Vektor-Funktionen

# How many elements in the vector?
# Wie viele Elemente im Vektor?
length(species_counts)

# Calculate the sum
# Berechne die Summe
sum(species_counts)

# Calculate the mean (average)
# Berechne den Mittelwert (Durchschnitt)
mean(species_counts)

# Your turn - calculate mean of your tree heights
# Du bist dran - berechne den Mittelwert deiner Baumhöhen
mean(____)

# Find min and max
# Finde Minimum und Maximum
min(species_counts)
max(species_counts)

2c: Combining vectors2c: Vektoren kombinieren

# Species from different plots
# Arten von verschiedenen Plots
plot1 <- c("Oak", "Beech", "Pine")
plot2 <- c("Beech", "Maple", "Oak")
plot3 <- c("Birch", "Oak", "Ash")

# Combine all into one vector
# Kombiniere alle in einen Vektor
all_species <- c(plot1, plot2, plot3)
print(all_species)

# How many total observations?
# Wie viele Beobachtungen insgesamt?
length(all_species)

Hint: c() combines values. length() counts elements. mean() calculates average. Hinweis: c() kombiniert Werte. length() zählt Elemente. mean() berechnet Durchschnitt.


Exercise 3: The Magic of unique()Übung 3: Die Magie von unique()

Concept: unique() is the key function for ecology! It tells us how many different species we found (not counting duplicates).

Konzept: unique() ist die Schlüsselfunktion für Ökologie! Sie sagt uns, wie viele verschiedene Arten wir gefunden haben (ohne Duplikate).

# 3a: We observed these species (some repeats!)
# 3a: Wir haben diese Arten beobachtet (einige Wiederholungen!)

observations <- c("Oak", "Beech", "Oak", "Pine", "Beech", "Oak", "Maple")

# How many observations total?
# Wie viele Beobachtungen insgesamt?
length(observations)

# 3b: How many UNIQUE species?
# 3b: Wie viele EINZIGARTIGE Arten?
unique(observations)
length(unique(observations))

# 3c: Using our plots from before
# 3c: Benutze unsere Plots von vorher
plot1 <- c("Oak", "Beech", "Pine")
plot2 <- c("Beech", "Maple", "Oak")
plot3 <- c("Birch", "Oak", "Ash")

all_species <- c(plot1, plot2, plot3)

# Total observations vs unique species
# Gesamte Beobachtungen vs einzigartige Arten
length(all_species)           # Total / Gesamt
length(unique(all_species))   # Unique / Einzigartig

# 3d: Your turn - how many unique species after plot1 + plot2?
# 3d: Du bist dran - wie viele einzigartige Arten nach plot1 + plot2?
after_two_plots <- c(plot1, ____)
length(unique(after_two_plots))

Hint: Species richness = length(unique(species_list)). This is THE key formula! Hinweis: Artenreichtum = length(unique(artenliste)). Das ist DIE Schlüsselformel!


Exercise 4: Data FramesÜbung 4: Data Frames

A data frame is like a spreadsheet - it has rows and columns. Let’s practice with a small example before loading real data!

Ein Data Frame ist wie eine Tabelle - er hat Zeilen und Spalten. Üben wir mit einem kleinen Beispiel, bevor wir echte Daten laden!

# 4a: Create a simple data frame
# 4a: Erstelle einen einfachen Data Frame

my_data <- data.frame(
  species = c("Oak", "Beech", "Pine", "Maple"),
  height = c(20, 18, 25, 15),
  native = c(TRUE, TRUE, TRUE, FALSE)
)

my_data

# 4b: How many rows and columns?
# 4b: Wie viele Zeilen und Spalten?

nrow(my_data)
ncol(my_data)

# 4c: Access a column with $
# 4c: Greife auf eine Spalte mit $ zu

my_data$species
my_data$height

# 4d: Your turn - get the mean height
# 4d: Du bist dran - berechne die mittlere Höhe

mean(my_data$___)

# 4e: Access a specific row (row 2)
# 4e: Greife auf eine bestimmte Zeile zu (Zeile 2)

my_data[2, ]

# 4f: Access a specific cell (row 2, column "height")
# 4f: Greife auf eine bestimmte Zelle zu (Zeile 2, Spalte "height")

my_data[2, "height"]

Hint: $ accesses columns by name. Square brackets [row, column] access specific cells. Hinweis: $ greift auf Spalten per Name zu. Eckige Klammern [zeile, spalte] greifen auf bestimmte Zellen zu.


Exercise 5: Loading Real DataÜbung 5: Echte Daten laden

Now let’s load the Austrian vegetation data!

Jetzt laden wir die österreichischen Vegetationsdaten!

# 5a: Load the tidyverse package
# 5a: Lade das tidyverse Paket

library(tidyverse)

# 5b: Load the species data
# 5b: Lade die Artdaten

species_data <- read_csv("../data/austria_species.csv")

# 5c: Look at the first few rows
# 5c: Schau dir die ersten Zeilen an

head(species_data)

# 5d: How many rows (observations)?
# 5d: Wie viele Zeilen (Beobachtungen)?

nrow(species_data)

# 5e: What columns do we have?
# 5e: Welche Spalten haben wir?

colnames(species_data)

# 5f: How many unique plots?
# 5f: Wie viele einzigartige Plots?

length(unique(species_data$PlotObservationID))

# 5g: How many unique species in the whole dataset?
# 5g: Wie viele einzigartige Arten im gesamten Datensatz?

length(unique(species_data$___))

Hint: Use $ to access a column, e.g. data$column_name Hinweis: Benutze $ um auf eine Spalte zuzugreifen, z.B. data$spaltenname


Exercise 6: Filtering DataÜbung 6: Daten filtern

Often we want to look at only part of our data. The filter() function helps us select specific rows!

Oft wollen wir nur einen Teil unserer Daten betrachten. Die filter() Funktion hilft uns, bestimmte Zeilen auszuwählen!

# 6a: Look at the STATUS column - what values are there?
# 6a: Schau dir die STATUS-Spalte an - welche Werte gibt es?

unique(species_data$STATUS)

# 6b: Filter for native species only (STATUS == "nat")
# 6b: Filtere nur heimische Arten (STATUS == "nat")

native_only <- species_data %>%
  filter(STATUS == "nat")

nrow(native_only)

# 6c: Filter for alien/invasive species (STATUS == "neo")
# 6c: Filtere Alien/invasive Arten (STATUS == "neo")

alien_only <- species_data %>%
  filter(STATUS == "neo")

nrow(alien_only)

# 6d: How many unique native species?
# 6d: Wie viele einzigartige heimische Arten?

length(unique(native_only$WFO_TAXON))

# 6e: Your turn - how many unique alien species?
# 6e: Du bist dran - wie viele einzigartige Alien-Arten?

length(unique(___$WFO_TAXON))

# 6f: Filter for a specific plot
# 6f: Filtere einen bestimmten Plot

first_plot <- unique(species_data$PlotObservationID)[1]
first_plot

one_plot <- species_data %>%
  filter(PlotObservationID == first_plot)

# How many species in this one plot?
# Wie viele Arten in diesem einen Plot?

length(unique(one_plot$WFO_TAXON))

Hint: filter() keeps rows where the condition is TRUE. Use == for “equals”. Hinweis: filter() behält Zeilen, wo die Bedingung TRUE ist. Benutze == für “gleich”.


Exercise 7: Building the Accumulation CurveÜbung 7: Die Akkumulationskurve bauen

Now the exciting part - let’s build a species accumulation curve step by step!

Jetzt der spannende Teil - bauen wir eine Artenakkumulationskurve Schritt für Schritt!

# 7a: Get a list of all unique plots
# 7a: Hole eine Liste aller einzigartigen Plots

all_plots <- unique(species_data$PlotObservationID)
head(all_plots)

# 7b: Take a small sample (first 50 plots for speed)
# 7b: Nimm eine kleine Stichprobe (erste 50 Plots für Geschwindigkeit)

sample_plots <- all_plots[1:50]

# 7c: Initialize our accumulation tracking
# 7c: Initialisiere unsere Akkumulations-Verfolgung

species_found <- c()           # Empty vector to collect species
                               # Leerer Vektor um Arten zu sammeln
accumulation <- c()            # Will store species count after each plot
                               # Speichert Artenzahl nach jedem Plot

# 7d: Loop through each plot and count species!
# 7d: Schleife durch jeden Plot und zähle Arten!

for (i in 1:length(sample_plots)) {

  # Get current plot ID
  # Hole aktuelle Plot-ID
  current_plot <- sample_plots[i]

  # Get species in this plot
  # Hole Arten in diesem Plot
  plot_species <- species_data$WFO_TAXON[species_data$PlotObservationID == current_plot]

  # Add to our collection
  # Füge zu unserer Sammlung hinzu
  species_found <- c(species_found, plot_species)

  # Count unique species so far
  # Zähle einzigartige Arten bisher
  total_species <- length(unique(species_found))

  # Store in accumulation vector
  # Speichere im Akkumulationsvektor
  accumulation <- c(accumulation, total_species)
}

# 7e: Look at the result!
# 7e: Schau dir das Ergebnis an!

accumulation

Exercise 8: Plot Your Curve!Übung 8: Zeichne deine Kurve!

The final step - let’s visualize our accumulation curve!

Der letzte Schritt - visualisieren wir unsere Akkumulationskurve!

# 8a: Create a data frame for plotting
# 8a: Erstelle einen Data Frame zum Plotten

curve_data <- data.frame(
  plots = 1:length(accumulation),
  species = accumulation
)

head(curve_data)

# 8b: Make the plot!
# 8b: Mache den Plot!

ggplot(curve_data, aes(x = plots, y = species)) +
  geom_line(color = "#2E7D32", linewidth = 2) +
  geom_point(color = "#2E7D32", size = 2) +
  labs(
    title = "My First Species Accumulation Curve!",
    x = "Number of Plots Sampled",
    y = "Cumulative Species Count"
  ) +
  theme_minimal(base_size = 14)

# 8c: Make it prettier with a filled area
# 8c: Mache es schöner mit gefüllter Fläche

ggplot(curve_data, aes(x = plots, y = species)) +
  geom_area(fill = "#C8E6C9", alpha = 0.5) +
  geom_line(color = "#2E7D32", linewidth = 2) +
  labs(
    title = "Species Accumulation Curve - Austria",
    subtitle = paste("Total species found:", max(accumulation)),
    x = "Plots Sampled",
    y = "Cumulative Species"
  ) +
  theme_minimal(base_size = 14)

Hint: The curve flattens because we find fewer NEW species as we sample more plots! Hinweis: Die Kurve flacht ab, weil wir weniger NEUE Arten finden, je mehr Plots wir untersuchen!


Bonus: Compare Native vs Alien!Bonus: Vergleiche Heimisch vs Alien!

If you finish early, try comparing native and alien species!

Wenn du früh fertig bist, versuche heimische und Alien-Arten zu vergleichen!

# The species_data already has a STATUS column!
# Die species_data hat bereits eine STATUS-Spalte!

# Filter for native species only
# Filtere nur heimische Arten

native_species <- species_data %>%
  filter(STATUS == "nat")

# How many native species?
# Wie viele heimische Arten?

length(unique(native_species$WFO_TAXON))

# How many alien species?
# Wie viele Alien-Arten?

alien_species <- species_data %>%
  filter(STATUS == "neo")

length(unique(alien_species$WFO_TAXON))

# Now you can build separate curves for native vs alien!
# Jetzt kannst du separate Kurven für heimisch vs alien bauen!

You did it! You built your first species accumulation curve using real Austrian data!

Key concepts learned: - Variables store data with <- - c() creates vectors - unique() counts different values - Data frames organize data in rows and columns - filter() selects specific rows - Loops let us repeat actions - ggplot() creates beautiful plots

Du hast es geschafft! Du hast deine erste Artenakkumulationskurve mit echten österreichischen Daten gebaut!

Gelernte Schlüsselkonzepte: - Variablen speichern Daten mit <- - c() erstellt Vektoren - unique() zählt verschiedene Werte - Data Frames organisieren Daten in Zeilen und Spalten - filter() wählt bestimmte Zeilen aus - Schleifen lassen uns Aktionen wiederholen - ggplot() erstellt schöne Plots