R函数解析打印到控制台的输出并返回有意义的对象

时间:2016-09-12 04:21:39

标签: r

有时会在R中出现一个函数将输出打印到控制台,该控制台永远不会作为对象返回。例如,factanal打印所解释的方差比例以及带有隐藏载荷的加载矩阵,但这些东西都不能作为返回对象直接供用户使用。虽然在某些情况下,存在特殊的提取器功能,但是如果要在后续分析中使用它,通常必须搜索相关的打印方法并尝试提取生成信息的相关代码。

因此,我很好奇是否有一个能够在R中解析打印输出的通用函数。理想情况下,这样的函数会识别何时打印矩阵/ data.frame并将其作为列表中的一个元素返回数据框架或矩阵格式。

为了具体说明,我使用factanal函数。如果我们运行以下代码:

fit <- factanal(matrix(rnorm(1000), ncol = 5), 2)
fit

我们得到以下输出:

Call:
factanal(x = matrix(rnorm(1000), ncol = 5), factors = 2)

Uniquenesses:
[1] 0.005 0.990 0.994 0.807 0.915

Loadings:
     Factor1 Factor2
[1,]  0.974   0.216 
[2,]                
[3,]                
[4,]          0.429 
[5,]          0.289 

               Factor1 Factor2
SS loadings      0.963   0.327
Proportion Var   0.193   0.065
Cumulative Var   0.193   0.258

Test of the hypothesis that 2 factors are sufficient.
The chi square statistic is 0.27 on 1 degree of freedom.
The p-value is 0.601 

有各种方法可以解析上述文本并将其作为有意义的对象返回。一种选择只是返回每行一行的字符向量。更复杂的方法将返回一个列表,其中每个元素在有空行的地方被分割,并且它将以某种方式识别矩阵的呈现位置。很明显,“加载:......”和它所说的“因子1,因子2”是矩阵的开始。

问题

  • R中是否有通用功能可用于提取打印输出的元素?
  • 或者,是否有一种通用方法可以很好地从打印到控制台的输出中提取输出?

具体而言,我感兴趣的是如何将这些方法应用于上述用于从因子分析中提取内容的特定案例。

1 个答案:

答案 0 :(得分:2)

以下是使用Jota推荐capture.output的部分答案。它还使用readr::read_fwfreadr::fwf_empty来智能地提取固定宽度的数据。

所以我们适合因子分析:

fit <- factanal(matrix(rnorm(1000), ncol = 5), 2)

然后我们使用capture.output()捕获输出。

all_output <- capture.output(fit)

这是all_output看起来的缩写版本(即,向量中每个元素有一行的字符向量):

 [1] ""                                                        
 [2] "Call:"                                                   
 [3] "factanal(x = matrix(rnorm(1000), ncol = 5), factors = 2)"
...                                
[15] ""                                                        
[16] "               Factor1 Factor2"                          
[17] "SS loadings      1.055   0.363"                          
[18] "Proportion Var   0.211   0.073"                          
[19] "Cumulative Var   0.211   0.284"                          

然后我们可以提取相关的行,按照read_fwf的预期与行分隔符合并为单个向量,并使用fwf_empty来猜测字段的划分位置:

x <- all_output[16:19] # extract lines with data.frame output
xc <- paste(x, collapse = "\n") # combine into a single character vector with new line
readr::read_fwf(xc, readr::fwf_empty(xc), ) # use fwf_empty to auto-detect widths

这将返回一个数据框:

# A tibble: 4 × 3
              X1      X2      X3
           <chr>   <chr>   <chr>
1           <NA> Factor1 Factor2
2    SS loadings   1.055   0.363
3 Proportion Var   0.211   0.073
4 Cumulative Var   0.211   0.284

可能会有更复杂的答案:

  • 解决data.frame名称不正确的问题
  • 可能会根据空行的存在自动将输出解析为离散元素
  • 可能会在第一列是行名称时自动检测
  • 自动检测打印矩阵/ data.frame的位置,可能基于具有相同字符数的行的存在:例如,nchar(capture.output(fit))