You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用stat_density2d_filled搭配scale_fill_gradient报错求助

问题:stat_density2d_filled搭配scale_fill_gradient报错的解决办法

问题描述

尝试用stat_density2d_filled基于点位置生成热图,stat_density2d会产生难看的伪影;stat_density2d可与scale_fill_gradient正常配合,但stat_density2d_filled搭配该刻度时出现报错:

Error: Discrete value supplied to continuous scale

以下示例代码中前两幅图可正常运行,第三幅图报错:

rm(list = ls())

library(tidyverse)
library(tidygeocoder)
library(rnaturalearth)

no <- ne_states(geounit = "Norway", returnclass = "sf") 

no_south <- no %>%
  filter(name == "Aust-Agder" | 
           name == "Vest-Agder" |
           name == "Telemark") 

towns <- tribble(
  ~town, 
  "Kristiansand, NO", 
  "Søgne, NO",              
  "Vennesla, NO",
  "Arendal, NO",
  "Lillesand Town, NO",
  "Porsgrunn, NO",
  "Skien, NO") %>%
  tidygeocoder::geocode(town, method = "osm", 
                        lat = latitude , long = longitude) 

# Map with stat_density_2d and scale_fill_gradient works:
ggplot(data = no_south) +
  geom_sf() +
  stat_density_2d(data = towns,
                        aes(x = longitude, y = latitude,
                            fill = after_stat(level)),
                  geom = "polygon",
                  alpha = 0.5) +
  scale_fill_gradient() +
  geom_point(data = towns,
             aes(x = longitude, y = latitude),
             size = rel(3),
             shape = 20) 

# Map with stat_density_2d_filled and withouth scale_fill_gradient works:
ggplot(data = no_south) +
  geom_sf() +
  stat_density2d_filled(data = towns,
                        aes(x = longitude, y = latitude,
                            fill = after_stat(level)),
                        alpha = 0.5) +
  # scale_fill_gradient() +
  geom_point(data = towns,
             aes(x = longitude, y = latitude),
             size = rel(3),
             shape = 20) 

# Map with stat_density_2d_filled and scale_fill_gradient does not work:
ggplot(data = no_south) +
  geom_sf() +
  stat_density2d_filled(data = towns,
                        aes(x = longitude, y = latitude,
                            fill = after_stat(level)),
                        alpha = 0.5) +
  scale_fill_gradient() +
  geom_point(data = towns,
             aes(x = longitude, y = latitude),
             size = rel(3),
             shape = 20) 

原因分析

  • stat_density2d返回的after_stat(level)是连续数值,因此可以适配scale_fill_gradient这类要求连续输入的填充刻度
  • stat_density2d_filled返回的after_stat(level)是离散的区间因子(例如[0,0.2), [0.2,0.4)这类分组标签),属于离散变量,无法适配连续刻度,因此触发报错

解决方案

方案1:使用离散填充刻度适配stat_density2d_filled

既然stat_density2d_filled输出的是离散区间,直接使用离散填充刻度即可,这类刻度也能生成渐变风格的视觉效果,推荐使用scale_fill_viridis_d(自带美观的配色)或scale_fill_brewer:

修改后的第三幅图代码:

ggplot(data = no_south) +
  geom_sf() +
  stat_density2d_filled(data = towns,
                        aes(x = longitude, y = latitude,
                            fill = after_stat(level)),
                        alpha = 0.5) +
  # 改用离散渐变刻度,option参数可调整配色风格
  scale_fill_viridis_d(option = "plasma") +
  geom_point(data = towns,
             aes(x = longitude, y = latitude),
             size = rel(3),
             shape = 20) 

方案2:调整stat_density2d参数消除伪影

如果坚持需要连续填充效果,可以回到stat_density2d,通过调整参数消除伪影:

  • 增加n参数提升计算分辨率,减少锯齿
  • 调整bins参数增加轮廓数量,让填充过渡更平滑

示例代码:

ggplot(data = no_south) +
  geom_sf() +
  stat_density_2d(data = towns,
                  aes(x = longitude, y = latitude,
                      fill = after_stat(level)),
                  geom = "polygon",
                  alpha = 0.5,
                  n = 500,  # 提升计算精度,减少伪影
                  bins = 15)  # 增加轮廓数量,优化过渡效果
  scale_fill_gradient(low = "lightblue", high = "darkred") +
  geom_point(data = towns,
             aes(x = longitude, y = latitude),
             size = rel(3),
             shape = 20) 

内容的提问来源于stack exchange,提问作者Del

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 18:15:01