我正在尝试创建包含一些负值和大部分为正值的 map 。我拥有的代码(如下所示)会生成正确的 map ,但是图例未居中于0(即白色不在0处,而更多的负值表示深红色,而更多的正值表示蓝色)。无论数据集中的值如何,如何将调色板更改为以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)
}


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 = lattice::do.breaks(endpoints = c(-max_val, max_val), nint = 2 * n_val + 1)
p <- mapView(foo, zcol = 'foo', layer.name = "Example", col.regions = palfunc, at = at)

最佳答案

TL; DR
看来r-mapviewat变量不能处理超过10个中断。往下看:

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))))
  • 10个间隔:

  • 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)
    
  • 11休息时间:

  • 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)
    
  • 当数据限制实际上在0左右镜像时:

  • 但是,如果我们实际上具有负值(min(values) ≈ max(values)),则图例默认情况下将以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)
    

    解:
    因此,我解决问题的方法是在foo数据中添加两行,其中-max_val+max_val基本上是multipolygons,没有面积和长度(aka点),因此我们的数据集的镜像值约为零,因此mapview将生成“平衡”图例,但是用户不会在 map 上看到这些点,因为它们的面积为零。再次在下面查找骇客的实现。 (请注意,如果需要,您可以在数据边界之外的某个位置添加这些虚拟点/多面体,然后将默认缩放比例设置为实际数据,这是不必要的,因为正如我所说,这些虚拟点不可见)。
    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)
    

    reprex package(v0.3.0)创建于2019-06-25

    08-25 10:47
    查看更多