修复坐标轴标签的排版问题

20

前言:我希望能够在R中创建出版物级别的图形,而不需要进行后处理。我们研究所的其他研究人员总是在图形软件(如Adobe Illustrator)中进行后处理。我希望能够避免这种情况。

我的抱怨是R对于负数(特别是在绘图坐标轴中)没有使用正确的减号:

plot(-20:-1, rnorm(20) + 1 : 20)

带有负数的绘图

(我在这里圈出了问题所在,供您参考。)

作为一个有些迷恋字体排印的人(是真的!请查看我的 Careers CV !),这是无法接受的。我需要使用正确的 Unicode 字符 ᴍɪɴᴜꜱ ꜱɪɢɴ (U+2212, “−”)。我的一个朋友在出版前通过 Adobe Illustrator 替换所有减号来实现这一点,但我不禁想到必须有一种更好的方式——从 R 中实现;而且这种方法会强制我手动替换所有轴标签。

(我目前没有使用 ggplot2 ,但如果只有 ggplot2 可以解决问题,我也会很愿意采用它。)


3
不使用XKCD风格图表,请翻译文本内容。 - Mysticial
2
嗨,Konrad,你知道已经不在CRAN上(不确定为什么)的tikzDevice包吗?请参见此链接以获取示例。 - Dirk Eddelbuettel
@Dirk 哦,非常有趣,我一定会安装它。然而,仅仅粗略地看一下示例,似乎TikZ设备并没有自动将数字放入数学环境中,所以它不能解决我的特定问题。 - Konrad Rudolph
请参考我对这个相关问题的回答(尽管现在看来,似乎cairo_pdf设备将减号放置得比应该更低)。 - Josh O'Brien
@Josh 有趣,但显然这是一种hack,因为它替换了所有 - 即使是合法的 - 连字符。哦,还有cairo_pdf显然会导致我的R崩溃。;-) 好吧,没关系。 - Konrad Rudolph
它确实感觉像是使用TikZ设备(特别是与LaTeX文档结合使用)将为您提供最好的排版解决方案(例如,字体匹配文档)。 - Ben Bolker
5个回答

7
也许手动绘制坐标轴和标签,而不是接受默认值?
plot(-20:-1, rnorm(20) + 1 : 20, xaxt="n")
Axis(-20:-1, at=seq(-20,-5,5), side=1,
  labels=paste("\U2212",seq(20,5,-5),sep=""))

enter image description here


实际上,这正是我想要避免的,但如果没有更好的解决方案,我就会接受它。无论如何,加1。 - Konrad Rudolph

5

另一种方式几乎与Joshua Ulrich提供的方法相同,只是您可以让R计算轴标记:

plot(-20:-1, rnorm(20) + 1 : 20, xaxt="n")
at <- axTicks(1, usr=par("usr")[1:2])
labs <- gsub("-", "\U2212", print.default(at))
axis(1, at=at, labels=labs)

enter image description here


嗯,事实上我可以编写自己的 plot 版本,它可以在内部完成这个操作。唯一的问题是正确地捕获所有边缘情况有点棘手(例如当轴应该打印在另一侧时,或者根本不打印...) - Konrad Rudolph
@juba -- 你能告诉我你正在使用哪个操作系统吗?(如果不显式设置Encoding(lab) <- "UTF-8",这对我来说是无效的,我想确定是否因为我正在使用Windows。奇怪的是,当Unicode字符被paste粘贴时(就像Joshua的解决方案一样),Windows版的R确实能够找出结果字符串现在是Unicode)。 - Josh O'Brien
@JoshO'Brien 我正在使用Linux。 - juba
@juba -- 我好嫉妒啊。感谢确认。 - Josh O'Brien

5

以下是使用ggplot进行操作的方法。由于pdf设备无法渲染Unicode符号,因此请改用cairo_pdf

unicode_minus <- function(x) sub('^-', '\U2212', format(x))

# change the default scales
scale_x_continuous <- function(..., labels=unicode_minus)
                        ggplot2::scale_x_continuous(..., labels=labels)
scale_y_continuous <- function(..., labels=unicode_minus)
                        ggplot2::scale_y_continuous(..., labels=labels)

qplot(-20:-1, rnorm(20) + 1:20)

3
新的软件包signs完全满足了原帖中所要求的功能。以下是网站上的示例:
library(dplyr)
library(ggplot2)
library(ggrepel)

theme_set(theme_gray())
theme_update(panel.grid.minor = element_blank())

p <- 
  ggplot(sleep) +
  aes(group, extra) +
  geom_point() +
  xlab("Drug") +
  ylab("Extra Sleep (hours)")

label_hours <- function(mapping) {
  geom_text_repel(
    mapping,
    nudge_x       = -.1,
    direction     = "y",
    segment.size  = .4,
    segment.color = "grey75",
    hjust         = "right"
  )
}

p +
  label_hours(
    mapping = aes(
      label = case_when(
        group == 1 ~ signs(extra, accuracy = .1), # Unicode minuses
        group == 2 ~ number(extra, accuracy = .1) # ASCII minuses
      )
    )
  ) +
  scale_y_continuous(
    limits = c(-4, 6),
    breaks = seq(-4, 6),
    labels = signs_format(accuracy = .1) # Unicode, analogous to number_format() 
  )

Here is the plot on the website.


3
以下是关于修复lattice图表轴标签的技巧。思路是在低级函数panel.axis()中插入代码,该函数被大多数/所有高级绘图函数调用。
以下是您手动插入的代码(上下各有几行):“library(lattice); trace(“panel.axis”,edit = TRUE)”之后的内容。
if (draw.labels && !is.null(labels)) {
    {
        labels <- gsub("-", "\U2212", labels)  ## <- My addition
        Encoding(labels) <- "UTF-8"            ## <- My addition
        just <- if (outside) 
            switch(side, bottom = if (rot[1] == 0) c("centre", 

更好的选择(一旦您确定了at=参数的正确值(并在这里查看几种方法)),则运行以下内容:

library(lattice)

trace(what = "panel.axis",
      tracer = quote({labels <- gsub("-", "\U2212", labels)
                      Encoding(labels) <- "UTF-8"}),
      at = list(c(30,3,2,2)))

在我检查过的许多屏幕或文件图形设备上,适当的负号会在刻度标签中打印出来。

如果要在您自己的屏幕设备上进行比较,请直接运行上面的代码块,然后:

xyplot(1:10 ~ -1:-10)
untrace("panel.axis")
windows()
xyplot(1:10 ~ -1:-10)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接