9

我正在尝试为 R 找到一个函数,它可以data.frame像这样以 MySQL 样式的 ascii 表输出对象

+----+------+------+
| id | var1 | var2 |
+----+------+------+
|  1 | asdf | g    |
|  2 | asdf | h    |
|  3 | asdf | j    |
+----+------+------+

有这样的功能吗?至少有两个工具可以做到这一点

但是有没有办法直接从 R 中做到这一点?

4

3 回答 3

22

使用您的数据:

d <- data.frame(id = 1:3, va1 = rep("asdf", 3), var2 = c("g","h","j"),
                stringsAsFactors = FALSE)

这里有一些可以帮助您入门的东西,至少对于简单的表格来说可能就足够了。

asciify <- function(df, pad = 1, ...) {
    ## error checking
    stopifnot(is.data.frame(df))
    ## internal functions
    SepLine <- function(n, pad = 1) {
        tmp <- lapply(n, function(x, pad) paste(rep("-", x + (2* pad)),
                                                collapse = ""),
                      pad = pad)
        paste0("+", paste(tmp, collapse = "+"), "+")
    }
    Row <- function(x, n, pad = 1) {
        foo <- function(i, x, n) {
            fmt <- paste0("%", n[i], "s")
            sprintf(fmt, as.character(x[i]))
        }
        rowc <- sapply(seq_along(x), foo, x = x, n = n)
        paste0("|", paste(paste0(rep(" ", pad), rowc, rep(" ", pad)),
                          collapse = "|"),
               "|")
    }
    ## convert everything to characters
    df <- as.matrix(df)
    ## nchar in data
    mdf <- apply(df, 2, function(x) max(nchar(x)))
    ## nchar in names
    cnames <- nchar(colnames(df))
    ## max nchar of name+data per elements
    M <- pmax(mdf, cnames)
    ## write the header
    sep <- SepLine(M, pad = pad)
    writeLines(sep)
    writeLines(Row(colnames(df), M, pad = pad))
    writeLines(sep)
    ## write the rows
    for(i in seq_len(nrow(df))) {
        ## write a row
        writeLines(Row(df[i,], M, pad = pad))
        ## write separator
        writeLines(sep)
    }
    invisible(df)
}

在使用中我们得到:

> asciify(d)
+----+------+------+
| id |  va1 | var2 |
+----+------+------+
|  1 | asdf |    g |
+----+------+------+
|  2 | asdf |    h |
+----+------+------+
|  3 | asdf |    j |
+----+------+------+

在一些更复杂的事情上,我们得到

> asciify(mtcars)
+------+-----+-------+-----+------+-------+-------+----+----+------+------+
|  mpg | cyl |  disp |  hp | drat |    wt |  qsec | vs | am | gear | carb |
+------+-----+-------+-----+------+-------+-------+----+----+------+------+
|   21 |   6 |   160 | 110 |  3.9 |  2.62 | 16.46 |  0 |  1 |    4 |    4 |
+------+-----+-------+-----+------+-------+-------+----+----+------+------+
|   21 |   6 |   160 | 110 |  3.9 | 2.875 | 17.02 |  0 |  1 |    4 |    4 |
+------+-----+-------+-----+------+-------+-------+----+----+------+------+
| 22.8 |   4 |   108 |  93 | 3.85 |  2.32 | 18.61 |  1 |  1 |    4 |    1 |
+------+-----+-------+-----+------+-------+-------+----+----+------+------+
| 21.4 |   6 |   258 | 110 | 3.08 | 3.215 | 19.44 |  1 |  0 |    3 |    1 |
+------+-----+-------+-----+------+-------+-------+----+----+------+------+
| 18.7 |   8 |   360 | 175 | 3.15 |  3.44 | 17.02 |  0 |  0 |    3 |    2 |
+------+-----+-------+-----+------+-------+-------+----+----+------+------+
| 18.1 |   6 |   225 | 105 | 2.76 |  3.46 | 20.22 |  1 |  0 |    3 |    1 |
+------+-----+-------+-----+------+-------+-------+----+----+------+------+
| 14.3 |   8 |   360 | 245 | 3.21 |  3.57 | 15.84 |  0 |  0 |    3 |    4 |
+------+-----+-------+-----+------+-------+-------+----+----+------+------+
| 24.4 |   4 | 146.7 |  62 | 3.69 |  3.19 |    20 |  1 |  0 |    4 |    2 |
+------+-----+-------+-----+------+-------+-------+----+----+------+------+
| 22.8 |   4 | 140.8 |  95 | 3.92 |  3.15 |  22.9 |  1 |  0 |    4 |    2 |
+------+-----+-------+-----+------+-------+-------+----+----+------+------+
| 19.2 |   6 | 167.6 | 123 | 3.92 |  3.44 |  18.3 |  1 |  0 |    4 |    4 |
+------+-----+-------+-----+------+-------+-------+----+----+------+------+
| 17.8 |   6 | 167.6 | 123 | 3.92 |  3.44 |  18.9 |  1 |  0 |    4 |    4 |
+------+-----+-------+-----+------+-------+-------+----+----+------+------+
| 16.4 |   8 | 275.8 | 180 | 3.07 |  4.07 |  17.4 |  0 |  0 |    3 |    3 |
+------+-----+-------+-----+------+-------+-------+----+----+------+------+
| 17.3 |   8 | 275.8 | 180 | 3.07 |  3.73 |  17.6 |  0 |  0 |    3 |    3 |
+------+-----+-------+-----+------+-------+-------+----+----+------+------+
| 15.2 |   8 | 275.8 | 180 | 3.07 |  3.78 |    18 |  0 |  0 |    3 |    3 |
+------+-----+-------+-----+------+-------+-------+----+----+------+------+
| 10.4 |   8 |   472 | 205 | 2.93 |  5.25 | 17.98 |  0 |  0 |    3 |    4 |
+------+-----+-------+-----+------+-------+-------+----+----+------+------+
| 10.4 |   8 |   460 | 215 |    3 | 5.424 | 17.82 |  0 |  0 |    3 |    4 |
+------+-----+-------+-----+------+-------+-------+----+----+------+------+
| 14.7 |   8 |   440 | 230 | 3.23 | 5.345 | 17.42 |  0 |  0 |    3 |    4 |
+------+-----+-------+-----+------+-------+-------+----+----+------+------+
| 32.4 |   4 |  78.7 |  66 | 4.08 |   2.2 | 19.47 |  1 |  1 |    4 |    1 |
+------+-----+-------+-----+------+-------+-------+----+----+------+------+
| 30.4 |   4 |  75.7 |  52 | 4.93 | 1.615 | 18.52 |  1 |  1 |    4 |    2 |
+------+-----+-------+-----+------+-------+-------+----+----+------+------+
| 33.9 |   4 |  71.1 |  65 | 4.22 | 1.835 |  19.9 |  1 |  1 |    4 |    1 |
+------+-----+-------+-----+------+-------+-------+----+----+------+------+
| 21.5 |   4 | 120.1 |  97 |  3.7 | 2.465 | 20.01 |  1 |  0 |    3 |    1 |
+------+-----+-------+-----+------+-------+-------+----+----+------+------+
| 15.5 |   8 |   318 | 150 | 2.76 |  3.52 | 16.87 |  0 |  0 |    3 |    2 |
+------+-----+-------+-----+------+-------+-------+----+----+------+------+
| 15.2 |   8 |   304 | 150 | 3.15 | 3.435 |  17.3 |  0 |  0 |    3 |    2 |
+------+-----+-------+-----+------+-------+-------+----+----+------+------+
| 13.3 |   8 |   350 | 245 | 3.73 |  3.84 | 15.41 |  0 |  0 |    3 |    4 |
+------+-----+-------+-----+------+-------+-------+----+----+------+------+
| 19.2 |   8 |   400 | 175 | 3.08 | 3.845 | 17.05 |  0 |  0 |    3 |    2 |
+------+-----+-------+-----+------+-------+-------+----+----+------+------+
| 27.3 |   4 |    79 |  66 | 4.08 | 1.935 |  18.9 |  1 |  1 |    4 |    1 |
+------+-----+-------+-----+------+-------+-------+----+----+------+------+
|   26 |   4 | 120.3 |  91 | 4.43 |  2.14 |  16.7 |  0 |  1 |    5 |    2 |
+------+-----+-------+-----+------+-------+-------+----+----+------+------+
| 30.4 |   4 |  95.1 | 113 | 3.77 | 1.513 |  16.9 |  1 |  1 |    5 |    2 |
+------+-----+-------+-----+------+-------+-------+----+----+------+------+
| 15.8 |   8 |   351 | 264 | 4.22 |  3.17 |  14.5 |  0 |  1 |    5 |    4 |
+------+-----+-------+-----+------+-------+-------+----+----+------+------+
| 19.7 |   6 |   145 | 175 | 3.62 |  2.77 |  15.5 |  0 |  1 |    5 |    6 |
+------+-----+-------+-----+------+-------+-------+----+----+------+------+
|   15 |   8 |   301 | 335 | 3.54 |  3.57 |  14.6 |  0 |  1 |    5 |    8 |
+------+-----+-------+-----+------+-------+-------+----+----+------+------+
| 21.4 |   4 |   121 | 109 | 4.11 |  2.78 |  18.6 |  1 |  1 |    4 |    2 |
+------+-----+-------+-----+------+-------+-------+----+----+------+------+

请注意,代码不处理在小数点上对齐数字数据,但Row()可以修改内部函数的代码以适应所有需要的sprintf()调用略有不同。另外,我意识到我已将字符串右对齐,这不是您在示例表中显示的内容,但不是终端故障!

要在文件中获取输出,请asciify()使用以下命令捕获输出capture.output()

> capture.output(asciify(d), file = "asciified_d.txt")
> readLines("asciified_d.txt")
[1] "+----+------+------+" "| id |  va1 | var2 |" "+----+------+------+"
[4] "|  1 | asdf |    g |" "+----+------+------+" "|  2 | asdf |    h |"
[7] "+----+------+------+" "|  3 | asdf |    j |" "+----+------+------+"

(注意上面显示的输出只是一个字符串向量,每个字符串在捕获的文件中占一行。文件在磁盘上看起来像这样:

$ cat asciified_d.txt 
+----+------+------+
| id |  va1 | var2 |
+----+------+------+
|  1 | asdf |    g |
+----+------+------+
|  2 | asdf |    h |
+----+------+------+
|  3 | asdf |    j |
+----+------+------+

.)

我没有检查过这么多,在很多情况下它很可能会失败,但它适用于基本数据帧。

Update asciify()现在处理带有因子的数据帧以及字符和数字数据:

> require(ggplot2)
> asciify(head(diamonds))
+-------+-----------+-------+---------+-------+-------+-------+------+------+------+
| carat |       cut | color | clarity | depth | table | price |    x |    y |    z |
+-------+-----------+-------+---------+-------+-------+-------+------+------+------+
|  0.23 |     Ideal |     E |     SI2 |  61.5 |    55 |   326 | 3.95 | 3.98 | 2.43 |
+-------+-----------+-------+---------+-------+-------+-------+------+------+------+
|  0.21 |   Premium |     E |     SI1 |  59.8 |    61 |   326 | 3.89 | 3.84 | 2.31 |
+-------+-----------+-------+---------+-------+-------+-------+------+------+------+
|  0.23 |      Good |     E |     VS1 |  56.9 |    65 |   327 | 4.05 | 4.07 | 2.31 |
+-------+-----------+-------+---------+-------+-------+-------+------+------+------+
|  0.29 |   Premium |     I |     VS2 |  62.4 |    58 |   334 | 4.20 | 4.23 | 2.63 |
+-------+-----------+-------+---------+-------+-------+-------+------+------+------+
|  0.31 |      Good |     J |     SI2 |  63.3 |    58 |   335 | 4.34 | 4.35 | 2.75 |
+-------+-----------+-------+---------+-------+-------+-------+------+------+------+
|  0.24 | Very Good |     J |    VVS2 |  62.8 |    57 |   336 | 3.94 | 3.96 | 2.48 |
+-------+-----------+-------+---------+-------+-------+-------+------+------+------+
于 2012-10-22T13:16:53.583 回答
9

另一个已经比我在午餐时写的代码更先进的解决方案是pander,它在 Pandoc markdown 中呈现 R 对象,以便随后转换为一系列其他格式。

标记与显示的 MySQL 不太相同,但最相似的是:

> pandoc.table(m, style = "grid")

+---------------------+-------+-------+--------+
| &nbsp;              | mpg   | cyl   | disp   |
+=====================+=======+=======+========+
| **Mazda RX4**       | 21    | 6     | 160    |
+---------------------+-------+-------+--------+
| **Mazda RX4 Wag**   | 21    | 6     | 160    |
+---------------------+-------+-------+--------+

如您所见,这具有对行名称的内置处理(我的没有),并且随着时间的推移可能会获得更多的糖。

在这个 StackOverflow question中有一些相关的讨论和进一步的例子。

于 2012-10-22T15:56:31.013 回答
5

如果您追求的是 HTML 结果,也许您可​​以收获googleVis包的力量。您在包中有更多示例demo()

library(googleVis)
x <- data.frame(matrix(runif(9), nrow = 3))
xg <- gvisTable(x, options=list(page='enable', height=300))
plot(xg)

上面的块将生成一个看起来像这样的网页。

在此处输入图像描述

如果您正在寻找报告工具,可以Markdown在 RStudio 中查看。

于 2012-10-22T20:06:36.660 回答