knitr 不会在绘图中挂钩科学记数法

knitr does not hook scientific notation in plots

当使用 knitr 内联时,$\Sexpr{2.5e3}$.5 \times 10^3$ 的拼写错误非常好。但是我想念这样一个事实,即这不适用于绘图中的标签。我猜 knitr 认为有字符而不是数字。有办法改变吗?

正如我在评论中所讨论的那样,让这一切自动发生并不容易,但翻译你的天平并不难。 sfsmisc::eaxis() 是基本地块的一个很好的解决方案。这里有一些 ggplot 风格的解决方案:

如果您想使用本机 ?plotmath 格式:

##scale function for plotting y-axis labels
scientific_10 <- function(x) {
    s <- scales::scientific_format()(x)
    ## substitute for exact zeros
    s[s=="0e+00"] <- "0"
    ## regex: [+]?  = "zero or one occurrences of '+'"
    parse(text=gsub("e[+]?", " %*% 10^", s ))
}

或者如果你使用 LaTeX/TikZ(我在这里使用 Hmisc::latexSN()。这是一个 3 行函数,所以如果你想避免依赖或破解它,你可以直接复制它):

scientific_latex <- function(x,scipen=-2) {
    require(Hmisc)
    op <- options(scipen=scipen)  ## encourage use of scientific notation
    on.exit(options(op)
    s <- paste0("$",Hmisc::latexSN(x),"$")
}

示例:

set.seed(101)
d <- data.frame(trait=runif(1000),
                time=runif(1000,0,1000))
library(ggplot2); theme_set(theme_bw())

## make plot
breaks.y<-seq(from=0, to=1000, by=200)
g0 <- ggplot(d,aes(trait,time))+
   geom_point()

plotmath 风格:

g0 + scale_y_continuous(label=scientific_10,
                   breaks=breaks.y, limits=c(0,1000))

TikZ:

g0 + scale_y_continuous(label=scientific_latex,
                   breaks=breaks.y, limits=c(0,1000))

在@Ben Bolker 发表评论后,我在这里也添加了我的解决方案,也许更多的是 knitr 心情,因为将 knitr 渲染应用于轴标签只是一种 hack .特别是在 knitr 文档中,人们通常会在开头设置 digitsscipen 并期望它被应用到所有地方。

所以在设置块中定义函数:

inline_hook <- function (x) {
  if (is.numeric(x)) {
    x = knitr:::format_sci(x, "latex")
    i = grep("[^0-9.,]", x)
    x[i] = sprintf("\ensuremath{%s}", x[i])
    if (getOption("OutDec") != ".") 
      x = sprintf("\text{%s}", x)
  }
  if (is.numeric(x)) x = round(x, getOption("digits"))
  x
}

这只是 knitr::.inline.hook.texknitr:::.inline.hook 的混合,最后的 collapse 被丢弃。然后根据修改scale_y_continous的默认行为:

scale_y_continuous <- function(...) ggplot2:::scale_y_continuous(..., labels=inline_hook)

那么从上面的例子:

set.seed(101)
d <- data.frame(trait=runif(1000),
                time=runif(1000,0,1000))
library(ggplot2); theme_set(theme_bw())

## make plot
breaks.y<-seq(from=0, to=1000, by=200)
g0 <- ggplot(d,aes(trait,time))+
   geom_point()
g0

我默认得到:

这正是 knitr 对给定内联数字所做的。