Skip to content

Instantly share code, notes, and snippets.

@tim-salabim
Last active September 5, 2017 19:14
Show Gist options
  • Save tim-salabim/2c4641e6767d6168b2f2b4445101609c to your computer and use it in GitHub Desktop.
Save tim-salabim/2c4641e6767d6168b2f2b4445101609c to your computer and use it in GitHub Desktop.
Produce scatterplots with mapview and sf
library(mapview)
library(sf)
xyGrid = function(x) {
# x = iris_sf
xrange = mapview:::extendLimits(c(st_bbox(x)[["xmin"]], st_bbox(x)[["xmax"]]))
yrange = mapview:::extendLimits(c(st_bbox(x)[["ymin"]], st_bbox(x)[["ymax"]]))
xticks = pretty(xrange)
yticks = pretty(yrange)
hline = lapply(yticks, function(i) {
st_linestring(rbind(cbind(xticks[1], i), cbind(xticks[length(xticks)], i)))
})
vline = lapply(xticks, function(i) {
st_linestring(cbind(rbind(i, i), rbind(yticks[1], yticks[length(yticks)])))
})
hlines = st_sfc(hline[2:(length(hline)-1)], crs = st_crs(x))
vlines = st_sfc(vline[2:(length(vline)-1)], crs = st_crs(x))
hlabs = yticks[2:(length(yticks)-1)]
vlabs = xticks[2:(length(xticks)-1)]
out = mapview(hlines,
color = "black",
label = as.character(hlabs),
lwd = 1,
alpha = 0.5,
homebutton = FALSE) %>%
mapview(vlines,
map = .,
color = "black",
label = as.character(vlabs),
lwd = 1,
alpha = 0.5,
homebutton = FALSE)
out = out@map %>%
leaflet::addLabelOnlyMarkers(rep(xticks[1], length(hlabs)), hlabs,
label = as.character(hlabs),
labelOptions = labelOptions(noHide = T,
direction = "left",
textOnly = TRUE,
offset = c(0, -10),
opacity = 0.5)) %>%
leaflet::addLabelOnlyMarkers(vlabs, rep(yticks[1], length(vlabs)),
label = as.character(vlabs),
labelOptions = labelOptions(noHide = T,
direction = "left",
textOnly = TRUE,
offset = c(-10, 0),
opacity = 0.5))
return(out)
}
xyView = function(data, x, y, ...) {
nm = deparse(substitute(data))
data = sf::st_as_sf(data, coords = c(x, y), remove = FALSE)
out = xyGrid(data) %>%
mapview(data, map = .,
label = as.character(format(st_geometry(data))),
layer.name = nm,
...)
return(out)
# out@map %>%
# leaflet::addLabelOnlyMarkers(lng = min(data[[x]]), lat = max(data[[y]]),
# label = as.character(x),
# labelOptions = labelOptions(noHide = T,
# direction = "left",
# textOnly = TRUE,
# offset = c(0, -30),
# opacity = 0.5)) %>%
# leaflet::addLabelOnlyMarkers(lng = max(data[[x]]), lat = min(data[[y]]),
# label = as.character(y),
# labelOptions = labelOptions(noHide = T,
# direction = "right",
# textOnly = TRUE,
# offset = c(30, 10),
# opacity = 0.5))
}
xyView(x = "Petal.Length", y = "Petal.Width", data = iris, zcol = "Sepal.Length", legend = TRUE)
xyView(breweries)
@tim-salabim
Copy link
Author

UPDATE: now also supports line plots + with the latest mapedit develop version, select via draw should work

library(mapview)
library(sf)

xyGrid = function(x) {
  # x = iris_sf
  
  xrange = mapview:::extendLimits(
    c(sf::st_bbox(x)[["xmin"]], 
      sf::st_bbox(x)[["xmax"]])
  )
  yrange = mapview:::extendLimits(
    c(sf::st_bbox(x)[["ymin"]], 
      sf::st_bbox(x)[["ymax"]])
  )
  
  xticks = pretty(xrange)
  xstep = unique(diff(xticks))
  xticks = c(
    xticks[1] + xstep * 0.3, 
    xticks[2:(length(xticks)-1)], 
    xticks[length(xticks)] - xstep * 0.3
  )
  yticks = pretty(yrange)
  ystep = unique(diff(yticks))
  yticks = c(
    yticks[1] + ystep * 0.3, 
    yticks[2:(length(yticks)-1)], 
    yticks[length(yticks)] - ystep * 0.3
  )
  
  hline = lapply(yticks, function(i) {
    sf::st_linestring(
      rbind(cbind(xticks[1], i), cbind(xticks[length(xticks)], i))
    )
  })
  
  vline = lapply(xticks, function(i) {
    sf::st_linestring(
      cbind(rbind(i, i), rbind(yticks[1], yticks[length(yticks)]))
    )
  })
  
  hlines = sf::st_sfc(hline[2:(length(hline)-1)], crs = sf::st_crs(x))
  vlines = sf::st_sfc(vline[2:(length(vline)-1)], crs = sf::st_crs(x))
  
  hlabs = yticks[2:(length(yticks)-1)]
  vlabs = xticks[2:(length(xticks)-1)]
  
  out = mapview(
    c(hlines, vlines),
    layer.name = "grid",
    color = "black", 
    label = as.character(hlabs), 
    lwd = 1,
    alpha = 0.5,
    homebutton = FALSE
  ) 
  
  out = out@map %>% 
    leaflet::addLabelOnlyMarkers(
      rep(xticks[1], length(hlabs)), hlabs,
      label = as.character(hlabs),
      labelOptions = leaflet::labelOptions(
        noHide = T, 
        direction = "left",
        textOnly = TRUE,
        offset = c(0, -10),
        opacity = 0.5
      )
    ) %>% 
    leaflet::addLabelOnlyMarkers(
      vlabs, rep(yticks[1], length(vlabs)),
      label = as.character(vlabs),
      labelOptions = leaflet::labelOptions(
        noHide = T, 
        direction = "left",
        textOnly = TRUE,
        offset = c(-10, 0),
        opacity = 0.5
      )
    )
  
  return(out)
}


xyView = function(x, y, data, type = "p", ...) {
  
  if (!missing(data)) {
    nm = deparse(substitute(data))
    data = sf::st_as_sf(data, coords = c(x, y), remove = FALSE)
  } else if (missing(x) | missing(y)) {
    stop("need both x and y if data is missing")
  } else {
    data = sf::st_as_sf(
      data.frame(x = x, y = y), 
      coords = c("x", "y"), 
      remove = FALSE
    )
    nm = "data"
  }
   
  if (type == "l") {
    data = sf::st_sfc(
      sf::st_cast(
        sf::st_combine(
          data
          ), 
        to = "LINESTRING"
      ) %>% 
        .[[1]]
    )
  }
  
  out = xyGrid(data) %>%
    mapview(
      data, map = ., 
      label =  as.character(format(st_geometry(data))),
      layer.name = nm,
      highlight = NULL,
      ...
    )
  return(out)
}
  

xyView(
  data = iris, 
  x = "Petal.Length", 
  y = "Petal.Width", 
  zcol = "Sepal.Length", 
  legend = TRUE, 
  type = "p"
)

xyView(data = breweries)

xyView(1:100, runif(100, 5, 50), type = "l")

xyView(iris$Petal.Length, iris$Petal.Width)

# devtools::install_github("r-spatial/mapedit")
library(mapedit)
iris_sf = st_as_sf(iris, coords = c("Petal.Length", "Petal.Width"), remove = FALSE)
sel = mapedit::selectFeatures(iris_sf, map = xyGrid(iris_sf), mode = "draw")

xyView(data = sel)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment