通过ggproto扩展ggplot2时设置默认值的技术问题咨询
自定义ggplot2 Stat层:关于
setup_params中数据与参数的疑问解析 我最近跟着ggplot2扩展相关的内容写自定义Stat时,给代码加了print()语句来追踪每一步的变量变化,现在把修改后的代码贴出来,疑问标在注释里:
StatDensityCommon <- ggproto("StatDensityCommon", Stat, required_aes = "x", setup_params = function(data, params) { print("PARAMS BEFORE:") print(params) if(!is.null(params$bandwidth)) return(params) print("DATA: ") print(data) # 疑问1:这里的data具体是什么结构?为什么要在这里获取全部数据来计算带宽? # 补全原教程的带宽计算逻辑 xs <- data$x params$bandwidth <- bw.nrd0(xs) params }, compute_group = function(data, scales, bandwidth = NULL, na.rm = FALSE) { # 用共享带宽计算密度的核心逻辑 density(data$x, bw = bandwidth, na.rm = na.rm) %>% ggplot2:::rename(as.data.frame(.), x = x, density = y) %>% mutate(count = density * nrow(data)) } ) # 示例调用 ggplot(faithful, aes(x = eruptions, colour = waiting > 70)) + stat_density_common(geom = "line")
针对疑问的解释:
data的结构:这里的data是ggplot2传递给Stat层的全部分组预处理数据,是一个data.frame,包含你映射的x变量,还有自动生成的group列(如果有分组映射,比如示例里的colour = waiting > 70),以及其他可能的美学映射列。它不是单个分组的子集,而是所有要计算的观测值的集合。- 为什么在这里计算带宽:这个自定义Stat的核心是让所有分组共享同一个带宽,而不是默认的每个分组单独计算带宽。所以必须在
setup_params里拿到全部的x值,用全局数据计算出一个统一的带宽,再传递给每个分组的compute_group函数使用。
运行时print()的输出示例:
- 首先会打印初始的
params(默认是list(bandwidth = NULL, na.rm = FALSE)) - 然后打印
data,比如示例里的faithful数据,会包含eruptions列和group列(对应waiting > 70的两个分组) - 最后计算出
bandwidth并更新params
这样就能实现所有分组用同一个带宽绘制密度线的效果啦~
内容的提问来源于stack exchange,提问作者passiflora
相关产品推荐
相关产品推荐

