Изменение ширины линии в ggplot, а не размер

Я вижу несколько сообщений об изменении ширины линии в ggplot. Ответы, в то время как информативные и эффективные для ОП, изменяют размер линии. То есть, ggplot, кажется, рассматривает линии как ряд единиц, а размер увеличивает как длину, так и ширину каждого блока, делая другие корректировки более грубыми.

Я надеюсь, что есть способ сделать линии шире (толще), не затрагивая также длину и, в свою очередь, масштаб тире.

Я заимствовал код из https://cran.r-project.org/web/packages/ggplot2/vignettes/ggplot2-specs.html, чтобы проиллюстрировать, что я имею в виду:

library(ggplot2)

#A simple plot with manually set dashes.
#The first numeral is units of dash length, the second units in the gap in hexadecimal. 
lty <- c("11", "18", "1f", "81", "88", "8f", "f1", "f8", "ff")
linetypes <- data.frame(y = seq_along(lty), lty = lty) 

ggplot(linetypes, aes(0, y)) + 
  geom_segment(aes(xend = 5, yend = y, linetype = lty)) + 
  scale_linetype_identity() + 
  geom_text(aes(label = lty), hjust = 0, nudge_y = 0.2) +
  scale_x_continuous(NULL, breaks = NULL) + 
  scale_y_reverse(NULL, breaks = NULL)

Default size dashed lines.

#Altering the size changes the line width AND dash spacing.

ggplot(linetypes, aes(0, y)) + 
  geom_segment(aes(xend = 5, yend = y, linetype = lty), 
     size = 3) + 
  scale_linetype_identity() + 
  geom_text(aes(label = lty), hjust = 0, nudge_y = 0.3) +
  scale_x_continuous(NULL, breaks = NULL) + 
  scale_y_reverse(NULL, breaks = NULL)

Size 3 dashed lines.

По сути, я хочу толстые линии с относительно тонкими и точно отрегулированными пробелами. Я думаю, что это один и тот же вопрос, заданный другим способом: есть ли способ сделать строки, которые все, скажем, "пунктирные", отличаются по ширине, но не в относительном расположении тире? Как это (что я полностью подделал):

Lines of different width, but the same size.

Ответ 1

Из файла справки ?par для "Спецификация типа линии" (выделено жирным шрифтом для акцента):

Типы линий могут быть либо определены, давая индекс в небольшой встроенной таблицы типов линий (1 = твердые, 2 = пунктирными и т.д., см lty выше) или непосредственно в качестве длин включения/выключения отрезков линии. Это делается с помощью строки четного числа (до восьми) символов, а именно ненулевых (шестнадцатеричных) цифр, которые дают длины в последовательных позициях в строке. Например, строка "33" указывает три единицы, за которыми следуют три, а "3313" указывает три единицы, за которыми следуют три, а затем один на и, наконец, три. "Единицы здесь (на большинстве устройств) пропорциональны lwd, а lwd = 1 - в пикселях или точках или 1/96 дюйма.

Это говорит о том, что если мы укажем типы линий и ширину линии, которые будут меняться соответствующим образом (например, более толстая линия в два раза шире, чем более тонкая линия, причем длительность включения-выключения составляет половину длины), мы можем достичь желаемого эффекта, казалось бы, идентичных длин деления при разных ширины линий.

Примечание: допустимыми символами в спецификации типа линии являются c(1:9, "A":"F")), что означает, что кратчайшая длина растяжения составляет 1 единицу, а самая длинная - 15 единиц. Это ограничивает количество различных строк, которые могут быть созданы.

Он работает так, как ожидалось, с базовыми функциями построения R:

plot.new()
plot.window(xlim=c(0, 5), ylim=c(1, 3))
abline(h = 3, lty = "22", lwd = 8)
abline(h = 2, lty = "44", lwd = 4)
abline(h = 1, lty = "88", lwd = 2)
axis(2, at = 3:1, labels=c("22", "44", "88"), tick = FALSE, las = 1)

base R

С другой стороны, для ggplot2, насколько мне удалось выяснить, выбор графического файлового устройства имеет значение. Черточки аккуратно выравниваются для векторных устройств, но не обязательно для битмап-основанных:

p <- ggplot(data.frame(y = seq(1, 3),
                       lty = c("11", "22", "44"),
                       lwd = c(8, 4, 2)), 
            aes(0, y)) + 
  geom_segment(aes(xend = 5, yend = y, 
                   linetype = lty,
                   lwd = lwd)) + 
  geom_text(aes(label = lty), hjust = 0, nudge_x = -0.3) +

  scale_linetype_identity() + 
  scale_size_identity() +
  scale_x_continuous(NULL, breaks = NULL) + 
  scale_y_reverse(NULL, breaks = NULL, expand = c(0.5, 0))

# bitmap devices
ggsave("test.bmp", p + ggtitle(".bmp"))
ggsave("test.jpg", p + ggtitle(".jpg"))
ggsave("test.png", p + ggtitle(".png"))
ggsave("test.tiff", p + ggtitle(".tiff"))
ggsave("test.wmf", p + ggtitle(".wmf"))

# vector devices
ggsave("test.eps", p + ggtitle(".eps"))
ggsave("test.pdf", p + ggtitle(".pdf"))
ggsave("test.svg", p + ggtitle(".svg"))

output from different devices

Я не нашел ничего, что обращается к этому прямо в ggplot2. Тем не менее, если вам нужен один из форматов растровых изображений, но однотипные тире являются приоритетными, вы можете сначала выводить свои графики на одно из векторных устройств и затем конвертировать из одного формата файла в другой.