Я работаю с действительно удивительной библиотекой ggplot2. Я понял, как установить соотношение сторон графика, используя coord_fixed
. Теперь я хотел бы сохранить график в PDF с указанной шириной (например, 10 см) и позволить рассчитывать требуемую высоту. Я не понял, как это сделать. Возможно ли это?Сохранить участок с заданным соотношением сторон
ответ
Вы можете использовать функции сетки, чтобы вычислить полный размер ggplot grob, но там является (редактирования: по крайней мере) два оговорок:
дополнительным окно устройства будет открытым, чтобы сделать преобразование блока
сюжета размером панели будет 0 по умолчанию, так как это означает, для расчета на лету в зависимости от устройства (видового экрана), в котором он живет, а не наоборот.
При этом, следующая функция пытается открыть устройство, которое соответствует ggplot точно,
library(ggplot2)
library(grid)
sizeit <- function(p, panel.size = 2, default.ar=1){
gb <- ggplot_build(p)
# first check if theme sets an aspect ratio
ar <- gb$plot$coordinates$ratio
# second possibility: aspect ratio is set by the coordinates, which results in
# the use of 'null' units for the gtable layout. let's find out
g <- ggplot_gtable(gb)
nullw <- sapply(g$widths, attr, "unit")
nullh <- sapply(g$heights, attr, "unit")
# ugly hack to extract the aspect ratio from these weird units
if(any(nullw == "null"))
ar <- unlist(g$widths[nullw == "null"])/unlist(g$heights[nullh == "null"])
if(is.null(ar)) # if the aspect ratio wasn't specified by the plot
ar <- default.ar
# ensure that panel.size is always the larger dimension
if(ar <= 1) panel.size <- panel.size/ar
g$fullwidth <- convertWidth(sum(g$widths), "in", valueOnly=TRUE) +
panel.size
g$fullheight <- convertHeight(sum(g$heights), "in", valueOnly=TRUE) +
panel.size/ar
class(g) <- c("sizedgrob", class(g))
g
}
print.sizedgrob <- function(x){
# note: dev.new doesn't seem to respect those parameters
# when called from Rstudio; in this case it
# may be replaced by x11 or quartz or ...
dev.new(width=x$fullwidth, height=x$fullheight)
grid.draw(x)
}
p1 <- ggplot(mtcars, aes(x = wt, y = mpg)) + geom_point() + coord_fixed() +
theme(plot.background = element_rect(colour = "red"))
p2 <- p1 + aes(x = mpg, y = wt)
# need for an explicit dummy device open, otherwise it's a bit off
# for no apparent reason that I can understand
dev.new()
sizeit(p1, 0.1)
sizeit(p2, 2)
Если вы используете ggsave
, вы можете просто указать ширину и высоту графического устройства. Если вы укажете соотношение сторон самого сюжета, также хорошо иметь это соотношение сторон (примерно) в графическом устройстве. Единица height
и width
при сохранении pdf
дюймы:
ggplot(...) # make a plot here
ggsave("plot.pdf", width = 10)
Теперь у вас есть только для преобразования 10 см в дюймы. Кроме того, height
не привязан к определенному соотношению сторон, если вы его не укажете. Если вы хотите соотношение сторон 16: 9, вы можете легко рассчитать высоту на основе ширины:
ggplot(...) # make plot
width = 10
height = (9/16) * width
ggsave("plot.pdf", width = width, height = height)
Вы можете обернуть это в функции, если вы действительно хотите.
править: Суть состоит в синхронизации соотношение сторон участка (через coord_fixed()
) и соотношение сторон графического устройства. Например
library(ggplot2)
ggplot(mtcars, aes(x = wt, y = mpg)) + geom_point() + coord_fixed()
ggsave("plt.png", width = 7, height = 7)
приводит к большому количеству белого пространства. В то время как следующий ggsave
вызов, который имеет гораздо лучше подходят в пропорции, не имеет такого количества белого пространства (простите за большую картину, не может установить максимальный размер :)):
ggsave("plt.png", width = 2, height = 7)
Я думал, что Пол, но это размер * устройства *, а не сюжет. Когда вы добавите в заголовок, метки осей и легенды и т. Д., Сама область построения графика может быть не квадратной, а с помощью 'coord_fixed()' самой области сюжета, а затем не заполняет свободное пространство. Я не знаю ничего хорошего, кроме как изменить размер окна построения до тех пор, пока 'ggsave()' не указывая ширину, получив изображение шириной 10 см. –
Спасибо, Пол за ваш ответ. Гэвин, это точно так же, как вы указали в своем комментарии. Я думаю, что это довольно проблема, нужно обрезать каждый сюжет вручную. Подождем, если кто-нибудь придумает решение. – marsl
Не уверен, но что-то вроде этого, что вам нужно?
ggplot(data.frame(x = seq(10), y = seq(10)), aes(x = x, y = y)) +
geom_point() +
coord_equal() +
theme(aspect.ratio = 1)
Это выглядит хорошо для меня:
ggsave("test.pdf", width = 4, height = 4)
Слишком много белого пространства, но само изображение имеет соотношение сторон 1:
ggsave("test2.pdf", width = 4)
Сообщение: Сохранение 4 х 6,93 в изображении
Спасибо за ваш ответ Деннис. К сожалению, это не подходит, поскольку 'ggsave' просто по умолчанию занимает размер текущего окна графика. – marsl
на основе I ответ Батист в разделил его код вниз, чтобы вернуть соотношение сторон, как предложено g eotheory. Это было намного удобнее для меня, потому что я либо хотел иметь фиксированную ширину или высоту, а также передавал все через существующую функцию обертки, которая также добавляет шрифты в мой pdf.
О, и если вы использовали грани, вам необходимо учитывать их вручную. Разделите по строкам и умножьте на столбцы. Не уверен, есть ли лучший способ .....
ggGetAr <- function(p, default.ar=-1){
gb <- ggplot_build(p)
# first check if theme sets an aspect ratio
ar <- gb$plot$coordinates$ratio
# second possibility: aspect ratio is set by the coordinates, which results in
# the use of 'null' units for the gtable layout. let's find out
g <- ggplot_gtable(gb)
nullw <- sapply(g$widths, attr, "unit")
nullh <- sapply(g$heights, attr, "unit")
# ugly hack to extract the aspect ratio from these weird units
if(any(nullw == "null"))
ar <- unlist(g$widths[nullw == "null"])/unlist(g$heights[nullh == "null"])
if(is.null(ar)) # if the aspect ratio wasn't specified by the plot
ar <- default.ar
ar[1]
}
Более упрощенное решение было бы сохранить участок с полямами по умолчанию и обрезать полученный с ImageMagick детским.
require(ggplot2)
require(dplyr)
ggplot(iris, aes(Sepal.Length, Sepal.Width)) + geom_point() + coord_fixed(0.3)
ggsave("untrimmed.png")
system("convert untrimmed.png -trim -bordercolor white -border 20 reframed.png")
Конечно, обрезка будет отличаться в зависимости от используемого устройства вывода. Например. в случае pdf вы можете использовать pdfcrop, как описано here.
- 1. Вычислить прямоугольник прямоугольника с заданным соотношением сторон
- 2. CSS Сохранить изображение с соотношением сторон
- 3. Как обрезать участок Axes3D с квадратным соотношением сторон?
- 4. Центр Div с соотношением сторон
- 5. Подзаголовок с равным соотношением сторон
- 6. FragmentDialog с фиксированным соотношением сторон
- 7. Смутные проблемы с соотношением сторон
- 8. Диалоговое окно JQuery с постоянным соотношением сторон
- 9. Изменение размера JavaScript с соотношением сторон
- 10. Динамический эскиз с правильным соотношением сторон
- 11. Как увеличить с правильным соотношением сторон
- 12. Отзывчивый фон с поддерживаемым соотношением сторон
- 13. iOS - Воспроизведение видео с произвольным соотношением сторон
- 14. Flexbox с rowspan и фиксированным соотношением сторон
- 15. Seaborn JointGrid hexplot: проблема с соотношением сторон
- 16. Косые изображения с соотношением сторон камеры Preview
- 17. matplotlib - подзаголовки с фиксированным соотношением сторон
- 18. изменение размера изображения с соответствующим соотношением сторон
- 19. Минимальный размер с соотношением сторон Копир.изобр
- 20. Flex - приложение шкалы с фиксированным соотношением сторон
- 21. изменение размера изображения с соотношением сторон
- 22. Resizing Tkinter Рамка с фиксированным соотношением сторон-
- 23. Изменить размер NSWindow с "полуфиксированным" соотношением сторон
- 24. Открытие fancyBox с определенным соотношением сторон
- 25. Android квадратного изображения с соотношением сторон
- 26. Заполните div с соотношением сторон изображения
- 27. Вторичная ось Matplotlib с равным соотношением сторон
- 28. Динамический элемент масштабирования с неизвестным соотношением сторон
- 29. Изменить размер UIImage с соотношением сторон?
- 30. jQuery imgAreaВыбрать начальный выбор с соотношением сторон
точный ответ на вопрос оставлен как упражнение для читателя (этот взлом сетки становится слишком уродливым, мне нужен перерыв) – baptiste
Спасибо за ваш ответ, баптист. Похоже, что нет никакого правильного решения. – marsl
Принял ваш ответ, поскольку я думаю, что нет лучшего решения. Спасибо всем. – marsl