TL;DR
It seems that r-mapview
cannot handle more than 10 breaks in its at
variable. Look below:
library(tidyverse)
library(sf)
library(mapview)
palfunc <- function (n, alpha = 1, begin = 0, end = 1, direction = 1)
{
colors <- RColorBrewer::brewer.pal(11, "RdBu")
if (direction < 0) colors <- rev(colors)
colorRampPalette(colors, alpha = alpha)(n)
}
set.seed(92)
foo <- franconia %>% mutate(foo = rnorm(n()) + 2)
max_val = max(abs(foo$foo), na.rm = T)
n_val = max( length(unique(keep(foo$foo, ~.x > 0))),
length(unique(keep(foo$foo, ~.x < 0))))
at_10 = lattice::do.breaks(endpoints = c(-max_val, max_val), nint = 10)
mapView(foo, zcol = 'foo', layer.name = "Example", col.regions = palfunc, at = at_10)

at_11 = lattice::do.breaks(endpoints = c(-max_val, max_val), nint = 11)
mapView(foo, zcol = 'foo', layer.name = "Example", col.regions = palfunc, at = at_11)

- When limits of data are actually mirrored around 0:
However, if we actually had the negative value (min(values) ≈ max(values)
), then the legend by default would be centered around 0:
library(tidyverse)
library(sf)
library(mapview)
palfunc <- function (n, alpha = 1, begin = 0, end = 1, direction = 1)
{
colors <- RColorBrewer::brewer.pal(11, "RdBu")
if (direction < 0) colors <- rev(colors)
colorRampPalette(colors, alpha = alpha)(n)
}
set.seed(92)
foo <- franconia %>% mutate(foo = c((rnorm((n()-1)) + 2), -4))
max_val = max(abs(foo$foo), na.rm = T)
n_val = max( length(unique(keep(foo$foo, ~.x > 0))),
length(unique(keep(foo$foo, ~.x < 0))))
mapView(foo, zcol = 'foo', layer.name = "Example", col.regions = palfunc)

Solution:
So, my hacky way to address your problem is adding two rows to your foo
datast with -max_val
and +max_val
which are basically multipolygons
with no area and length (a.k.a. point) so our dataset has mirrored values around zero and therefore mapview
would generate "balanced" legend, however user would not see those points on the map as their area is zero. Look below for, again, hacky implementation. (p.s. If you want to you can add those dummy points/multipolygons somewhere out of the boundary of your data and then set the default zoom to your actual data, which is unnecessary because as I said, those dummy points are not visible).
library(tidyverse)
library(sf)
library(mapview)
palfunc <- function (n, alpha = 1, begin = 0, end = 1, direction = 1)
{
colors <- RColorBrewer::brewer.pal(11, "RdBu")
if (direction < 0) colors <- rev(colors)
colorRampPalette(colors, alpha = alpha)(n)
}
set.seed(92)
foo <- franconia %>% mutate(foo = (rnorm((n())) + 2))
max_val = max(abs(foo$foo), na.rm = T)
n_val = max( length(unique(keep(foo$foo, ~.x > 0))),
length(unique(keep(foo$foo, ~.x < 0))))
#creating a dummy polygon which all of its boundaries point are the same
a_dummy_m <- matrix(c(10.92582, 49.92508, 10.92582, 49.92508,
10.92582, 49.92508, 10.92582, 49.92508,
10.92582, 49.92508),ncol=2, byrow=TRUE)
a_dummy_p <- st_multipolygon(list(list(a_dummy_m), list(a_dummy_m), list(a_dummy_m)))
#mimicking foo structure to make a point with negative value of absolute maximum
dummy_neg <- structure(list(NUTS_ID = "N/A", SHAPE_AREA = st_area(a_dummy_p),
SHAPE_LEN = st_length(a_dummy_p), CNTR_CODE = structure(1L,
.Label = "N/A", class = "factor"),
NAME_ASCI = structure(1L, .Label = c("N/A"), class = "factor"),
geometry = structure(list(a_dummy_p), class = c("sfc_MULTIPOLYGON", "sfc"),
precision = 0, bbox = st_bbox(a_dummy_p),
crs = structure(list(epsg = 4326L,
proj4string = "+proj=longlat +datum=WGS84 +no_defs"),
class = "crs"), n_empty = 0L),
district = "N/A", foo = -max_val), sf_column = "geometry",
agr = structure(c(NUTS_ID = NA_integer_, SHAPE_AREA = NA_integer_,
SHAPE_LEN = NA_integer_, CNTR_CODE = NA_integer_,
NAME_ASCI = NA_integer_, district = NA_integer_,
foo = NA_integer_),
.Label = c("constant", "aggregate", "identity"), class = "factor"),
row.names = 1L, class = c("sf", "data.frame"))
#and now making the data with positive value
dummy_pos <- dummy_neg %>% mutate(foo=max_val)
#row binding those with `foo` dataset to make a new dataset which is "balanced"
foo2 <- rbind(dummy_neg, dummy_pos,foo)
mapView(foo2, zcol = 'foo', layer.name = "Example", col.regions = palfunc)

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