Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
The 30-Day Map Challenge is on again, and I’m hoping to be able to scrounge some time to get an entry for each day. Day 2 is lines (Day 1 was posted on Twitter only) and — while I’m hoping to focus on saving U.S. democracy for the majority of the entries, today’s is a short one that shows all the walks/hikes/boats we took during our Iceland vacation.
I use HealthFit to export data (automagically) from all my Apple Watch, Garmin, and Peloton activities, and have it auto-sync to iCloud, which means I have instant access to all the Garmin FIT files it creates in ~/Library/Mobile Documents/iCloud~com~altifondo~HealthFit/
.
We can use {FITFileR} to read in those files, turn the points into lines, and plot them all on a {leaflet} map, so I can get an interactive view into the paths.
If I had more time, I’d add activity names and other clickable statistics in popups, which is pretty straightforward in {leaflet}.
Comments in code hopefully explain the workflow:
library(sf) library(FITfileR) # remotes::install_github("grimbough/FITfileR") library(leaflet) library(tidyverse) # get a listing of all the files for when we were in Iceland list.files( path = "~/Library/Mobile Documents/iCloud~com~altifondo~HealthFit/Documents", pattern = "(2021-07-3[01]|2021-08-0[1-9])", full.names = TRUE ) %>% map( ~readFitFile(.x) %>% # read the file in records() %>% # turn into something we can then bind into a data frame bind_rows() %>% # bind ^^ into a data frame! mutate(file = basename(.x)) # add the file info in case we want to eventually make a popup of information ) -> iceland_fit_files # look at the data iceland_fit_files[[1]] ## # A tibble: 2,210 × 12 ## timestamp position_lat position_long gps_accuracy altitude distance speed temperature heart_rate cadence ## <dttm> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> ## 1 2021-07-30 06:28:26 64.2 -21.9 2 21 318. 0.221 13 116 NA ## 2 2021-07-30 06:28:27 64.2 -21.9 2 21 318. 0.521 13 116 NA ## 3 2021-07-30 06:28:28 64.2 -21.9 2 21 319. 0.792 13 116 NA ## 4 2021-07-30 06:28:47 64.2 -21.9 2 19.4 338. 0.217 13 118 NA ## 5 2021-07-30 06:28:48 64.2 -21.9 2 19.2 338. 0.147 13 118 NA ## 6 2021-07-30 06:28:49 64.2 -21.9 2 19 338. 0.109 13 117 NA ## 7 2021-07-30 06:28:50 64.2 -21.9 2 19 338. 0.076 13 117 NA ## 8 2021-07-30 06:28:51 64.2 -21.9 2 18.8 338. 0.036 13 116 NA ## 9 2021-07-30 06:28:52 64.2 -21.9 2 18.6 338. 0.153 13 115 NA ## 10 2021-07-30 06:28:53 64.2 -21.9 2 18.4 339. 0.393 13 115 NA ## # … with 2,200 more rows, and 2 more variables: fractional_cadence <dbl>, file <chr> iceland_fit_files[map_lgl(iceland_fit_files, has_name, "position_long")] %>% # only want activities with geo data map( ~.x %>% filter(!is.na(position_long), !is.na(position_lat)) %>% # {sf} hates NAs st_as_sf( coords = c("position_long", "position_lat"), # turn the data frame into an {sf} object crs = 4326 ) ) %>% bind_rows() %>% # this makes one big data frame group_by(file) %>% # which we can turn into individual geometries summarise( # with the epic summarise() function m = max(distance) ) %>% st_cast("LINESTRING") -> paths # and then turn the points into linestrings # let's take a look paths ## Simple feature collection with 33 features and 2 fields ## Geometry type: LINESTRING ## Dimension: XY ## Bounding box: xmin: -23.92788 ymin: 63.40121 xmax: -16.18086 ymax: 65.08101 ## Geodetic CRS: WGS 84 ## # A tibble: 33 × 3 ## file m geometry ## <chr> <dbl> <LINESTRING [°]> ## 1 2021-07-30-062401-Walking-Chetzmoka.fit 2807. (-21.94386 64.15495, -21.94382 64.15497, -21.94384 64.15496, -21.94388 64.… ## 2 2021-07-30-101146-Walking-Chetzmoka.fit 1191. (-21.93504 64.14761, -21.93502 64.1476, -21.93503 64.14761, -21.93501 64.1… ## 3 2021-07-30-105706-Walking-Chetzmoka.fit 1554. (-21.91706 64.12906, -21.91704 64.12905, -21.91702 64.12905, -21.917 64.12… ## 4 2021-07-30-143247-Walking-Chetzmoka.fit 1620. (-21.94977 64.15683, -21.94978 64.15685, -21.94979 64.15686, -21.94995 64.… ## 5 2021-07-31-122122-Walking-Chetzmoka.fit 702. (-22.26431 64.7628, -22.26463 64.76297, -22.26527 64.76332, -22.26496 64.7… ## 6 2021-07-31-131832-Walking-Chetzmoka.fit 2084. (-22.84353 64.90553, -22.84351 64.90553, -22.84349 64.90553, -22.84347 64.… ## 7 2021-07-31-182725-Walking-Chetzmoka.fit 578. (-22.72256 65.0809, -22.72255 65.0809, -22.72254 65.08089, -22.72252 65.08… ## 8 2021-08-01-105420-Walking-Chetzmoka.fit 1210. (-23.63732 64.79827, -23.6373 64.79829, -23.6373 64.79829, -23.6373 64.798… ## 9 2021-08-01-142847-Walking-Chetzmoka.fit 2385. (-23.80382 64.73048, -23.8038 64.73047, -23.8038 64.73047, -23.8038 64.730… ## 10 2021-08-01-165642-Walking-Chetzmoka.fit 423. (-23.92745 64.85198, -23.92749 64.85197, -23.92747 64.85197, -23.92746 64.… ## # … with 23 more rows # make room locally dir.create("~/projects/2021-iceland", showWarnings = FALSE) # save the widget out paths %>% filter(!grepl("2021-08-10", file)) %>% leaflet() %>% addProviderTiles("CartoDB.Positron") %>% addPolygons(color = "green") %>% htmlwidgets::saveWidget( file = "~/projects/2021-iceland/index.html", selfcontained = FALSE ) # rsync it out to my website #
This is the (static) overview:
And, this is a zoom into our boating tour of a glacier lagoon:
Hit up the widget to see where we did our Iceland activities this summer!
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.