xtable用于条件单元格格式化表格中显著的p值

12
我正在使用xtable生成表格放入Latex中,想知道是否有一种方法可以对单元格进行条件格式设置,以使所有显著的p值都以灰色显示?我在TexShop中使用Knitr。
这里是一个示例,使用ggplot2中的diamonds数据,并运行TukeyHSD测试来预测从cut中的carat。
library(ggplot2)
library(xtable)
summary(data.aov <- aov(carat~cut, data = diamonds))
data.hsd<-TukeyHSD(data.aov)
data.hsd.result<-data.frame(data.hsd$cut)
data.hsd.result

我可以使用以下代码将data.hsd.result转换为xtable格式:

xtable(data.hsd.result)
在LaTeX中,输出如下所示:
                         diff         lwr         upr        p.adj
Good-Fair         -0.19695197 -0.23342631 -0.16047764 0.000000e+00
Very Good-Fair    -0.23975525 -0.27344709 -0.20606342 0.000000e+00
Premium-Fair      -0.15418175 -0.18762721 -0.12073628 0.000000e+00
Ideal-Fair        -0.34329965 -0.37610961 -0.31048970 0.000000e+00
Very Good-Good    -0.04280328 -0.06430194 -0.02130461 5.585171e-07
Premium-Good       0.04277023  0.02165976  0.06388070 3.256208e-07
Ideal-Good        -0.14634768 -0.16643613 -0.12625923 0.000000e+00
Premium-Very Good  0.08557350  0.06974902  0.10139799 0.000000e+00
Ideal-Very Good   -0.10354440 -0.11797729 -0.08911151 0.000000e+00
Ideal-Premium     -0.18911791 -0.20296592 -0.17526989 0.000000e+00

是否可以自动将任何p值小于0.05的值标记为灰色背景或以某种方式突出显示?显然,对于这个数据集,整个列都会被标记,但我希望能够处理所有我的数据。

2个回答

18

你好,试试这个:

\documentclass{article}
\usepackage{color}
\begin{document}

<<echo=FALSE, results='asis'>>=
df = data.frame(V1 = LETTERS[1:6], V2 = runif(6, 0, 1))
df$V3 = ifelse(df$V2 < 0.5, paste0("\\colorbox{red}{", df$V2, "}"), df$V2)
library(xtable)
print(xtable(df), sanitize.text.function = function(x) x)
@

\end{document}

编辑

如果您有多个条件,一种解决方案是使用包dplyr和函数case_when

set.seed(123)
df <- data.frame(V1 = LETTERS[1:6], V2 = runif(6, 0, 1))

library("dplyr")
df %>% 
  mutate(
    V3 = case_when(
      V2 < 0.5 ~ paste0("\\colorbox{red}{", round(V2, 3), "}"),
      V2 >= 0.5 & V2 < 0.8 ~ paste0("\\colorbox{blue}{", round(V2, 3), "}"),
      TRUE ~ formatC(V2, digits = 3)
    )
  )
#   V1        V2                      V3
# 1  A 0.2875775  \\colorbox{red}{0.288}
# 2  B 0.7883051 \\colorbox{blue}{0.788}
# 3  C 0.4089769  \\colorbox{red}{0.409}
# 4  D 0.8830174                   0.883
# 5  E 0.9404673                    0.94
# 6  F 0.0455565  \\colorbox{red}{0.046}

谢谢@Victorp,但我注意到转换后的数据小数位数要长得多。有什么提示可以让它保持与其他列相同的位数? - PaoloCrosetto
@Victorp df$V2 < 0.5 ;) - Luca Braglia
@PaoloCrosetto,你可以在ifelse中使用round(df$V2, 4L)。此外,你还可以添加options(scipen = 10)来惩罚科学计数法。 - akhmed
如果我想要强加多个条件,例如:df$V3 = ifelse(df$V2 < 0.5, paste0("\\colorbox{red}{", df$V2, "}"), df$V2)df$V3 = ifelse(df$V2 >= 0.5 & df$V2 <0.8, paste0("\\colorbox{blue}{", df$V2, "}"), df$V2),第二行代码将无法工作,因为第一行代码将 df$V3 转换为 "character",在其上不能强加数值条件。有什么解决方法吗? - Jason Goal
@Jason,你可以嵌套使用ifelse。请看我的编辑,有一个更优雅的解决方案。 - Victorp
@Victorp,确实优雅,我知道有像你这样的优秀程序员,这将会非常简短。 - Jason Goal

1
Victorp提供了一个出色的解决方案,使我从长达数小时的挣扎中得到了极大的缓解。然后在同一天晚些时候,我需要对相同的数据集施加多个条件,这意味着我需要根据不同的条件在单元格上使用两种不同的颜色。基于Victorp的答案,我找到了一个解决方案,并希望这可以帮助那些将来需要这个功能的人。
    <<echo=FALSE, results='asis'>>=
    df = data.frame(V1 = LETTERS[1:6], V2 = runif(6, 0, 1),V3 = runif(6, 0, 1))
    ## replicate the data frame of which you are going to highlight the cells
    ## the number of duplicates should be equal to number of conditions you want to impose
    temp.1<-df
    temp.2<-df
    ## impose conditions on those temporary data frame separately.
    ## change the columns you want to 
    for (i in colnames(temp.1)[2:3]) {
    temp.1[,i]= ifelse(temp.1[,i] <= 0.5,
                                paste0("\\colorbox{red}{", temp.1[,i], "}"), temp.1[,i])}
    rm(i)


    for (i in colnames(temp.2)[2]) {
    temp.2[,i]= ifelse(temp.2[,i] > 0.5 & temp.2[,i] <=0.8,
                                paste0("\\colorbox{blue}{", temp.2[,i], "}"),temp.2[,i])}
    rm(i)
    ## then record the position of cells under you conditions
    pos.1<-which(df[,] <=0.5,arr.ind = TRUE)
    pos.2<-which(df[,] >0.5 & df[,]<=0.8,arr.ind = TRUE)
    ## replace cells in original data frame that you want to highlight
    ## replace those values in temp which satisfy the condition imposed on temp.1
    if(length(pos.1)>0) {
      temp[pos.1]<-temp.1[pos.1]
    }


    ## replace those values in temp which satisfy the condition imposed on temp.2
    if(length(pos.2)>0) {
      temp[pos.2]<-temp.2[pos.2]
    }
    rm(temp.1,temp.2,pos.1,pos.2)
    @

然后您可以按照自己的方式打印df。虽然这种方法可行,但考虑到R的强大功能,我相信应该有更简单的方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接