在一列中保留 emmeans::contrast 的 p 值格式,在其他列中保留合理数量的小数点

Keep p-value format from emmeans::contrast in one column and a reasonable number of decimal points at other columns

我的 .Rprofile 文件中有 option(scipen=999),我的 .Rmd 文件开头有 options(digits = 7),以适应我的大比率和范围广泛的比率对比表。

我想在ratioSEt.ratio列中保留2位小数,除非值太小,并保持<.0001格式在p.value column。当值太小时,在我的例子中是 0.0004,我不想将它四舍五入为 0。我正在寻找比我想出的更圆滑的解决方案。

这是我要编辑的dataframe

tab1 <- contrast(model, list("..."), infer = c(F,T)) %>% print(export = T) %>% as.data.frame()

虽然 print 命令使输出 而不是 dataframe,但保持 p.value 格式,as.data.frame 命令允许我稍后修改其他列。 Keep p-value format from the `emmeans::joint_tests()` output in a knitted pdf

> dput(tab1)
structure(list(`contrast           ` = c("(2-year) / (3-year)", 
"(2-year) / (4-year)", "(3-year) / (4-year)", "soybean / oat    ", 
"soybean / alfalfa", "soybean / corn   ", "oat / alfalfa    ", 
"oat / corn       ", "alfalfa / corn   "), ratio = c(0.429, 0.286, 
0.668, 0.000388, 0.00323, 0.0331, 8.34, 85.3, 10.2), SE = c(0.2, 
0.127, 0.26, 0.000181, 0.00191, 0.0138, 5.21, 39.8, 6.03), df = c("51", 
"51", "51", "51", "51", "51", "51", "51", "51"), null = c("   1", 
"   1", "   1", "   1", "   1", "   1", "   1", "   1", "   1"
), t.ratio = c(-1.818, -2.829, -1.034, -16.857, -9.728, -8.18, 
3.392, 9.541, 3.944), p.value = c(" 0.1738", " 0.0180", " 0.5588", 
" <.0001", " <.0001", " <.0001", " 0.0071", " <.0001", " 0.0014"
)), row.names = c("X", "X.1", "X.2", "X.3", "X.4", "X.5", "X.6", 
"X.7", "X.8"), class = "data.frame")

ratioSEt.ratio 转换为数字: tab1[c(2,3,6)] <- sapply(tab1[c(2,3,6)],as.numeric)

第一个 mutate 命令将数字四舍五入到小数点后 4 位以以非科学格式显示,第二个 mutate 删除了 ratio、[=19] 中的所有尾随零=], 和 t.ratio.

tab1_rounded <- tab1 %>% mutate(across(where(is.numeric), round, 4)) %>%mutate(across(where(is.numeric), as.character))`

我对我的 tab1_rounded 并不完全满意,因为 soybean/oat 是科学形式,4e-04。我想要 0.0004,这是我对 mutate(across(where(is.numeric), round, 4)) 的期望。

使用 mutate(across(where(is.numeric), round, 5)) 返回 0.00039

我知道 digits = 命令使用特定列中的最大值指示列中的总位数,并且可能呈现不一致的小数位数,因此建议使用 round而不是试图搞乱 digits

感谢您的关注!!

一个选项是使用 formattable::comma 并指定 digits,这也会将列保留为 numeric

library(dplyr)
tab1 %>%
    mutate(across(where(is.numeric), ~ formattable::comma(., digits = 4)))
    contrast              ratio      SE df null  t.ratio p.value
X   (2-year) / (3-year)  0.4290  0.2000 51    1  -1.8180  0.1738
X.1 (2-year) / (4-year)  0.2860  0.1270 51    1  -2.8290  0.0180
X.2 (3-year) / (4-year)  0.6680  0.2600 51    1  -1.0340  0.5588
X.3   soybean / oat      0.0004  0.0002 51    1 -16.8570  <.0001
X.4   soybean / alfalfa  0.0032  0.0019 51    1  -9.7280  <.0001
X.5   soybean / corn     0.0331  0.0138 51    1  -8.1800  <.0001
X.6   oat / alfalfa      8.3400  5.2100 51    1   3.3920  0.0071
X.7   oat / corn        85.3000 39.8000 51    1   9.5410  <.0001
X.8   alfalfa / corn    10.2000  6.0300 51    1   3.9440  0.0014

或转换为tibble进行格式打印

tab1 %>%
     mutate(across(where(is.numeric), ~ as.numeric(sprintf('%.4f', .)))) %>% 
     as_tibble
# A tibble: 9 x 7
  `contrast           `   ratio      SE df    null   t.ratio p.value  
  <chr>                   <dbl>   <dbl> <chr> <chr>    <dbl> <chr>    
1 "(2-year) / (3-year)"  0.429   0.2    51    "   1"   -1.82 " 0.1738"
2 "(2-year) / (4-year)"  0.286   0.127  51    "   1"   -2.83 " 0.0180"
3 "(3-year) / (4-year)"  0.668   0.26   51    "   1"   -1.03 " 0.5588"
4 "soybean / oat    "    0.0004  0.0002 51    "   1"  -16.9  " <.0001"
5 "soybean / alfalfa"    0.0032  0.0019 51    "   1"   -9.73 " <.0001"
6 "soybean / corn   "    0.0331  0.0138 51    "   1"   -8.18 " <.0001"
7 "oat / alfalfa    "    8.34    5.21   51    "   1"    3.39 " 0.0071"
8 "oat / corn       "   85.3    39.8    51    "   1"    9.54 " <.0001"
9 "alfalfa / corn   "   10.2     6.03   51    "   1"    3.94 " 0.0014"