【问题标题】:scientific measurements +- error in Rmarkdown/bookdown tables科学测量 +- Rmarkdown/bookdown 表中的错误
【发布时间】:2018-03-12 17:22:23
【问题描述】:

如果我想以y +- errory(error) 的形式进行测量及其错误,那么获得一张好表的最佳方法是什么(例如kable),并且具有通常的错误规则: 有 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 和它们的 Delta,我会得到不同的“宽度”,并且我希望小数点后的位数相同。

【问题讨论】:

  • 你可以使用sprintf: df.print&lt;-with(df, data.frame( x=paste(sprintf("%.2f", x), "±", sprintf("%.2f", Delta.x)), y=paste(sprintf("%.2f", y), "±", sprintf("%.2f", Delta.y)) ))
  • 有没有办法根据 Delta.x 或 Delta.y 值自动选择位数("%.2f""%.3f")?

标签: r r-markdown bookdown


【解决方案1】:

这是tidyverse 对您的问题的看法,这可以说是非常冗长。一些解释:

1) 第一个 mutate() 块将两个 Delta 列四舍五入以具有一个有效数字并将其转换为一个字符;这样可以保留长度。

2) 第二个 mutate() 块将“正常”xy 列四舍五入,使其长度与 Delta 列相同。 - 2L 避免了基于. 之前的数字和. 本身在Delta 列中的错误舍入。

3) 第三个mutate() 块首先处理两种“不寻常”的情况:第一个if_else() 处理四舍五入的y 数字没有. 和数字,但@ 987654336@ 值可以。第二个if_else() 处理舍入过程中的最后一位数字是0 的情况,而R 舍入时会下降。对x 列重复这两种措施。

4) 第四个mutate() 块在xy 列中的值末尾添加空格,以确保错误编号对齐。

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)
}

【讨论】:

  • 谢谢。但是,您的答案有两个问题。首先我不明白(我想我应该看看tidiverse)。其次,我仍然有自动获取位数的问题,因此不确定性总是只有一个有效数字
  • 对不起,我最初误解了你的问题;我已经相应地更新了我的答案,现在应该动态地产生你想要的输出。让我知道这是否是您要找的东西!
  • 非常感谢您的编辑,@Supertasty。还有一件事,把它转换成一个函数以便更容易地使用它,但我不会问你,我会尝试自己做。再次感谢你!!我会做进一步的测试以检查它是否适用于所有情况......
猜你喜欢
  • 2023-01-31
  • 1970-01-01
  • 1970-01-01
  • 2019-07-28
  • 1970-01-01
  • 2018-12-10
  • 2022-01-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多