作为起点,我使用 Kat 对这个问题的回答(如何使地图边框的粗糙度小于地图填充的粗糙度)中非常有用的代码来创建两个图表,目的是将其中一个图表放在另一个图表之上。
library(magrittr)
library(ggplot2)
#devtools::install_github("xvrdm/ggrough")
library(ggrough)
library(sf)
library(htmltools)
library(ggiraph)
trace(ggrough:::parse_rough, edit=TRUE)
#In the popup window, paste this so that parse_rough will use parse_sf for GeomSf.
function (svg, geom)
{
rough_els <- list()
if (geom %in% c("GeomCol", "GeomBar", "GeomTile",
"Background")) {
rough_els <- append(rough_els, parse_rects(svg))
}
if (geom %in% c("GeomArea", "GeomViolin", "GeomSmooth",
"Background")) {
rough_els <- append(rough_els, parse_areas(svg))
}
if (geom %in% c("GeomPoint", "GeomJitter", "GeomDotPlot",
"Background")) {
rough_els <- append(rough_els, parse_circles(svg))
}
if (geom %in% c("GeomLine", "GeomSmooth", "Background")) {
rough_els <- append(rough_els, parse_lines(svg))
}
if (geom %in% c("Background")) {
rough_els <- append(rough_els, parse_texts(svg))
}
if (geom %in% c("GeomSf")) {
rough_els <- append(rough_els, parse_sf(svg))
}
purrr::map(rough_els, ~purrr::list_modify(.x, geom = geom))
}
# Create the function parse_sf.
parse_sf <- function (svg) {
shape <- "path"
keys <- NULL
ggrough:::parse_shape(svg, shape, keys) %>% {
purrr::map(.,
~purrr::list_modify(.x,
points = .x$d,
shape = "path"
))
}
}
nc <- sf::st_read(system.file("shape/nc.shp", package = "sf"), quiet = TRUE)
b <- ggplot(nc) + geom_sf(color = "black") + theme_minimal() +
theme(panel.grid = element_line(color = NA), # not resized or removed! (keep spacing)
axis.text = element_text(color = NA))
options <- list(GeomSf = list(fill_style = "hachure", angle = 60, angle_noise = 1,
gap_noise = 0, gap = 6, fill_weight = 2, bowing = 5,
roughness = 30))
(xx <- get_rough_chart(b, options)) # from your question
fixer <- function(ggr) { # where ggr is the ggrough graph
nd <- lapply(1:length(ggr$x$data), function(j) {
if(!is.null(ggr$x$data[[j]]$lengthAdjust)) { # if a text element (axis label)
ggr$x$data[[j]]$content <- "" # remove text, but keep spacing
ggr$x$data[[j]] # return modified data element
} else {
ggr$x$data[[j]] # not text, return orig data
}
})
ggr$x$data <- nd # add mod data to graph
ggr # return mod graph
}
xx2 <- xx %>% fixer() # modify the plot, to hide text
(g2 <- ggplot(nc) +
geom_sf(fill = "transparent", color = "black", linewidth = 2) +
theme_minimal() +
theme(plot.background = element_rect(fill = NA, color = "transparent"), # no white background
panel.background = element_rect(fill = NA, color = "transparent"),
text = element_text(size = 9))) # text size to match defaults in ggrough
gg <- girafe(ggobj = g2, width_svg = 7, height_svg = 5) # h/w default w/ ggrough
browsable(div( # parent div, size matches ggrough's default
style = css(width = "960px", height = "500px", position = "relative"),
div(xx2, style = css(display = "block")), # ggrough graph
div(gg, style = css(position = "absolute", top = 0, padding.top = "54.2px", # layer behind
width = "610px", height = "500px", z.index = -2))
)) # size and padding found by trial and error with defaults for graph sizes
答案中的图表似乎已正确叠加。但是,当我运行相同的代码(在 RStudio 中)时,我得到的叠加是不正确的:
我也在另一台计算机上的 RStudio 上尝试过,也得到了不完美的叠加,但程度不同。
我有两个问题:
- 如何才能正确地叠加图形,而不必反复试验?
- 我该如何调整代码,以便将当前背景切换到前景?换句话说,我该如何让黑色边框位于灰色涂鸦之上,而不是相反?我尝试
div
在结尾处交换两个边框的顺序,但没有成功。
我找不到关于如何
ggrough
转换为文字大小的明确信息。在这个答案中,我使用了 7 x 5 (英寸) 的宽高比,这是相当标准的 (
browser
、knitr
等等)。我没有测试这些公式是否适用于不同的宽高比。因为我无法确定什么看起来像是向吊扇上扔泥巴
ggrough
,所以我建立了数百个图表,对它们进行对齐,然后确定是否存在我可以创建的公式来准确地识别 ggplot 对象的正确尺寸。当我提到时,
ggplot
我指的是位于顶部的边框层。当我提到时,ggrough
我指的是位于底部的填充层。以下指标根据分配给 ggrough 的高度和宽度而变化。
由于这些元素分散在不同的函数中,我创建了一个依赖于 3 个输入的 UDF:ggrough 的宽度和高度以及要绘制的数据。
您为宽度和高度指定的值...我相信这些值代表英寸,但我不会假设 1 = 1 英寸。他们的文档中没有任何内容表明这些值代表什么,但 1 相当于大约 72 像素,如果 1 代表一英寸,那么这是准确的。
我在代码中留下了一条用于验证的消息,因为您可能会发现它是有用的信息。它在处理数据时会将所有计算出的指标吐出到控制台中。
虽然 SO 自然会将图像尺寸最大化以适应,但您至少可以看到字体大小的变化。
或者在 5, 5 处:
或者在9点、7点:
这是您可能看到的输出暗淡和错误消息的示例。