开发 stat_contour 的修改版本
Develop a modified version of stat_contour
我最终试图绘制不规则数据集的等高线图或“光栅图”——这当然是一个相当常见的问题。许多解决方案建议先对数据进行插值,然后绘制它,例如这里:Plotting contours on an irregular grid amongst other - or in fact, the man page at https://ggplot2.tidyverse.org/reference/geom_contour.html
但是,为了方便起见,我试图将其包装到一个新的统计数据中。
我设法获得了适用于 geom_raster 的东西,只需从手册中的示例中提取插值代码即可:
require(akima)
StatInterpRaster <- ggproto("StatInterpRaster", Stat,
compute_group = function(data, scales) {
ii<-akima::interp(x = data$x,
y = data$y,
z = data$fill)
data.out <- tibble(x = rep(ii$x, nrow(ii$z)),
y = rep(ii$y, each = ncol(ii$z)),
fill = as.numeric(ii$z) )
return(data.out)
},
required_aes = c("x", "y", "fill")
)
stat_interp_raster<- function(mapping = NULL, data = NULL, geom = "contour",
position = "identity", na.rm = FALSE, show.legend = NA,
inherit.aes = TRUE, ...) {
layer(
stat = StatInterpRaster, data = data, mapping = mapping, geom = geom,
position = position, show.legend = show.legend, inherit.aes = inherit.aes,
params = list(na.rm = na.rm, ...)
)
}
按预期工作:
ee <- tibble (x=rnorm(50),y=rnorm(50),z=x*y)
ee %>% ggplot() + geom_raster(aes(x=x,y=y,fill=z),stat=StatInterpRaster)
我现在想用等高线来达到同样的效果。我天真地尝试了
StatInterpContour <- ggproto("StatInterpContour", Stat,
compute_group = function(data, scales) {
ii<-akima::interp(x = data$x,
y = data$y,
z = data$z)
data.out <- tibble(x = rep(ii$x, nrow(ii$z)),
y = rep(ii$y, each = ncol(ii$z)),
z = as.numeric(ii$z) )
#StatContour(data.out)
return(data.out)
},
required_aes = c("x", "y", "z")
)
stat_interp_contour<- function(mapping = NULL, data = NULL, geom = "contour",
position = "identity", na.rm = FALSE, show.legend = NA,
inherit.aes = TRUE, ...) {
layer(
stat = StatInterpContour, data = data, mapping = mapping, geom = geom,
position = position, show.legend = show.legend, inherit.aes = inherit.aes,
params = list(na.rm = na.rm, ...)
)
}
与上面基本相同。但是它不会产生预期的结果:
ee %>% ggplot() + geom_contour(aes(x=x,y=y,z=z),stat=StatInterpContour)
回想起来,这并不奇怪。我的 stat 正在生成一个常规数据数组,在 x 和 y 中具有整齐有序的值,但我没有在任何地方生成实际的行。轮廓线更复杂,似乎是由 stat_contour 中的 xyz_to_isolines
生成的(参见 https://github.com/tidyverse/ggplot2/blob/main/R/stat-contour.r ,截至今天的第 97 行)。
我可以复制stat-contour.r中的相关代码,但在我看来这是浪费精力,最好将我的结果简单地传递给stat_contour,那已经完成了工作:它从该形状的对象生成轮廓线。所以显然我“只是”必须在我的 StatInterpContour
函数 compute_group
的某处调用 StatContour(或朋友)——但是如何呢?
谢谢!
你是对的,你不需要从 StatContour
复制代码。相反,让你的 ggproto
class 继承 来自 StatContour
。准备数据,然后将其连同所有必要的参数一起传递给 StatContour
中的 compute_group
函数
StatInterpContour <- ggproto("StatInterpRaster", StatContour,
compute_group = function(data, scales, z.range, bins = NULL, binwidth = NULL,
breaks = NULL, na.rm = FALSE) {
ii<-akima::interp(x = data$x,
y = data$y,
z = data$z)
data <- tibble(x = rep(ii$x, nrow(ii$z)),
y = rep(ii$y, each = ncol(ii$z)),
z = as.numeric(ii$z), group = 1)
StatContour$compute_group(data, scales, z.range,
bins, binwidth, breaks, na.rm)
},
required_aes = c("x", "y", "z")
)
这需要对您的 user-facing 函数稍作修改:
stat_interp_contour<- function(mapping = NULL, data = NULL, geom = "contour",
position = "identity", na.rm = FALSE,
show.legend = NA,
inherit.aes = TRUE, bins = NULL, binwidth = NULL,
breaks = NULL, ...) {
layer(
stat = StatInterpContour, data = data, mapping = mapping, geom = geom,
position = position, show.legend = show.legend, inherit.aes = inherit.aes,
params = list(na.rm = na.rm, bins = bins, binwidth = binwidth,
breaks = breaks, ...)
)
}
但现在应该没有按预期工作。在这里,我将它与根据其 z 值着色的原始点一起绘制,以表明等高线试图接近点的水平:
ee %>%
ggplot(aes(x, y)) +
geom_point(aes(color = z), size = 3) +
stat_interp_contour(aes(z = z, color = after_stat(level))) +
scale_color_viridis_c()
我最终试图绘制不规则数据集的等高线图或“光栅图”——这当然是一个相当常见的问题。许多解决方案建议先对数据进行插值,然后绘制它,例如这里:Plotting contours on an irregular grid amongst other - or in fact, the man page at https://ggplot2.tidyverse.org/reference/geom_contour.html
但是,为了方便起见,我试图将其包装到一个新的统计数据中。
我设法获得了适用于 geom_raster 的东西,只需从手册中的示例中提取插值代码即可:
require(akima)
StatInterpRaster <- ggproto("StatInterpRaster", Stat,
compute_group = function(data, scales) {
ii<-akima::interp(x = data$x,
y = data$y,
z = data$fill)
data.out <- tibble(x = rep(ii$x, nrow(ii$z)),
y = rep(ii$y, each = ncol(ii$z)),
fill = as.numeric(ii$z) )
return(data.out)
},
required_aes = c("x", "y", "fill")
)
stat_interp_raster<- function(mapping = NULL, data = NULL, geom = "contour",
position = "identity", na.rm = FALSE, show.legend = NA,
inherit.aes = TRUE, ...) {
layer(
stat = StatInterpRaster, data = data, mapping = mapping, geom = geom,
position = position, show.legend = show.legend, inherit.aes = inherit.aes,
params = list(na.rm = na.rm, ...)
)
}
按预期工作:
ee <- tibble (x=rnorm(50),y=rnorm(50),z=x*y)
ee %>% ggplot() + geom_raster(aes(x=x,y=y,fill=z),stat=StatInterpRaster)
我现在想用等高线来达到同样的效果。我天真地尝试了
StatInterpContour <- ggproto("StatInterpContour", Stat,
compute_group = function(data, scales) {
ii<-akima::interp(x = data$x,
y = data$y,
z = data$z)
data.out <- tibble(x = rep(ii$x, nrow(ii$z)),
y = rep(ii$y, each = ncol(ii$z)),
z = as.numeric(ii$z) )
#StatContour(data.out)
return(data.out)
},
required_aes = c("x", "y", "z")
)
stat_interp_contour<- function(mapping = NULL, data = NULL, geom = "contour",
position = "identity", na.rm = FALSE, show.legend = NA,
inherit.aes = TRUE, ...) {
layer(
stat = StatInterpContour, data = data, mapping = mapping, geom = geom,
position = position, show.legend = show.legend, inherit.aes = inherit.aes,
params = list(na.rm = na.rm, ...)
)
}
与上面基本相同。但是它不会产生预期的结果:
ee %>% ggplot() + geom_contour(aes(x=x,y=y,z=z),stat=StatInterpContour)
回想起来,这并不奇怪。我的 stat 正在生成一个常规数据数组,在 x 和 y 中具有整齐有序的值,但我没有在任何地方生成实际的行。轮廓线更复杂,似乎是由 stat_contour 中的 xyz_to_isolines
生成的(参见 https://github.com/tidyverse/ggplot2/blob/main/R/stat-contour.r ,截至今天的第 97 行)。
我可以复制stat-contour.r中的相关代码,但在我看来这是浪费精力,最好将我的结果简单地传递给stat_contour,那已经完成了工作:它从该形状的对象生成轮廓线。所以显然我“只是”必须在我的 StatInterpContour
函数 compute_group
的某处调用 StatContour(或朋友)——但是如何呢?
谢谢!
你是对的,你不需要从 StatContour
复制代码。相反,让你的 ggproto
class 继承 来自 StatContour
。准备数据,然后将其连同所有必要的参数一起传递给 StatContour
compute_group
函数
StatInterpContour <- ggproto("StatInterpRaster", StatContour,
compute_group = function(data, scales, z.range, bins = NULL, binwidth = NULL,
breaks = NULL, na.rm = FALSE) {
ii<-akima::interp(x = data$x,
y = data$y,
z = data$z)
data <- tibble(x = rep(ii$x, nrow(ii$z)),
y = rep(ii$y, each = ncol(ii$z)),
z = as.numeric(ii$z), group = 1)
StatContour$compute_group(data, scales, z.range,
bins, binwidth, breaks, na.rm)
},
required_aes = c("x", "y", "z")
)
这需要对您的 user-facing 函数稍作修改:
stat_interp_contour<- function(mapping = NULL, data = NULL, geom = "contour",
position = "identity", na.rm = FALSE,
show.legend = NA,
inherit.aes = TRUE, bins = NULL, binwidth = NULL,
breaks = NULL, ...) {
layer(
stat = StatInterpContour, data = data, mapping = mapping, geom = geom,
position = position, show.legend = show.legend, inherit.aes = inherit.aes,
params = list(na.rm = na.rm, bins = bins, binwidth = binwidth,
breaks = breaks, ...)
)
}
但现在应该没有按预期工作。在这里,我将它与根据其 z 值着色的原始点一起绘制,以表明等高线试图接近点的水平:
ee %>%
ggplot(aes(x, y)) +
geom_point(aes(color = z), size = 3) +
stat_interp_contour(aes(z = z, color = after_stat(level))) +
scale_color_viridis_c()