如何从 sprintf 打印 R 矩阵



对于以下矩阵:

> mat
             [,1]          [,2]          [,3]
[1,] 8.326673e-17  5.551115e-17  5.551115e-17
[2,] 2.775558e-17  3.677614e-16 -5.551115e-17
[3,] 0.000000e+00 -2.775558e-17  5.551115e-17

请考虑以下sprintf

sprintf("proj: %s", mat)

输出为:

print(sprintf("proj: %s", mat))
[1] "proj: 8.32667268468867e-17"  "proj: 2.77555756156289e-17"
[3] "proj: 0"                     "proj: 5.55111512312578e-17"
[5] "proj: 3.67761376907083e-16"  "proj: -2.77555756156289e-17"
[7] "proj: 5.55111512312578e-17"  "proj: -5.55111512312578e-17"
[9] "proj: 5.55111512312578e-17"

我们想要的是与 mat 相同的输出,但具有

"项目:"

消息已预置。具体说来:

proj:             [,1]          [,2]          [,3]
[1,] 8.326673e-17  5.551115e-17  5.551115e-17
[2,] 2.775558e-17  3.677614e-16 -5.551115e-17
[3,] 0.000000e+00 -2.775558e-17  5.551115e-17

如何使用sprintf来实现这一点?

更新 从 Sven 的回答中,尝试创建一个函数在这里:

printmat <- function(mat) {
  out <- capture.output(mat)
  out[1] <- paste0("proj:", out[1])
  paste(out, collapse = "n")
}

这是输出:单行(最好像原来一样 4 行):

print(printmat(mat))
[1] "proj:             [,1]          [,2]          [,3]n[1,] 8.326673e-17  5.551115e-17  5.551115e-17n[2,] 2.775558e-17  3.677614e-16 -5.551115e-17n[3,] 0.000000e+00 -2.775558e-17  5.551115e-17"

另一个更新 一个不同的答案 - 来自理查德斯克里文 - 使用print.listof(list) . 这是一个包含capture.output的功能。 然而,此解决方案存在不允许灵活消息的困扰:它被硬编码为"proj"

printmat <- function(mat) {
  out <- capture.output(print.listof(list(proj = mat)))
}

这是输出:它很接近..但请注意,我们无法选择将"proj"更改为其他内容:

   print(printmat(mat))
[1] "proj :"
[2] "             [,1]          [,2]          [,3]"
[3] "[1,] 8.326673e-17  5.551115e-17  5.551115e-17"
[4] "[2,] 2.775558e-17  3.677614e-16 -5.551115e-17"
[5] "[3,] 0.000000e+00 -2.775558e-17  5.551115e-17"
[6] ""

第三次更新 我添加了一个灵活的"消息/矩阵名称"参数。但是,sprintf将其附加到输出的每一行:

printmat <- function(msg, mat) {
  out <- capture.output(print.listof(list(mat)))
  sprintf("%s: %s", msg, out)
}

这是一个测试:

> print(printmat("mymat", mat))
[1] "mymat: Component 1 :"
[2] "mymat:              [,1]          [,2]          [,3]"
[3] "mymat: [1,] 8.326673e-17  5.551115e-17  5.551115e-17"
[4] "mymat: [2,] 2.775558e-17  3.677614e-16 -5.551115e-17"
[5] "mymat: [3,] 0.000000e+00 -2.775558e-17  5.551115e-17"
[6] "mymat:

那么有没有办法禁止sprintf行前面加上消息呢?

使用 sprintf(),您将整个矩阵转换为字符,使以后访问其数值变得更加困难。

相反,您可以使用 listof 类,然后仍然可以访问所有数值。首先将矩阵(或矩阵)放入命名列表中。以下是它的外观快速浏览。

m <- structure(c(8.326673e-17, 2.775558e-17, 0, 5.551115e-17, 3.677614e-16, 
-2.775558e-17, 5.551115e-17, -5.551115e-17, 5.551115e-17), .Dim = c(3L, 
3L))
print.listof(list(proj = m))
# proj :
#              [,1]          [,2]          [,3]
# [1,] 8.326673e-17  5.551115e-17  5.551115e-17
# [2,] 2.775558e-17  3.677614e-16 -5.551115e-17
# [3,] 0.000000e+00 -2.775558e-17  5.551115e-17

为了做到这一点,我们不需要调用 print.listof() ,我们可以将listof类添加到包含 m 的列表中。然后它将像您想要的那样打印,您仍然可以访问不变的矩阵值。

mm <- list(proj = m)
class(mm) <- "listof"
mm
# proj :
#              [,1]          [,2]          [,3]
# [1,] 8.326673e-17  5.551115e-17  5.551115e-17
# [2,] 2.775558e-17  3.677614e-16 -5.551115e-17
# [3,] 0.000000e+00 -2.775558e-17  5.551115e-17    
mm$proj[1,]
# [1] 8.326673e-17 5.551115e-17 5.551115e-17

您可以随时更改第一行,只需更改mm的名称

即可
setNames(mm, "PROJ")
# PROJ :
#              [,1]          [,2]          [,3]
# [1,] 8.326673e-17  5.551115e-17  5.551115e-17
# [2,] 2.775558e-17  3.677614e-16 -5.551115e-17
# [3,] 0.000000e+00 -2.775558e-17  5.551115e-17

最后,以下是我们如何将所有这些信息用作函数:

f <- function(mat, nm) {
    x <- setNames(list(mat), nm)
    class(x) <- "listof"
    x
}
f(m, "proj")
f(m, "project 1")

这是capture.output的方法:

# an example matrix
mat <- matrix(rnorm(9), nrow = 3)
# standard print output
out <- capture.output(mat)
# modify first line
out[1] <- paste0("proj:", out[1])
# print modified version
cat(paste(out, collapse = "n"))

输出:

proj:          [,1]       [,2]      [,3]
[1,] 0.8760935 -0.8395728 -1.569009
[2,] 0.2660100 -2.2364285 -1.872737
[3,] 0.4996019 -0.6997563 -2.136702

作为一个函数:

printmat <- function(mat) {
  out <- capture.output(mat)
  out[1] <- paste0("proj:", out[1])
  cat(paste(out, collapse = "n"))
}

printmat(mat)

最新更新