R return types of commands and capturing R model summaries in emac's org mode

StackOverflow https://stackoverflow.com/questions/22519211

  •  17-06-2023
  •  | 
  •  

Вопрос

When you type a command in R say:

>5
[1] 5

it returns the integer 5 prefaced by [1]. Similar stuff happens when using a semicolon

>c(1,2,3); c(2,3,4)
[1] 1 2 3
[1] 2 3 4

If you assign 5 to a variable it does not return anything:

>a = 5

I think I understand R as a repl. If there is anything besides a variable assignment going on it prints that out prefaced by [1]

What confuses me is that doing something like this

>a = c(1,2,3)
>b = c(1,2,3)
>data = as.data.frame(cbind(a,b))
>model = lm(a ~ b, data)
>summary(model)
Call:
lm(formula = a ~ b, data = data)

Residuals:
1 2 3 
0 0 0 
.
.
.

Residual standard error: 0 on 1 degrees of freedom
Multiple R-squared:      1, Adjusted R-squared:      1 
F-statistic:   Inf on 1 and 1 DF,  p-value: < 2.2e-16

My question is why is there no [1] in front of the summary of the model? In addition for emac's org mode to capture the results of a code block, the end of the code block seems to need to "return" something (i.e. the [1] prefaced in front of it). I read about the need to return something here. My idea right now is to capture the summary output in a PNG of some sort to display in my org mode block, however, I'd like to understand what's going on here and if there is a more basic hack. Also does anyone have any best practices for capturing the output of R model summaries in emac's org mode.

Thanks!!!!

UPDATE:

Using the 3 posts below I came up with:

#+begin_src R :results output :session R :exports results
library(ascii)
options(asciiType="org")
options(warn = -1)
a = c(1,2,3)
b = c(1,2,3)
data = as.data.frame(cbind(a,b))
model = lm(a ~ b, data)
ascii(summary(model))
#+end_src

Это было полезно?

Решение

I've wondered about this myself and went source code sleuthing.

The reason there is no '[1]' is that summary(model) returns an object of class summaryDefault which has a method SummaryDefault.print defined for it which gets called by the repl when it prints the summary info to the terminal and returns the summaryDefault object invisibly. So, the underlying vector of summary stats itself is not printed by print.default, which provides those indexes inside brackets.

However, the lack of the '[1]' is not the reason org is returning a blank result.

Here is the reason:

When you declare an org-mode code block with :returns value, Org mode tries to convert the value of the last expression in your code block into something that can be formatted as an org table (i.e. with | characters as delimiters).

It takes advantage of R's special variable .Last.value to get the value that needs to be converted.

It tries to convert this value to by calling the R function write.table on it, writing to a temp file which it then reads/parses/reformats into well formatted org table.

Alas, write.table, when called on an object of class SummaryDefault, generates an error, which gets caught and is silently un-reported, but that temp file winds up empty.

So there is nothing to reformat into an org table.

Your options today include:

  • OK: declare your code block instead with :returns output. Downside of this is that it will return ALL output, and the summary is not nicely reformatted into an org-table which maybe you want.
  • OK: leave it as returns :value, but make the last expression in your block be capture.output(summary(model)). The output will be a one column table, with one row for each line of output.
  • Better: leave it as returns :value, but make the last expression be unclass(summary(model)). Then the vector will get printed. Add a :rownames yes and we're looking pretty.
  • Betterer: leave it as returns :value, but use t(summary(model)) to simultaneously unclass the value and get it formatted wide.
  • Betterest: leave it as returns :value, but use t(t(summary(model))) to simultaneously unclass the value and keep it formatted skinny.

It is after all a reach to expect org to magically be able to convert any R data structure to a data.frame like thing and from there to an org table. I suppose org magic could catch the error and try something else, like calling t(t(.)) on the object it is trying to coerce to something tabular. Or as(.,data.frame). I'm not sure that's in the org "spirit". I wonder...

In any case, it would be good if org mode would raise an error, like, "Erhm, how do expect me to convert a summaryDefault object to a table".

Or?

Другие советы

There is a read-eval-print loop in R. Sometimes, however, the print method does not get anything if the method returns the value "invisibly" although that is not the case here. Furthermore, in the case of summary methods (which are generic) there is/are often specific print method(s) which will be associated with the generic summary function(s). These print functions then intervene and may instead print something at the console that is thought to be more easily digestible to human eyes that the nested list object that is actually the returned value. (So the print.summary.lm function uses cat, which works by side-effects and has no value, to "print" to the console and then returns the value ... invisibly.) In the simple case of:

a = 5

You can test for what is returned with:

b <- (a = 5)
b
[1] 5

So what is returned is the evaluated expression on the RHS of the assignment.

> d = 6
> e <- (b=d)
> e
[1] 6

If you type methods(print) you will see that there is a print.summary.lm* function that dispatched and handles the task of output to the console but what appears at the console is not the same as what you see with str(summary(model)). (The trailing asterisk means that the function will not be printed to the console if you just type its name, but you can get it to print with stats:::print.summary.lm.) You can also look at either:

?`<-`
?assign

I cannot really help with the Emacs part of the question. You may want to use either sink or capture.output to recover and store text identical to console output.

> cap <- capture.output(summary(model))
> print(cap)
 [1] ""                                                              
 [2] "Call:"                                                         
 [3] "lm(formula = a ~ b, data = data)"                              
 [4] ""                                                              
 [5] "Residuals:"                                                    
 [6] "1 2 3 "                                                        
 [7] "0 0 0 "                                                        
 [8] ""                                                              
 [9] "Coefficients:"                                                 
[10] "            Estimate Std. Error t value Pr(>|t|)    "          
[11] "(Intercept)        0          0      NA       NA    "          
[12] "b                  1          0     Inf   <2e-16 ***"          
[13] "---"                                                           
[14] "Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1"
[15] ""                                                              
[16] "Residual standard error: 0 on 1 degrees of freedom"            
[17] "Multiple R-squared:      1,\tAdjusted R-squared:      1 "      
[18] "F-statistic:   Inf on 1 and 1 DF,  p-value: < 2.2e-16"         
[19] ""                                                        

[1] ([2], etc) is for showing values of vectors. It refers to the index of the leftmost value that is shown in this line. There are no scalars in R, that's why you see [1] even if you assign a single value to a variable. On the other hand, if you print something to standard output (say, using cat), that's not going to be the value that the function call returned (the result of cat is "invisible" NULL) but rather a side effect. Hence, no [1].

In order to use R with org-mode you need to decide what do you want to have in your document after a code block is executed: the last value, the output, or an image you code generated. It is controlled by :results header argument:

#+begin_src R :results value
  a <- 5
#+end_src

Please see R Source Code Blocks in Org Mode for more details.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top