如何在R中平滑stat_density_2d_filled实现正态分布圆形分层?
解决方案:生成嵌套圆形的填充密度图
你的核心问题是stat_density_2d_filled会贴合原始数据的分布生成等高线,若数据本身非圆形分布,仅调整bins或换用其他密度函数无法得到规则圆形。要强制生成层层嵌套的圆形,需绕过二维核密度估计,改用径向密度统计或直接生成圆形轮廓。
方法1:基于径向密度的自定义圆形填充
该方法先计算数据到中心的径向距离,对距离做一维密度估计,再生成对应密度层级的圆形轮廓:
library(ggplot2) library(dplyr) library(purrr) library(tibble) # 替换为你的数据集 your_data <- mtcars %>% select(wt, mpg) # 1. 计算数据中心(可替换为自定义中心,如原点) center <- c(mean(your_data$wt), mean(your_data$mpg)) # 2. 计算每个点到中心的径向距离 your_data <- your_data %>% mutate(r = sqrt((wt - center[1])^2 + (mpg - center[2])^2)) # 3. 对径向距离做密度估计,提取ndensity层级对应的半径 r_density <- density(your_data$r) ndensity_levels <- seq(0.2, 1, by = 0.2) # 对应原bins=5的层级 radius_vals <- sapply(ndensity_levels, function(level) { r_density$x[which.min(abs(r_density$y/max(r_density$y) - level))] }) # 4. 生成每个半径对应的圆形坐标 circle_coords <- map_dfr(radius_vals, function(r) { theta <- seq(0, 2*pi, length.out = 100) tibble( x = center[1] + r*cos(theta), y = center[2] + r*sin(theta), ndensity = level ) }) # 5. 绘制填充图 ggplot() + geom_polygon(data = circle_coords, aes(x = x, y = y, group = ndensity, fill = ndensity)) + scale_fill_viridis_c(name = "ndensity") + theme_minimal()
方法2:用ggforce快速生成嵌套圆形
若无需严格匹配密度分布,仅需基于径向距离分位数生成圆形,可使用ggforce的geom_circle:
library(ggplot2) library(ggforce) library(dplyr) your_data <- mtcars %>% select(wt, mpg) center <- c(mean(your_data$wt), mean(your_data$mpg)) your_data <- your_data %>% mutate(r = sqrt((wt - center[1])^2 + (mpg - center[2])^2)) # 计算对应ndensity层级的径向分位数 ndensity_levels <- seq(0.2, 1, by = 0.2) radius_quantiles <- quantile(your_data$r, probs = ndensity_levels) ggplot() + geom_circle(aes(x0 = center[1], y0 = center[2], r = r, fill = r), data = tibble(r = radius_quantiles)) + scale_fill_viridis_c(name = "ndensity") + theme_minimal()
关键说明
- 两种方法均强制生成圆形轮廓,不受原始数据分布影响;
- 若需自定义中心,直接修改
center变量即可(如设为c(0,0)); ndensity_levels可调整层级数量,对应原bins参数。
内容的提问来源于stack exchange,提问作者Jackson Del Rosario
相关产品推荐
相关产品推荐

