-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathREADME.Rmd
181 lines (129 loc) · 7.76 KB
/
README.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
---
output: github_document
editor_options:
chunk_output_type: console
---
<!-- README.md is generated from README.Rmd. Please edit that file -->
```{r, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>",
fig.path = "man/figures/README-",
out.width = "100%"
)
library(tidyverse)
```
# traipse
<!-- badges: start -->
[![Lifecycle: experimental](https://img.shields.io/badge/lifecycle-maturing-blue.svg)](https://lifecycle.r-lib.org/articles/stages.html)
[![CRAN status](https://www.r-pkg.org/badges/version/traipse)](https://cran.r-project.org/package=traipse)
[![CRAN_Download_Badge](http://cranlogs.r-pkg.org/badges/traipse)](https://cran.r-project.org/package=traipse)
[![R build status](https://github.com/Trackage/traipse/workflows/R-CMD-check/badge.svg)](https://github.com/Trackage/traipse/actions)
[![R-CMD-check](https://github.com/Trackage/traipse/workflows/R-CMD-check/badge.svg)](https://github.com/Trackage/traipse/actions)
<!-- badges: end -->
The goal of traipse is to provide shared tools for tracking data, for common metrics of distance, direction, and speed. The package includes the following functions which are always assumed to operate on input locations in longitude latitude, and input date-times in R's `POSIXt` class.
* `track_distance()` for distance in metres
* `track_angle()` for internal angle in degrees
* `track_turn()` for relative turn angle
* `track_bearing()` for absolute bearing
* `track_time()` for duration in seconds
* `track_speed()` for speed in metres per second
* `track_distance_to()` for distance to location
* `track_bearing_to()` for bearing to location
* `track_intermediate()` for interpolating locations
* `track_query()` also for interpolation, by finding locations within a given track arbitrarily (in-development)
* `track_grid` for identifying locations in grid cells
Distances are always returned in **metres**, directions and angles are always returned in **degrees**. Absolute bearing is relative to North (0), and proceeds clockwise positive and anti-clockwise negative `N = 0, E = 90, S = +/-180, W = -90`.
Time is always returned in **seconds**, and speed in **metres per second**.
## No complex data structures
Traipse works directly on longitude and latitude vectors as it is intended for use within other tools that work directly with data.
There is no capacity for providing nested data structures because this is trivially done by using tidyverse code like
```R
data %>% group_by(id) %>% mutate(distance = track_distance(lon, lat)) %>% ungroup()
```
or by arranging use of the functions in various ways. Track metric values are inherently [window-like](https://dplyr.tidyverse.org/articles/window-functions.html) and in traipse padding value/s of `NA` are used to return an element for every input location.
## Installation
You can install traipse from [CRAN](https://CRAN.r-project.org/package=traipse) with:
```r
install.packages("traipse")
```
You can install the development version from [GitHub](https://github.com/) with:
``` r
# install.packages("devtools")
devtools::install_github("Trackage/traipse")
```
## Example
This is a basic example which shows you how to calculate ellipsoidal distance and turning angle for a data set of tracks.
First, calculate without any groupings - we definitely don't want this for real work as there are three separate tracks within our data set identified by `id`. (No ordering is applied other than the order the rows occur).
```{r example}
library(traipse)
library(dplyr)
## there's no grouping here - we haven't gotten our data organized yet
trips0 %>% mutate(distance = track_distance(x, y), angle = track_angle(x, y))
```
Now run a set of available metrics, but do it with respect to the grouping variable `id`.
```{r example-group_by}
metric <- trips0 %>% group_by(id) %>% mutate(distance = track_distance(x, y),
angle = track_angle(x, y),
turn = track_turn(x, y),
bearing = track_bearing(x, y),
duration = track_time(date),
speed = track_speed(x, y, date),
distance_to = track_distance_to(x, y, 147, -42),
bearing_to = track_bearing_to(x, y, 100, -42))
metric
metric %>%
ggplot(aes(x, y, cex= 1/angle)) +
geom_point() +
geom_path(col = rgb(0.2, 0.2, 0.2, 0.2))
metric %>%
ggplot(aes(x, y, colour = distance_to)) +
geom_point() + geom_label(data = data.frame(x = 147, y = -42, distance_to = 0),
label = "home")
metric %>%
ggplot(aes(x, y, colour = bearing_to)) +
geom_point() + geom_label(data = data.frame(x = 100, y = -42, bearing_to = 0),
label = "home")
```
Using the bearing and distance now reproduce the track as *destination point* segments.
```{r dest-point}
plot(metric[1:10, c("x", "y")], type = "b", lwd = 10, col = "grey")
dest <- geosphere::destPoint(metric[1:10, c("x", "y")],
b = metric$bearing[1:10],
d = metric$distance[2:11])
arrows(metric$x[1:10], metric$y[1:10], dest[1:10,1], dest[1:10,2], col = "firebrick", lwd = 2)
```
## Intermediate points require extra handling
The function `track_intermediate()` requires extra work as it inherently returns multiple variables (lon, lat, date-time). The output is a list-column of data frames, and if used within `mutate(inter = track_intermediate(lon, lat, date))` then it will be stored along side the rows of the input data.
To use this we must unnest the data and treat the new columns as the output.
See this example.
```{r intermediate}
if (requireNamespace("tidyr") && requireNamespace("dplyr")) {
tr1 <- trips0[seq(1, nrow(trips0), by = 30), ]
dd <- tr1 %>% group_by(id) %>%
mutate(inter = track_intermediate(x, y, date = date, distance = 150000)) %>%
tidyr::unnest()
plot(dd$int_date, dd$int_y, pch = ".", cex = 2, main = "equidistant in space")
abline(v = tr1$date)
dd1 <- tr1 %>% group_by(id) %>%
mutate(inter = track_intermediate(x, y, date = date, duration = 3600 * 12)) %>%
tidyr::unnest()
plot(dd1$int_date, dd1$int_y, pch = ".", cex = 2, main = "equispaced in time")
abline(v = tr1$date)
}
```
Query.
```{r, query}
track_query(trips0$x[1:10], trips0$y[1:10], query = c(4.5, 5.5, 6.5))
track_query(trips0$x[1:10], trips0$y[1:10], trips0$date[1:10], query = trips0$date[1:10] + 10)
s <- seq(min(trips0$date), max(trips0$date), by = "1 hour")
trips0 %>% group_by(id) %>% group_modify(~track_query(.x$x, .x$y, .x$date, query = s))
```
## Data are assumed to be sensibly organized
Note above that we provided a *grouping ID* for when we have separate trips within the same data set. There's nothing to stop from calculating distances when the arrangement of records does not make sense, but this is your responsibility. If missing values are present, or times are out of order, or include zero-length time durations, or movement backward in time there aren't any checks for that made in the traipse package.
The idea is for developers to be able to use these tools however they like but with an assumed consistent workflow.
We would like to have a simple core package to provide the most commonly used metrics. We assume `geodist` and `geosphere` as good examples of core packages for the underlying tool. These both apply the modern geodesic methods of C. F. F. Karney (2013) [Algorithms for geodesics](https://doi.org/10.1007/s00190-012-0578-z)
---
Please note that this project is released with a
[Contributor Code of Conduct](https://github.com/Trackage/traipse/blob/master/CODE_OF_CONDUCT.md).
By contributing to this project, you agree to abide by its terms.