【问题标题】:knitr: cannot create a figure with utf-8 characterknitr:无法创建带有 utf-8 字符的图形
【发布时间】:2017-01-13 06:31:05
【问题描述】:

以下是我的 .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。

【问题讨论】:

    标签: r encoding utf-8 knitr


    【解决方案1】:

    使用cairo_pdf 设备似乎可以解决此问题。在下面的setup 块中,我将设备选项设置为cairo_pdf 设备(即以option(device = ... 开头的行)和全局块选项dev 默认为“cairo_pdf”(在以@ 开头的行中) 987654330@)。这种方法在knitr documentation(参见多字节字符编码部分)和Issue #436 中进行了讨论。

    我还做了一些其他更改:

    1. 我使用 Unicode 符号代替“硬编码”"HI₂" 下标 2,"\U2082"。

    2. 将绘图调用更改为“标准”ggplot 而不是 qplot。

    3. 将绘图后调用 directlabels 更改为调用 geom_dl 以在“标准”ggplot 工作流程中添加直接标签。

    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 的情节如下所示:

    【讨论】:

    • +1 感谢您提供此代码。我通过研究它了解了更多关于 ggplot2 的信息。不幸的是,我确实需要直接标签附带的自动放置。
    • 我已经更新了我的答案。如果建议的解决方案适合您,请告诉我。
    • 感谢您的帮助。是的,使用 cairo 似乎有固定的东西。我也感谢您的额外建议。
    猜你喜欢
    • 2020-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-19
    • 2016-06-09
    • 1970-01-01
    • 2014-02-10
    • 1970-01-01
    相关资源
    最近更新 更多