В качестве отправной точки я использую очень полезный код из ответа Кэт на этот вопрос (Как добавить меньше шероховатостей к границам карты, чем к заливке карты), чтобы создать два графика с намерением чтобы один из графиков был наложен поверх другого.
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 х 5 (дюймов), что является довольно стандартным (browser, knitr и тому подобное). Я не проверял, будут ли эти формулы работать при разных соотношениях сторон.
Поскольку я не мог сформулировать то, что выглядит как обливание грязью потолочного вентилятора для ggrough, я построил сотни графиков, выровнял их, а затем определил, есть ли форум, который я мог бы создать, чтобы точно определить правильные размеры для объекта ggplot.
Когда я говорю о ggplot, я имею в виду пограничный слой, который находится сверху.
Когда я говорю о ggrough, я имею в виду слой заливки внизу.
Следующие метрики изменяются в зависимости от высоты и ширины, назначенных ggrough.
Поскольку эти элементы разбросаны по разным функциям, я создал пользовательскую функцию, которая опирается на три входных параметра: ширину и высоту ggrough и данные для построения графика.
Значение, которое вы назначаете для ширины и высоты... Я считаю, что они представляют собой дюймы, но я бы не стал предполагать, что 1 = 1 дюйм. В их документации нет ничего, что бы определяло, что представляют собой эти значения, но 1 соответствует примерно 72 пикселям, что является точным, если 1 представляет дюйм.
В функцию записано 2 вызова ошибок. 1) Если высота превышает ширину: это только создает больше бесполезного белого пространства над выступом. 2) Если значения высоты/ширины превышают размер окна браузера. (Если это произойдет, график ggrough потеряет свое соотношение сторон и скроет часть графика - ничего хорошего в этом нет!) Если вы активируете любой из них, вы увидите сообщение в консоли, сообщающее, что произошло.
Я оставил в коде сообщение, которое использовал для проверки, потому что оно может оказаться для вас полезной информацией. Он просто выплевывает все рассчитанные метрики в консоль при обработке данных.
aligner <- function(grw, grh, nc) { # set rough chart width/height (8, 5, for example), data used in plot
if (isTRUE(grh > grw)) {
return(cat("\033[0;37;101mThe height should not exceed the width for this plot.\033[0m\n"))
}
# hide the text in the ggrough object
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
}
tpad <- function(grw, grh) { # calculate the top padding, given ggrough width, height
delta <- grh - grw + 1
widD <<- 8 - grw
widH <- 7 - grh
45.5 - widD * 10.0 + delta * 35.5 + .5
}
#---------- set the variables -----------
pltW = 7; pltH = 5 # setting aspect ratio; if this changes nothing else may work correctly!
browsW = 960 # browser width (default is 960) for htmlwidgets/ used for error checking
browsH = 500 # browser height (default is 500) for htmlwidgets/ used for error checking
sfs <- list(-0.325, 6.1) # slope formula metrics for calculating font size of ggplot object
sdw <- list(72.5, -3) # slope formula metrics for calculating width of div
#---------- calculate metrics -----------
fs <- sfs[[1]] * grw + sfs[[2]] # calculate the approriate font size for ggplot object
dw <- sdw[[1]] * grw + sdw[[2]] # calculate the approriate div width for ggplot object
if (any(pltH/pltW * dw > browsH)) { # validate aspect ratio by width fits in browser window
return(cat("\033[0;37;101mWidth of", grw, "is too high to fit. Reduce width & try again.\033[0m\n"))
}
tp <- tpad(grw, grh) # calculate top padding
if (isTRUE(tp < 0)) { # validate aspect ratio fits in browser window
return(cat("\033[0;37;101mWith the given height and width, the plot doesn't fit. Try increasing the height.\033[0m\n"))
}
lp <- ifelse(isTRUE(widD > 0), 1 - .5 * widD, 1) # calculate the left padding
#------------ create graphs ------------
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, width = grw, height = grh) %>% fixer() # create gg rough graph
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 = rel(fs))) # text size to match defaults in ggrough
gg <- girafe(ggobj = g2, width_svg = pltW, height_svg = pltH) # great ggplot graph HTML
#-------- notify user of calcs ---------
message(paste0("Entered size: ", grw, ", ", grh, "; calculated dims are: ",
"div width ", dw, "; font size ", fs, "; top padding ", tp,
" and left padding ", lp))
#-------- create graph overlay ---------
browsable(div( # parent div, size matches ggrough's default
style = css(width = "960px", height = paste0(browsH, "pt"), position = "relative"),
div(xx, style = css(display = "block", padding.left = paste0(lp, "px"))), # ggrough graph
div(gg, style = css(position = "absolute", top = 0, # ggplot graph
padding.top = paste0(tp, "px"),
width = paste0(dw, "px"), z.index = -2))
))
}
aligner(7, 7, nc)
Хотя SO естественным образом увеличивает размер изображения до нужного размера, вы, по крайней мере, можете увидеть разницу в размерах шрифта.
Или в 5, 5:
Или в 9, 7:
Это пример затемнения выходных данных и сообщения об ошибке, которое вы можете увидеть.
Ух ты, огромное спасибо! Это снова было превосходно!