科学测量 +- Rmarkdown/bookdown 表中的错误
scientific measurements +- error in Rmarkdown/bookdown tables
如果我想以 y +- error
或 y +- error
或y(error)
,具有通常的错误规则:有 1 位有效数字错误,相同位数的值,等等。例如:
- 1.124 \pm 0.003
- 0.30 \pm 0.02
等等。
可重现的例子
df<-data.frame(
x=runif(5),
Delta.x=runif(5)/10,
y=runif(5),
Delta.y=runif(5)/7
)
df.print<-with(df, data.frame(
x=paste0(x, "(", Delta.x, ")"),
y=paste0(y, "(", Delta.y, ")")
))
kable(df.print)
如果我使用 format(x, digits=3)
x、y 和它们的增量,我会得到不同的 "widths",我想得到相同的小数点后位数。
这里 tidyverse
解决您的问题,可以说它非常冗长。一些解释:
1) 第一个 mutate()
块舍入两个 Delta
列以具有一个有效数字并将其转换为字符;这保留了长度。
2) 第二个 mutate()
块舍入 "normal" x
和 y
列,使其与 Delta
列的长度相同。 - 2L
避免基于 .
之前的数字和 Delta
列中的 .
本身的错误舍入。
3)第三个mutate()
块首先处理两种"unusual"情况:第一个if_else()
处理四舍五入的y
数字没有的情况.
和数字,但 Delta.y
值有。第二个 if_else()
处理舍入过程中最后一位数字是 0
的情况,R
在舍入中下降。 x
列重复这两项措施。
4) 第四个 mutate()
块在 x
和 y
列的值末尾添加白色 space 以确保错误编号对齐.
5) 最后的 unite()
和 mutate()
命令合并列并为第二个数字添加括号。
library("tidyverse")
library("knitr")
df %>%
mutate(Delta.x = signif(Delta.x, digits = 1L),
Delta.x = as.character(Delta.x),
Delta.y = signif(Delta.y, digits = 1L),
Delta.y = as.character(Delta.y)) %>%
mutate(x = round(x, digits = str_count(Delta.x) - 2L),
x = as.character(x),
y = round(y, digits = str_count(Delta.y) - 2L),
y = as.character(y)) %>%
mutate(y = if_else(condition = str_count(y, "\.") == 0,
true = str_c(y, str_dup("0", str_count(Delta.y) - str_count(y) - 1L), sep = "."),
false = y),
y = if_else(condition = str_count(Delta.y) - str_count(y) != 0,
true = str_c(y, str_dup("0", times = str_count(Delta.y) - str_count(y))),
false = y),
x = if_else(condition = str_count(x, "\.") == 0,
true = str_c(x, str_dup("0", str_count(Delta.x) - str_count(x) - 1L), sep = "."),
false = x),
x = if_else(condition = str_count(Delta.x) - str_count(x) != 0,
true = str_c(x, str_dup("0", times = str_count(Delta.x) - str_count(x))),
false = x)) %>%
mutate(x = if_else(condition = str_count(x) < max(str_count(x)),
true = str_c(x, str_dup(" ", times = max(str_count(x)) - str_count(x))),
false = x),
y = if_else(condition = str_count(y) < max(str_count(y)),
true = str_c(y, str_dup(" ", times = max(str_count(y)) - str_count(y))),
false = y)) %>%
unite(x, x, Delta.x, sep = " (") %>%
unite(y, y, Delta.y, sep = " (") %>%
mutate(x = str_c(x, ")"),
y = str_c(y, ")")) %>%
kable()
|x |y |
|:-----------|:-------------|
|1.0 (0.1) |0.20 (0.01) |
|0.12 (0.07) |0.8 (0.1) |
|0.71 (0.03) |0.18 (0.09) |
|0.63 (0.02) |0.805 (0.003) |
|0.27 (0.09) |0.106 (0.008) |
此外,您可以设置全局 options(scipen = 999)
(或任何其他大数)以避免数字的科学表示,例如2e-5
(在你的 kable
的情况下应该看起来像 0.00002
)。
编辑:更新并阐明了一些命令。
更新(Javi_VM)
我只是把它变成了一个函数。您可以给出 2 个向量或 1 个 data.frame 两列。它仍然缺乏对科学计数法的支持(例如 1.05 10^9),但可以启动。
scinumber <- function(df=NULL, x, Delta.x){
if (is.null(df)) {
df <- data.frame(
x = x,
Delta.x = Delta.x
)
} else {
colnames(df)[colnames(df)==x] <- "x"
colnames(df)[colnames(df)==Delta.x] <- "Delta.x"
}
require(tidyverse)
options(scipen = 999)
output <-
df %>%
mutate(Delta.x = signif(Delta.x, digits = 1L),
Delta.x = as.character(Delta.x)) %>%
mutate(x = round(x, digits = str_count(Delta.x) - 2L),
x = as.character(x)
) %>%
mutate(x = if_else(condition = str_count(x, "\.") == 0,
true = str_c(x, str_dup("0", str_count(Delta.x) - str_count(x) - 1L), sep = "."),
false = x),
x = if_else(condition = str_count(Delta.x) - str_count(x) != 0,
true = str_c(x, str_dup("0", times = str_count(Delta.x) - str_count(x))),
false = x)) %>%
mutate(x = if_else(condition = str_count(x) < max(str_count(x)),
true = str_c(x, str_dup(" ", times = max(str_count(x)) - str_count(x))),
false = x)) %>%
unite(x, x, Delta.x, sep = " (") %>%
mutate(x = str_c(x, ")"))
return(output)
}
如果我想以 y +- error
或 y +- error
或y(error)
,具有通常的错误规则:有 1 位有效数字错误,相同位数的值,等等。例如:
- 1.124 \pm 0.003
- 0.30 \pm 0.02
等等。
可重现的例子
df<-data.frame(
x=runif(5),
Delta.x=runif(5)/10,
y=runif(5),
Delta.y=runif(5)/7
)
df.print<-with(df, data.frame(
x=paste0(x, "(", Delta.x, ")"),
y=paste0(y, "(", Delta.y, ")")
))
kable(df.print)
如果我使用 format(x, digits=3)
x、y 和它们的增量,我会得到不同的 "widths",我想得到相同的小数点后位数。
这里 tidyverse
解决您的问题,可以说它非常冗长。一些解释:
1) 第一个 mutate()
块舍入两个 Delta
列以具有一个有效数字并将其转换为字符;这保留了长度。
2) 第二个 mutate()
块舍入 "normal" x
和 y
列,使其与 Delta
列的长度相同。 - 2L
避免基于 .
之前的数字和 Delta
列中的 .
本身的错误舍入。
3)第三个mutate()
块首先处理两种"unusual"情况:第一个if_else()
处理四舍五入的y
数字没有的情况.
和数字,但 Delta.y
值有。第二个 if_else()
处理舍入过程中最后一位数字是 0
的情况,R
在舍入中下降。 x
列重复这两项措施。
4) 第四个 mutate()
块在 x
和 y
列的值末尾添加白色 space 以确保错误编号对齐.
5) 最后的 unite()
和 mutate()
命令合并列并为第二个数字添加括号。
library("tidyverse")
library("knitr")
df %>%
mutate(Delta.x = signif(Delta.x, digits = 1L),
Delta.x = as.character(Delta.x),
Delta.y = signif(Delta.y, digits = 1L),
Delta.y = as.character(Delta.y)) %>%
mutate(x = round(x, digits = str_count(Delta.x) - 2L),
x = as.character(x),
y = round(y, digits = str_count(Delta.y) - 2L),
y = as.character(y)) %>%
mutate(y = if_else(condition = str_count(y, "\.") == 0,
true = str_c(y, str_dup("0", str_count(Delta.y) - str_count(y) - 1L), sep = "."),
false = y),
y = if_else(condition = str_count(Delta.y) - str_count(y) != 0,
true = str_c(y, str_dup("0", times = str_count(Delta.y) - str_count(y))),
false = y),
x = if_else(condition = str_count(x, "\.") == 0,
true = str_c(x, str_dup("0", str_count(Delta.x) - str_count(x) - 1L), sep = "."),
false = x),
x = if_else(condition = str_count(Delta.x) - str_count(x) != 0,
true = str_c(x, str_dup("0", times = str_count(Delta.x) - str_count(x))),
false = x)) %>%
mutate(x = if_else(condition = str_count(x) < max(str_count(x)),
true = str_c(x, str_dup(" ", times = max(str_count(x)) - str_count(x))),
false = x),
y = if_else(condition = str_count(y) < max(str_count(y)),
true = str_c(y, str_dup(" ", times = max(str_count(y)) - str_count(y))),
false = y)) %>%
unite(x, x, Delta.x, sep = " (") %>%
unite(y, y, Delta.y, sep = " (") %>%
mutate(x = str_c(x, ")"),
y = str_c(y, ")")) %>%
kable()
|x |y |
|:-----------|:-------------|
|1.0 (0.1) |0.20 (0.01) |
|0.12 (0.07) |0.8 (0.1) |
|0.71 (0.03) |0.18 (0.09) |
|0.63 (0.02) |0.805 (0.003) |
|0.27 (0.09) |0.106 (0.008) |
此外,您可以设置全局 options(scipen = 999)
(或任何其他大数)以避免数字的科学表示,例如2e-5
(在你的 kable
的情况下应该看起来像 0.00002
)。
编辑:更新并阐明了一些命令。
更新(Javi_VM)
我只是把它变成了一个函数。您可以给出 2 个向量或 1 个 data.frame 两列。它仍然缺乏对科学计数法的支持(例如 1.05 10^9),但可以启动。
scinumber <- function(df=NULL, x, Delta.x){
if (is.null(df)) {
df <- data.frame(
x = x,
Delta.x = Delta.x
)
} else {
colnames(df)[colnames(df)==x] <- "x"
colnames(df)[colnames(df)==Delta.x] <- "Delta.x"
}
require(tidyverse)
options(scipen = 999)
output <-
df %>%
mutate(Delta.x = signif(Delta.x, digits = 1L),
Delta.x = as.character(Delta.x)) %>%
mutate(x = round(x, digits = str_count(Delta.x) - 2L),
x = as.character(x)
) %>%
mutate(x = if_else(condition = str_count(x, "\.") == 0,
true = str_c(x, str_dup("0", str_count(Delta.x) - str_count(x) - 1L), sep = "."),
false = x),
x = if_else(condition = str_count(Delta.x) - str_count(x) != 0,
true = str_c(x, str_dup("0", times = str_count(Delta.x) - str_count(x))),
false = x)) %>%
mutate(x = if_else(condition = str_count(x) < max(str_count(x)),
true = str_c(x, str_dup(" ", times = max(str_count(x)) - str_count(x))),
false = x)) %>%
unite(x, x, Delta.x, sep = " (") %>%
mutate(x = str_c(x, ")"))
return(output)
}