【问题标题】:Controlling output while printing data.table with xtable使用 xtable 打印 data.table 时控制输出
【发布时间】:2015-02-17 23:53:29
【问题描述】:

这是一个data.table,有很多记录/行:

dt <- data.table(a=sample(letters,1000,replace = T), b=rnorm(1000))

我们可以简单地使用:

dt

... 并生成一个非常方便的视图,其中包含第一行和最后 5 行。

但是,当使用 xtable 打印此文件时,使用 knitr 打印 pdf 报告时,xtable 会打印所有一千行:

print(xtable(dt))

任何想法如何解决这个问题?

我想要来自xtable 的漂亮表格,但默认格式为data.table

rbind 这样带有前五个元素和后五个元素的hack 是可能的,但不是很优雅。

【问题讨论】:

  • 您可以查看print.data.table 的函数定义,看看它是如何完成的。
  • 为什么要找到那个函数? xtabledata.table 中似乎不存在。
  • getAnywhere("print.data.table") 应该这样做。

标签: r data.table knitr xtable


【解决方案1】:

这里是 print.data.table 的修改版本,它返回格式化的对象而不是打印它:

firstLast <- function(x, ...) {
    UseMethod("firstLast")
}

firstLast.data.table  <- function (x,
                                   topn = getOption("datatable.print.topn"),
                                   nrows = getOption("datatable.print.nrows"),
                                   row.names = TRUE, ...) {
    if (!is.numeric(nrows)) 
        nrows = 100L
    if (!is.infinite(nrows)) 
        nrows = as.integer(nrows)
    if (nrows <= 0L) 
        return(invisible())
    if (!is.numeric(topn)) 
        topn = 5L
    topnmiss = missing(topn)
    topn = max(as.integer(topn), 1L)
    if (nrow(x) == 0L) {
        if (length(x) == 0L) 
            return("Null data.table (0 rows and 0 cols)\n")
        else return(paste("Empty data.table (0 rows) of ", length(x), 
            " col", if (length(x) > 1L) 
                "s", ": ", paste(head(names(x), 6), collapse = ","), 
            if (ncol(x) > 6) 
                "...", "\n", sep = ""))
    }
    if (topn * 2 < nrow(x) && (nrow(x) > nrows || !topnmiss)) {
        toprint = rbind(head(x, topn), tail(x, topn))
        rn = c(seq_len(topn), seq.int(to = nrow(x), length.out = topn))
        printdots = TRUE
    }
    else {
        toprint = x
        rn = seq_len(nrow(x))
        printdots = FALSE
    }
    toprint = data.table:::format.data.table(toprint, ...)
    if (isTRUE(row.names)) 
        rownames(toprint) = paste(format(rn, right = TRUE), ":", 
            sep = "")
    else rownames(toprint) = rep.int("", nrow(x))
    if (is.null(names(x))) 
        colnames(toprint) = rep("NA", ncol(toprint))
    if (printdots) {
        toprint = rbind(head(toprint, topn), `---` = "", tail(toprint, 
            topn))
        rownames(toprint) = format(rownames(toprint), justify = "right")
        return(toprint)
    }
    if (nrow(toprint) > 20L) 
        toprint = rbind(toprint, matrix(colnames(toprint), nrow = 1))
    return(toprint)
}

这可以用来准备一个大的data.table,以供xtable格式化:

library(xtable)
xtable(firstLast(dt))
% latex table generated in R 3.1.2 by xtable 1.7-4 package
% Tue Feb 17 20:15:12 2015
\begin{table}[ht]
\centering
\begin{tabular}{rll}
  \hline
 & a & b \\ 
  \hline
   1: & i & -0.6356429 \\ 
     2: & w & -1.1533783 \\ 
     3: & r & -0.7459959 \\ 
     4: & x &  1.5646809 \\ 
     5: & o & -1.8158744 \\ 
    --- &  &  \\ 
   996: & z & -1.0835897 \\ 
   997: & a &  0.9219506 \\ 
   998: & q &  0.3388118 \\ 
   999: & l & -1.7123250 \\ 
  1000: & l &  0.1240633 \\ 
   \hline
\end{tabular}
\end{table}

【讨论】:

  • 非常感谢。这正是我所需要的。我尝试将您在此处编写的函数与我从getAnywhere(print.data.table) 获得的函数进行比较,发现差异很小。你能解释一下你在这里改变了什么吗?此外,任何阅读参考的建议将不胜感激!
  • R 中的函数一般都会返回一个值,而这个值通常是有趣的东西。但是这个一般规则也有例外,print 函数就是这些例外之一。我们不使用print 作为返回值,而是将某些内容打印到控制台。我对print.data.table 的修改只是使它的行为更像大多数其他函数,即它返回一个值而不是打印它。
  • 哦,我明白了...谢谢。这很有帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-30
  • 2015-01-05
相关资源
最近更新 更多