In this post I will demonstrate how to display your Google Photos on a map. As you probably know, most of today´s mobile devices or cameras allow to record GPS position during taking the photos.
If you are using Google Photos you can leverage Google Takeout for this task. Google Takeout is a service for anyone with Google account allowing the users to download back any previously updated data.
It means you can download back all your uploaded photos including JSON files for each file. These JSON files are exactly what we are interested in as they contains all information the Google tracks about your photos.
library(jsonlite)
library(lubridate)
library(tidyverse)
library(leaflet)
library(mapview)
After you download your photos you can simply retrieve the list of all JSON files:
path_vector <- list.files("D:/GoogleDrive/Takeout", pattern = ".json$", recursive = TRUE, full.names = TRUE)
path_vector %>% head
## [1] "D:/GoogleDrive/Takeout/Fotky Google/2004_06 Budvar factory party 12,13/DSCF0019.jpg.json"
## [2] "D:/GoogleDrive/Takeout/Fotky Google/2004_06 Budvar factory party 12,13/DSCF0029.jpg.json"
## [3] "D:/GoogleDrive/Takeout/Fotky Google/2004_06 Budvar factory party 12,13/DSCF0030.jpg.json"
## [4] "D:/GoogleDrive/Takeout/Fotky Google/2004_06 Budvar factory party 12,13/DSCF0033.jpg.json"
## [5] "D:/GoogleDrive/Takeout/Fotky Google/2004_06 Budvar factory party 12,13/DSCF0037.jpg.json"
## [6] "D:/GoogleDrive/Takeout/Fotky Google/2004_06 Budvar factory party 12,13/DSCF6092.jpg.json"
Each JSON contains several variables about the photo. I´m interested only in GPS location, path to Google server and the date the picture was taken.
lst <- path_vector %>% map(fromJSON)
lst[1]
## [[1]]
## [[1]]$title
## [1] "DSCF0019.jpg"
##
## [[1]]$description
## [1] ""
##
## [[1]]$url
## [1] "https://lh3.googleusercontent.com/-6TjimfukJvM/XCJ3wEGP6OI/AAAAAAACR_Q/-hRC-QHc2Lgw16X21jBovjDDJ0RDSuRdACLABGAYYCw/s0-d/DSCF0019.jpg"
##
## [[1]]$imageViews
## [1] "0"
##
## [[1]]$creationTime
## [[1]]$creationTime$timestamp
## [1] "1545762751"
##
## [[1]]$creationTime$formatted
## [1] "25. 12. 2018 18:32:31 UTC"
##
##
## [[1]]$modificationTime
## [[1]]$modificationTime$timestamp
## [1] "1545851448"
##
## [[1]]$modificationTime$formatted
## [1] "26. 12. 2018 19:10:48 UTC"
##
##
## [[1]]$geoData
## [[1]]$geoData$latitude
## [1] 0
##
## [[1]]$geoData$longitude
## [1] 0
##
## [[1]]$geoData$altitude
## [1] 0
##
## [[1]]$geoData$latitudeSpan
## [1] 0
##
## [[1]]$geoData$longitudeSpan
## [1] 0
##
##
## [[1]]$geoDataExif
## [[1]]$geoDataExif$latitude
## [1] 0
##
## [[1]]$geoDataExif$longitude
## [1] 0
##
## [[1]]$geoDataExif$altitude
## [1] 0
##
## [[1]]$geoDataExif$latitudeSpan
## [1] 0
##
## [[1]]$geoDataExif$longitudeSpan
## [1] 0
##
##
## [[1]]$photoTakenTime
## [[1]]$photoTakenTime$timestamp
## [1] "1086109200"
##
## [[1]]$photoTakenTime$formatted
## [1] "1. 6. 2004 17:00:00 UTC"
Tibble is always good starting point..
df_raw <- tibble(orig_path = path_vector, data = lst)
df_raw
## # A tibble: 6,944 x 2
## orig_path data
## <chr> <list>
## 1 D:/GoogleDrive/Takeout/Fotky Google/2004_06 Budvar factory p~ <list [9~
## 2 D:/GoogleDrive/Takeout/Fotky Google/2004_06 Budvar factory p~ <list [9~
## 3 D:/GoogleDrive/Takeout/Fotky Google/2004_06 Budvar factory p~ <list [9~
## 4 D:/GoogleDrive/Takeout/Fotky Google/2004_06 Budvar factory p~ <list [9~
## 5 D:/GoogleDrive/Takeout/Fotky Google/2004_06 Budvar factory p~ <list [9~
## 6 D:/GoogleDrive/Takeout/Fotky Google/2004_06 Budvar factory p~ <list [9~
## 7 D:/GoogleDrive/Takeout/Fotky Google/2004_06 Budvar factory p~ <list [9~
## 8 D:/GoogleDrive/Takeout/Fotky Google/2004_06 Budvar factory p~ <list [9~
## 9 D:/GoogleDrive/Takeout/Fotky Google/2004_06 Budvar factory p~ <list [9~
## 10 D:/GoogleDrive/Takeout/Fotky Google/2004_06 Budvar factory p~ <list [9~
## # ... with 6,934 more rows
A little bit of extractions and manipulation..
df <- df_raw %>%
# exclude "metadata.json" files
filter(!str_detect(orig_path, "metadata")) %>%
# extract link to google server
mutate(google_path = map_chr(data, "url")) %>%
# exclude video files
filter(!str_detect(google_path, "video-downloads")) %>%
# this will modify the link in order to display in popup window later instead of download
mutate(google_path = str_replace(google_path, "/s0-d", "")) %>%
# extract GPS location
mutate(lat = map(data, "geoData") %>% map_dbl(., "latitude")) %>%
mutate(lon = map(data, "geoData") %>% map_dbl(., "longitude")) %>%
# extract photo taken time
mutate(photo_taken_time = map(data, "photoTakenTime") %>% map_chr(., "formatted")) %>%
mutate(photo_taken_time = dmy_hms(photo_taken_time)) %>%
select(-data)
df
## # A tibble: 6,725 x 5
## orig_path google_path lat lon photo_taken_time
## <chr> <chr> <dbl> <dbl> <dttm>
## 1 D:/GoogleDrive/Tak~ https://lh3.google~ 0 0 2004-06-01 17:00:00
## 2 D:/GoogleDrive/Tak~ https://lh3.google~ 0 0 2004-06-01 17:00:00
## 3 D:/GoogleDrive/Tak~ https://lh3.google~ 0 0 2004-06-01 17:00:00
## 4 D:/GoogleDrive/Tak~ https://lh3.google~ 0 0 2004-06-01 17:00:00
## 5 D:/GoogleDrive/Tak~ https://lh3.google~ 0 0 2004-06-01 17:00:00
## 6 D:/GoogleDrive/Tak~ https://lh3.google~ 0 0 2004-06-01 17:00:00
## 7 D:/GoogleDrive/Tak~ https://lh3.google~ 0 0 2004-06-01 17:00:00
## 8 D:/GoogleDrive/Tak~ https://lh3.google~ 0 0 2004-06-01 17:00:00
## 9 D:/GoogleDrive/Tak~ https://lh3.google~ 0 0 2004-06-01 17:00:00
## 10 D:/GoogleDrive/Tak~ https://lh3.google~ 0 0 2004-06-01 17:00:00
## # ... with 6,715 more rows
df %>%
count(lat != 0 & lon != 0) %>%
mutate(prop = round(n/sum(n)*100,2))
## # A tibble: 2 x 3
## `lat != 0 & lon != 0` n prop
## <lgl> <int> <dbl>
## 1 FALSE 6382 94.9
## 2 TRUE 343 5.1
..obviously most of my pictures is without GPS data. The good news is it can be easily edited directly on Google Photos app for any photo.
df %>%
filter(lat!=0) %>%
count(year(photo_taken_time))
## # A tibble: 7 x 2
## `year(photo_taken_time)` n
## <dbl> <int>
## 1 2012 37
## 2 2013 16
## 3 2014 14
## 4 2015 10
## 5 2016 6
## 6 2017 13
## 7 2018 247
..it is related to the fact that my last phone is my first which allows to record GPS during taking photos.
Finally, using the leaflet maps we can display all photos as points on a map and use it´s functionality as selecting the point and display the photo.
imgurl <- df %>%
filter(lat!=0) %>%
pull(google_path) #%>%
m <- df %>%
filter(lat!=0) %>%
leaflet() %>%
# add default OpenStreetMap map tiles
addTiles() %>%
addCircles(popup = popupImage(img = imgurl, src = c("remote"))) %>%
clearBounds()
m
This is just image due to obvious personal reasons. Feel free to replicate for your own data;) Hope you enjoyed.