knitr: 无法创建包含UTF-8字符的图像

4
以下是我的.Rnw文件:
\documentclass{article}
\begin{document}

<<myChunk>>=
options(warn = 2)
library(ggplot2)
library(directlabels)
data(BodyWeight,package="nlme")
BodyWeight$temp <- as.character(BodyWeight$Rat)
BodyWeight$temp[BodyWeight$temp == "4"] <- "HI₂"
p <- qplot(Time,weight,data=BodyWeight,colour=temp,geom="line")
direct.label(p,"first.qp")
@

\end{document}

以下是我从R中调用knitr的方法:
library(knitr)
# I have tryied this but doesn't make difference:
# pdf.options(encoding='ISOLatin2.enc')
knit("mwe_knitr.Rnw")

我得到以下输出:
> knit("mwe_knitr.Rnw")


processing file: mwe_knitr.Rnw
  |......................                                           |  33%
  ordinary text without R code

  |...........................................                      |  67%
label: myChunk
Quitting from lines 5-13 (mwe_knitr.Rnw) 
Error in grid.Call(L_convert, x, as.integer(whatfrom), as.integer(whatto),  : 
  (converted from warning) conversion failure on 'HI₂' in 'mbcsToSbcs': dot substituted for <e2>

我尝试了一些编码方案,比如这里发布的方案: Rhtml: Warning: conversion failure on '<var>' in 'mbcsToSbcs': dot substituted for <var>

(请注意,在上面的评论中,我确切地说明了我尝试解决该问题的位置),但对我来说好像没有改变任何事情。

我正在使用Ubuntu上的R 3.3.1和knitr包1.13。

1个回答

5
看起来使用 cairo_pdf 设备可以解决这个问题。在下面的 setup 块中,我将设备选项设置为 cairo_pdf 设备(即以 option(device = ... 开头的那一行),并将全局块选项 dev 默认设置为 "cairo_pdf"(在以 knitr::opts_chunk$set(... 开头的那一行)。这种方法在 knitr 文档(请参阅“多字节字符的编码”一节)和 Issue #436 中有讨论。
我还做了一些其他更改:
  1. 我没有“硬编码” "HI₂",而是使用了下标 2 的 Unicode 符号 "\U2082"

  2. 将绘图调用从 qplot 改为“标准”的 ggplot。

  3. 从制作图表后调用 directlabels 改为在“标准”ggplot 工作流程中调用 geom_dl 添加直接标签。

  4. geom_dl 内部设置 fontfamily。我发现下标 2 会在某些字体系列中呈现,而在其他字体系列中则不会。

  5. warn 选项设置为零(默认值),以便警告不会转换为错误。我只是在测试代码时这样做的,但当然可以将其设置回 2(如果需要的话)。

myChunk1a 块创建了图表。块 myChunk1b 创建了基本上相同的图表,但使用不同的字体系列进行多个版本。在这些版本中,您可以看到下标 2 在某些字体系列中呈现,而在其他字体系列中则不会。我不确定是什么决定了这一点,而且结果可能因您的系统而异。
\documentclass{article}
\begin{document}

<<setup, include=FALSE>>=
options(warn = 0)
options(device = function(file, width = 7, height = 7, ...) {
  cairo_pdf(tempfile(), width = width, height = height, ...)
})
knitr::opts_chunk$set(echo = FALSE, message=FALSE, warning=FALSE, dev="cairo_pdf")
@

<<myChunk>>=
library(ggplot2)
library(directlabels)
library(gridExtra)
library(dplyr)

data(BodyWeight,package="nlme")
BodyWeight$temp <- as.character(BodyWeight$Rat)

BodyWeight$temp[BodyWeight$temp=="4"] = "HI\U2082"

# Change first value so that HI2 label is easily visible
BodyWeight$weight[BodyWeight$temp=="HI\U2082" & BodyWeight$Time==1] = 350
@

<<myChunk1a, fig.height=5>>=
ggplot(BodyWeight, aes(Time, weight, colour=temp)) + 
  geom_line() +
  geom_dl(method=list("first.qp", fontfamily="Helvetica", cex=1), aes(label=temp)) + 
  theme_bw() +
  ggtitle("Helvetica") +
  guides(colour=FALSE)
@

<<myChunk1b, fig.height=11>>=
# Create several plots, each demonstrating a different font family for the labels
grid.arrange(grobs=lapply(c("Helvetica","Courier","Palatino","Times","Serif"), function(f) {
  ggplot(BodyWeight, aes(Time, weight, colour=temp)) + 
    geom_line() +
    geom_dl(method=list("first.qp", fontfamily=f, cex=1), aes(label=temp)) + 
    labs(x="") + 
    theme_bw() +
    theme(plot.margin=unit(c(0,0,0,0), "lines"),
          text=element_text(size=9)) +
    ggtitle(f) +
    guides(colour=FALSE)
}), ncol=1)
@

<<myChunk2, fig.height=5>>=
data(BodyWeight,package="nlme")
BodyWeight$temp <- as.character(BodyWeight$Rat)

# Change first value so that HI2 label is easily visible
BodyWeight$weight[BodyWeight$temp=="4" & BodyWeight$Time==1] = 350

# Set temp==4 to desired expression
BodyWeight$temp[BodyWeight$temp == "4"] <- paste(expression(HI[2]))

# Convert temp to factor to set order
BodyWeight$temp = factor(BodyWeight$temp, levels=unique(BodyWeight$temp))

qplot(Time, weight, data=BodyWeight, colour=temp, geom="line") +
  guides(colour=FALSE) +
  geom_text(data=BodyWeight %>% group_by(temp) %>%
              filter(Time == min(Time)), 
            aes(label=temp, x=Time-0.5, y=weight), parse=TRUE, hjust=1) +
  theme_bw()
@

\end{document}

这是myChunk1a中的情节展示: enter image description here

+1 谢谢你提供这段代码。通过学习它,我更深入地了解了 ggplot2。不过,我确实需要 directlabels 提供的自动标签位置。 - Xu Wang
我已经更新了我的答案。请告诉我所提出的解决方案是否适用于您。 - eipi10
谢谢你的帮助。是的,使用cairo似乎解决了问题。我也感激你额外的建议。 - Xu Wang

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