8

I'm trying for a divergent scale theme in mapview to help visualize gains vs. losses, with:

  • point symbol circle sizes on an absolute value scale (to highlight losses as much as gains)
  • a divergent color scale fill for the circles (say dark blue>blue>white>red>dark red for most negative>negative>zero>positive>largest)
  • mouse over hover label of the original value retained

any ideas?


library(tidyverse)
library(mapview)
library(sf)

lat <- rep(34,16)
lon <- seq(-128, -126, length = 16)
value <- c(-1000, -800, -600, -400, -200, -100, -50, 
            -25, 25, 50, 100, 200, 400, 600, 800, 1000)

#make data.frame
df <- data.frame(lat, lon, value) 

#make spatial object for mapview
df <- st_as_sf(df, coords = c("lon", "lat"), crs = 4326) %>%
      mutate(value_abs = abs(value)) #value_abs intended for `cex` argument

pal <-  mapviewPalette("mapviewSpectralColors") #from mapview doc. example
m   <-  mapview(df["value"], #sets hover over value as this column
         cex = "value",      #sets circle diameter scaling on this column
         legend = TRUE,
         col.regions = pal(100), #closest I found to a red-blue divergent scale
         layer.name = "value")  
m

In other words, I'm hoping for the pattern of points here below to be symmetrical with the left side as a mirror image of the right in size, but with blue circles at left, red at right, and still allowing the user to see the actual (non absolute) values (e.g. -1000) by mouseover.

enter image description here

attempts: switching cex = "value" with cex = "value_abs" yields warning: In min(x) : no non-missing arguments to min; returning Inf without any points drawn, or with cex = df$value_abs (no quotes), which makes uncolored, enormous points. I'm not planning on needing two legends - just one for either the circle size or fill, showing a min and max value like it does now, would be great.

zx8754
  • 52,746
  • 12
  • 114
  • 209
dbo
  • 1,174
  • 1
  • 11
  • 19
  • Editing your question to improve it is great, but please try to "merge" your edits into more significant chunks. Making [a large number of trivial edits](https://stackoverflow.com/posts/56743265/revisions) increase the noise volume of the site and can be annoying to our users. Thank you for keeping this in mind going forward! – Cody Gray - on strike Jun 25 '19 at 03:32

1 Answers1

4

You are very close. You need to explicitly refer to df$value_abs. Look below:

library(tidyverse)
library(mapview)
library(sf)

df <- data.frame(lat=rep(34,16), 
                 lon=seq(-128, -126, length = 16), 
                 value=c(-1000, -800, -600, -400, -200, -100, -50, 
                         -25, 25, 50, 100, 200, 400, 600, 800, 1000)) 

df <- st_as_sf(df, coords = c("lon", "lat"), crs = 4326) %>%
               mutate(value_abs = abs(value))

pal <-  mapviewPalette("mapviewSpectralColors")

mapview(df["value"], 
                cex = df$value_abs/100, 
                legend = TRUE,
                col.regions = pal(100), 
                layer.name = "value")  

Created on 2019-06-24 by the reprex package (v0.3.0)

M--
  • 25,431
  • 8
  • 61
  • 93
  • 1
    But there no info about the symbol size in the legend? – Herman Toothrot Jan 03 '20 at 13:05
  • 1
    Using cex is somewhat of a hack, isn't it? even using mutate I find it hard to have some balanced-sized points. The difference between the large and small points is too big. – Herman Toothrot Jan 03 '20 at 14:47
  • 2
    @HermanToothrot I don't understand why you calling it a *"hack"*. OP didn't ask for size to be a part of the legend. Please post a new question if you have follow up questions. You can share a link to this post and it's ok to tag me and share a link to that question of yours with me. Cheers. – M-- Jan 03 '20 at 16:54