E5

E5

Demo: R Functions

Zuerst macht man den Namen und dann öffnet man eine neue Funktion. Wenn man testet, dann enthält diese noch nichts, existiert aber. Mit class kann man abfragen, um was es sich handelt.

testfun <- function() {}

testfun()
NULL
class(testfun)
[1] "function"

Beispiel:

testfun <- function() {
    print("this function does nothing")
}

testfun()
[1] "this function does nothing"

Weiteres Beispiel

testfun <- function(sometext) {
    print(sometext)
}

testfun(sometext = "this function does slightly more, but still not much")
[1] "this function does slightly more, but still not much"

Ein Beispiel, um das Alter auszurechnen, wenn man den Geburtstag einspeist. Einmal eingespeist, ist die Funktion aktiviert für das ganze Skript.

my_age <- function(birthday, output_unit) {
    difftime(Sys.time(), birthday, units = output_unit)
}

my_age(birthday = "1997-04-23", output_unit = "days")
Time difference of 10618.96 days
# We can still overwrite units
my_age("1997-04-23", "hours")
Time difference of 254855 hours

Tasks and Inputs

Task 1: Write your own functions

Funktion machen, die den BMI basierend auf dem Gewicht und der Grösse berechnet.

  • BMI= Weight kg / Height m^2
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
library(lubridate)

Attaching package: 'lubridate'
The following objects are masked from 'package:base':

    date, intersect, setdiff, union
library(ggplot2)
library(plotly)

Attaching package: 'plotly'
The following object is masked from 'package:ggplot2':

    last_plot
The following object is masked from 'package:stats':

    filter
The following object is masked from 'package:graphics':

    layout
bmi <- function(weight, height) {
  weight / (height^2)
}

# Example
bmi(weight = 60, height = 1.63)
[1] 22.58271

Funktion machen, die Grad in Fahrenheit umwandelt.

  • Fahrenheit = Celsius x 9/5 + 32
c_to_f <- function(celsius) {
  (celsius * 9/5) + 32
}

# Example
c_to_f(20)
[1] 68

Funktion machen, die die euklidische Distanz zwischen zwei Koordinatensets ausrechnet (x1,y1 und x2, y2) wie in der Equation 21.3.

  • Euclidian Distance= Wurzel aus (x2-x1)^2 + (y2-y1)^2
euclidean_distance <- function(x1, y1, x2, y2) {
  sqrt((x2 - x1)^2 + (y2 - y1)^2)
}

# Example
euclidean_distance(0, 0, 3, 4)
[1] 5

Task 2: Prepare Analysis

Wir wollen uns “meeting” patterns anschauen in den Daten der Wildschweine –

  • Rosa und Sabi

  • in der Timespan 1.4.15-15.4.15

  • aus den Daten wildschwein_BE_2056.csv.

wildschwein <- read.csv("Data/wildschwein_BE_2056.csv")

wildschwein$DatetimeUTC <- ymd_hms(wildschwein$DatetimeUTC)

wildschwein_filter <- wildschwein %>%
  filter(
    TierName %in% c("Rosa", "Sabi"),
    DatetimeUTC >= ymd("2015-04-01"),
    DatetimeUTC <= ymd("2015-04-15")
  )

head(wildschwein_filter)
  TierID TierName CollarID         DatetimeUTC       E       N
1   002A     Sabi    12275 2015-04-01 00:00:11 2570372 1205313
2   002A     Sabi    12275 2015-04-01 00:15:22 2570309 1205262
3   002A     Sabi    12275 2015-04-01 00:30:11 2570326 1205248
4   002A     Sabi    12275 2015-04-01 00:45:16 2570315 1205242
5   002A     Sabi    12275 2015-04-01 01:00:44 2570323 1205237
6   002A     Sabi    12275 2015-04-01 01:15:17 2570320 1205247

Task 3: Create Join Key

Timestamps runden zu den nächsten 15min.

wildschwein_filter <- wildschwein_filter %>%
  mutate(
    DatetimeRound = round_date(DatetimeUTC, unit = "15 minutes")
  )

head(wildschwein_filter)
  TierID TierName CollarID         DatetimeUTC       E       N
1   002A     Sabi    12275 2015-04-01 00:00:11 2570372 1205313
2   002A     Sabi    12275 2015-04-01 00:15:22 2570309 1205262
3   002A     Sabi    12275 2015-04-01 00:30:11 2570326 1205248
4   002A     Sabi    12275 2015-04-01 00:45:16 2570315 1205242
5   002A     Sabi    12275 2015-04-01 01:00:44 2570323 1205237
6   002A     Sabi    12275 2015-04-01 01:15:17 2570320 1205247
        DatetimeRound
1 2015-04-01 00:00:00
2 2015-04-01 00:15:00
3 2015-04-01 00:30:00
4 2015-04-01 00:45:00
5 2015-04-01 01:00:00
6 2015-04-01 01:15:00

Task 4: Measuring distance at concurrent locations

Pro Tier machen, also einen für Rosa und einen für Sabi

  • Datensätze zuammentun mit einem Inner Join (matching)

  • Euklidische Distanz mit Funktion machen

  • Meets machen (100m)

rosa <- wildschwein_filter %>%
  filter(TierName == "Rosa")

sabi <- wildschwein_filter %>%
  filter(TierName == "Sabi")

meet_data <- inner_join(
  rosa,
  sabi,
  by = "DatetimeRound",
  suffix = c("_rosa", "_sabi")
)

meet_data <- meet_data %>%
  mutate(
    distance = euclidean_distance(
      E_rosa,
      N_rosa,
      E_sabi,
      N_sabi
    )
  )

meet_data <- meet_data %>%
  mutate(
    meet = distance <= 100
  )

head(meet_data)
  TierID_rosa TierName_rosa CollarID_rosa    DatetimeUTC_rosa  E_rosa  N_rosa
1        016A          Rosa         13972 2015-04-01 00:00:10 2570823 1204800
2        016A          Rosa         13972 2015-04-01 00:15:14 2570831 1204794
3        016A          Rosa         13972 2015-04-01 00:30:11 2570842 1204796
4        016A          Rosa         13972 2015-04-01 00:45:17 2570820 1204803
5        016A          Rosa         13972 2015-04-01 01:00:44 2570829 1204787
6        016A          Rosa         13972 2015-04-01 01:15:06 2570831 1204767
        DatetimeRound TierID_sabi TierName_sabi CollarID_sabi
1 2015-04-01 00:00:00        002A          Sabi         12275
2 2015-04-01 00:15:00        002A          Sabi         12275
3 2015-04-01 00:30:00        002A          Sabi         12275
4 2015-04-01 00:45:00        002A          Sabi         12275
5 2015-04-01 01:00:00        002A          Sabi         12275
6 2015-04-01 01:15:00        002A          Sabi         12275
     DatetimeUTC_sabi  E_sabi  N_sabi distance  meet
1 2015-04-01 00:00:11 2570372 1205313 682.8943 FALSE
2 2015-04-01 00:15:22 2570309 1205262 700.9568 FALSE
3 2015-04-01 00:30:11 2570326 1205248 685.8371 FALSE
4 2015-04-01 00:45:16 2570315 1205242 669.1526 FALSE
5 2015-04-01 01:00:44 2570323 1205237 676.5464 FALSE
6 2015-04-01 01:15:17 2570320 1205247 701.6919 FALSE

Task 5: Visualize Data

Meetings in Grün

meets_only <- meet_data %>%
  filter(meet == TRUE)
ggplot() +

  # Rosa trajectory
  geom_path(
    data = rosa,
    aes(x = E, y = N),
    color = "red"
  ) +

  # Sabi trajectory
  geom_path(
    data = sabi,
    aes(x = E, y = N),
    color = "blue"
  ) +

  # Meeting points
  geom_point(
    data = meets_only,
    aes(x = E_rosa, y = N_rosa),
    color = "green",
    size = 3
  ) +

  coord_cartesian(
    xlim = c(min(wildschwein_filter$E),
              max(wildschwein_filter$E)),
    ylim = c(min(wildschwein_filter$N),
              max(wildschwein_filter$N))
  ) +

  labs(
    title = "Meetings between Rosa and Sabi",
    x = "Easting",
    y = "Northing"
  ) +

  theme_minimal()

Task 6: Optional - Space time with plotly

3D Version

rosa$time_num <- as.numeric(rosa$DatetimeUTC)
sabi$time_num <- as.numeric(sabi$DatetimeUTC)

plot_ly() %>%

  add_trace(
    data = rosa,
    x = ~E,
    y = ~N,
    z = ~time_num,
    type = "scatter3d",
    mode = "lines",
    name = "Rosa"
  ) %>%

  add_trace(
    data = sabi,
    x = ~E,
    y = ~N,
    z = ~time_num,
    type = "scatter3d",
    mode = "lines",
    name = "Sabi"
  ) %>%

  layout(
    title = "Space-Time Cube of Rosa and Sabi",
    scene = list(
      xaxis = list(title = "Easting"),
      yaxis = list(title = "Northing"),
      zaxis = list(title = "Time")
    )
  )