Skip to content

Commit

Permalink
replace ggmap with leaflet for plot_location()
Browse files Browse the repository at this point in the history
  • Loading branch information
JuKo007 committed Mar 22, 2024
1 parent 669e067 commit 4b35af6
Show file tree
Hide file tree
Showing 9 changed files with 51 additions and 92 deletions.
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Description: Imports 'WhatsApp' chat logs and parses them into
media files from the messages, extracting timestamps from messages, extracting and anonymizing author
names from messages. Can be used to create anonymized versions of data.
License: GPL-3
Imports: stringi, qdapRegex, readr, tokenizers, data.table, ggplot2, anytime, mgsub, stats, qdap, ggwordcloud, dplyr, ragg, checkmate, visNetwork, lubridate, methods, ggmap
Imports: stringi, qdapRegex, readr, tokenizers, data.table, ggplot2, anytime, mgsub, stats, qdap, ggwordcloud, dplyr, ragg, checkmate, visNetwork, lubridate, methods, leaflet
Encoding: UTF-8
LazyData: true
RoxygenNote: 7.2.3
Expand Down
9 changes: 6 additions & 3 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,13 @@ importFrom(dplyr,n)
importFrom(dplyr,row_number)
importFrom(dplyr,summarise)
importFrom(dplyr,ungroup)
importFrom(ggmap,get_stadiamap)
importFrom(ggmap,ggmap)
importFrom(ggmap,register_stadiamaps)
importFrom(ggwordcloud,geom_text_wordcloud_area)
importFrom(grDevices,rainbow)
importFrom(leaflet,addCircleMarkers)
importFrom(leaflet,addLegend)
importFrom(leaflet,addTiles)
importFrom(leaflet,leaflet)
importFrom(leaflet,setView)
importFrom(lubridate,parse_date_time)
importFrom(methods,is)
importFrom(mgsub,mgsub)
Expand Down
111 changes: 40 additions & 71 deletions R/plot_locations.R
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,26 @@
#' @param return_data If TRUE, returns a data frame of LatLon coordinates extracted from the chat for more elaborate plotting. Default is FALSE.
#' @param jitter_value Amount of random jitter to add to the geolocations to hide exact locations. Default value is 0.01. Can be NA for exact locations.
#' @param jitter_seed Seed for adding random jitter to coordinates. Passed to \code{\link[base]{set.seed}}
#' @param map_leeway Adds additional space to the map so that points do not sit exactly at the border of the plot. Default value is 5.
#' @param exclude_sm If TRUE, excludes the 'WhatsApp' system messages from the descriptive statistics. Default is FALSE.
#' @param API_key API key for \code{\link[ggmap]{register_stadiamaps}}. Default is "fbb7105f-27c1-49a0-96f8-926dfddcae32". See also: \url{https://rdrr.io/cran/ggmap/man/register_stadiamaps.html}
#' @param map_type Type of map to be used. Passed down to \code{\link[ggmap]{get_stadiamap}}. Default is "alidade_smooth".
#' @import ggplot2
#' @importFrom anytime anytime
#' @importFrom dplyr %>%
#' @importFrom dplyr group_by
#' @importFrom dplyr summarise
#' @importFrom ggmap get_stadiamap
#' @importFrom ggmap register_stadiamaps
#' @importFrom ggmap ggmap
#' @importFrom leaflet leaflet
#' @importFrom leaflet addTiles
#' @importFrom leaflet setView
#' @importFrom leaflet addCircleMarkers
#' @importFrom leaflet addLegend
#' @importFrom grDevices rainbow
#' @importFrom stats runif
#' @importFrom stringi stri_extract_all
#' @importFrom methods is
#' @export
#' @return Plots for geolocation and/or a data frame of latitude and longitude coordinates
#' @examples
#' data <- readRDS(system.file("ParsedWhatsAppChat.rds", package = "WhatsR"))
#' plot_locations(data, mapzoom = 10)
#' plot_locations(data)
#'
### Plotting locations conained in WhatsApp chat logs on maps
plot_locations <- function(data,
Expand All @@ -36,29 +36,14 @@ plot_locations <- function(data,
endtime = "2200-01-01 00:00",
mapzoom = 5,
return_data = FALSE,
jitter_value = 0.01,
jitter_seed = 123,
map_leeway = 0.1,
exclude_sm = FALSE,
API_key = "fbb7105f-27c1-49a0-96f8-926dfddcae32",
map_type = "alidade_smooth") {
jitter_value = NA,
jitter_seed = 12345,
exclude_sm = FALSE
) {

# First of all, we assign local variable with NULL to prevent package build error: https://www.r-bloggers.com/no-visible-binding-for-global-variable/
cond <- Lon <- Lat <- Sender <- NULL

# catching bad params

# API Key
tryCatch({
register_stadiamaps(API_key, write = FALSE)
}, warning = function(warning_condition) {
message(cond)
}, error = function(error_condition) {
message("An error occured while registering the Stadiamaps API key. Please check your API key and try again.")
message(error_condition)
}, finally = {
})

# checking data
if (!is.data.frame(data)) {stop("'data' must be a dataframe parsed with parse_chat()")}

Expand Down Expand Up @@ -110,8 +95,7 @@ plot_locations <- function(data,
# limiting data to time and namescope
data <- data[is.element(data$Sender, names) & data$DateTime >= starttime & data$DateTime <= endtime, ]

# extracting locations with geocoordinates
# TODO: Subset to only use google maps locations!
# extracting locations with geo-coordinates
Places <- unlist(stri_extract_all(data$Location, regex = "(<?)https://maps.google.com.*"))
Places <- Places[!is.na(Places)]

Expand Down Expand Up @@ -142,45 +126,34 @@ plot_locations <- function(data,
LatLong <- cbind.data.frame(Metainfo, LatLong)

# round locations and add some leeway
location <- c(
floor(min(LatLong[, 4])) - map_leeway,
floor(min(LatLong[, 3])) - map_leeway,
ceiling(max(LatLong[, 4])) + map_leeway,
ceiling(max(LatLong[, 3])) + map_leeway
)

# Fetch the map [This should fail gracefully when there's no internet connection]
map <- tryCatch(
{
# trying to download map data
get_stadiamap(bbox = location, maptype = map_type, zoom = mapzoom, messaging = FALSE)
},
error = function(err) {
message("Could not download Stadiamaps map data. Do you have an Internet connection?")
#message(err)
return(NULL)
},
warning = function(warn) {
message("get_map()= returned a warning:")
message(warn)
return(NULL)
}
)

if (!is.null(map)) {

# Add the points layer
map <- ggmap(map) +
geom_point(data = LatLong, aes(x = Lon, y = Lat, fill = Sender), color = "black", size = 2, pch = 21) +
labs(
title = "Locations in Conversation",
subtitle = paste(starttime, " - ", endtime),
x = "Longitude",
y = "Latitude"
)

# plot
plot(map)
#location <- c(
# floor(min(LatLong[, 4])) - map_leeway,
# floor(min(LatLong[, 3])) - map_leeway,
# ceiling(max(LatLong[, 4])) + map_leeway,
# ceiling(max(LatLong[, 3])) + map_leeway
# )

# Create a color palette
unique_senders <- unique(LatLong$Sender)
colors <- rainbow(length(unique_senders))

# Assign colors to groups by creating a factor with levels in the order of appearance
LatLong$color <- colors[match(LatLong$Sender, unique_senders)]

# plotting
map <- leaflet(LatLong) %>%
addTiles() %>%
setView(LatLong$Lon[1],LatLong$Lat[1],zoom = mapzoom) %>%
addCircleMarkers(~Lon,
~Lat,
color = ~color,
popup = ~DateTime,
radius = 6,
fillOpacity = 0.9) %>%
addLegend("bottomleft",
colors = colors,
labels = unique_senders,
title = "Sender")

# returning LatLon data if desired
if (return_data == TRUE) {
Expand All @@ -189,8 +162,4 @@ plot_locations <- function(data,
return(map)
}


} else{return(NA)}


}
Binary file modified inst/test_location1.rds
Binary file not shown.
Binary file modified inst/test_location2.rds
Binary file not shown.
Binary file modified inst/test_location3.rds
Binary file not shown.
Binary file modified inst/test_location4.rds
Binary file not shown.
17 changes: 4 additions & 13 deletions man/plot_locations.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 0 additions & 4 deletions tests/testthat/test-WhatsR-tests.R
Original file line number Diff line number Diff line change
Expand Up @@ -1416,7 +1416,6 @@ test_that("Plotting Media", {
jitter_val = 1,
jitter_seed = 123,
mapzoom = 10,
map_leeway = 0.1,
exclude_sm = TRUE)


Expand All @@ -1431,7 +1430,6 @@ test_that("Plotting Media", {
jitter_val = NA,
jitter_seed = 567,
mapzoom = 10,
map_leeway = 0.1,
exclude_sm = TRUE)

# generate and write file [Use this to recreate test files when parse_chat() changed]
Expand All @@ -1447,7 +1445,6 @@ test_that("Plotting Media", {
jitter_val = 0.5,
jitter_seed = 890,
mapzoom = 10,
map_leeway = 0.1,
exclude_sm = TRUE)

# generate and write file [Use this to recreate test files when parse_chat() changed]
Expand All @@ -1462,7 +1459,6 @@ test_that("Plotting Media", {
jitter_val = 0.5,
jitter_seed = 345,
mapzoom = 10,
map_leeway = 0.3,
exclude_sm = TRUE)

# generate and write file [Use this to recreate test files when parse_chat() changed]
Expand Down

0 comments on commit 4b35af6

Please sign in to comment.