使用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
相关产品推荐
相关产品推荐

