emacs-orgmode@gnu.org archives
 help / color / mirror / code / Atom feed
* [babel] creating simple vectors in R
@ 2010-10-05 20:37 Dan Davison
  2010-10-05 21:35 ` Erik Iverson
  0 siblings, 1 reply; 2+ messages in thread
From: Dan Davison @ 2010-10-05 20:37 UTC (permalink / raw)
  To: emacs org-mode mailing list

I'd appreciate opinions from R users on the following org-babel-R
details:

Currently, Org tables, and lisp lists, are converted into data frames
when they are sent from Org to R, and we have no way to create simple
vectors such as c(1,2). I'd like to know whether users of org and R
would approve of the following change that makes simple R vectors
possible, or have other suggestions related to these issues.

With the patch below, there would be two ways to create a simple vector
in R. The most direct way is to pass a non-nested lisp list:

#+begin_src R :var x='(1 2) :results output
str(x)
#+end_src

CURRENT OUTPUT:
#+results:
: 'data.frame':	1 obs. of  2 variables:
:  $ V1: int 1
:  $ V2: int 2

NEW OUTPUT:
#+results:
:  num [1:2] 1 2

In addition, because babel's table-indexing code produces a non-nested
list when taking a one-dimensional slice, this would be another
situation in which a vector rather than data frame is created:

#+tblname: input-tab
    | 1 | 3 |
    | 2 | 4 |

#+begin_src R :var x=input-tab[0,] :results output
str(x)
#+end_src

CURRENT OUTPUT:
#+results:
: 'data.frame':	1 obs. of  2 variables:
:  $ V1: int 1
:  $ V2: int 3

NEW OUTPUT:
#+results:
:  num [1:2] 1 3

There's a possible argument that that's slightly at odds with R, since,
in R, a single row slice of a data frame is still a data frame.

A related issue is translating an Org table into a matrix rather than a
data frame in R. This can be done explicitly with a call to as.matrix in
the user's code, but if anyone feels that it would be helpful for babel
to automate this then do say so.

Dan


diff --git a/lisp/ob-R.el b/lisp/ob-R.el
index c709064..4b49af5 100644
--- a/lisp/ob-R.el
+++ b/lisp/ob-R.el
@@ -141,16 +141,18 @@ This function is called by `org-babel-execute-src-block'."
 (defun org-babel-R-assign-elisp (name value colnames-p rownames-p)
   "Construct R code assigning the elisp VALUE to a variable named NAME."
   (if (listp value)
-      (let ((transition-file (org-babel-temp-file "R-import-")))
-        ;; ensure VALUE has an orgtbl structure (depth of at least 2)
-        (unless (listp (car value)) (setq value (list value)))
-        (with-temp-file transition-file
-          (insert (orgtbl-to-tsv value '(:fmt org-babel-R-quote-tsv-field)))
-          (insert "\n"))
-        (format "%s <- read.table(\"%s\", header=%s, row.names=%s, sep=\"\\t\", as.is=TRUE)"
-                name (org-babel-process-file-name transition-file 'noquote)
-               (if (or (eq (nth 1 value) 'hline) colnames-p) "TRUE" "FALSE")
-               (if rownames-p "1" "NULL")))
+      (if (listp (car value))
+         (let ((transition-file (org-babel-temp-file "R-import-")))
+           (with-temp-file transition-file
+             (insert (orgtbl-to-tsv value '(:fmt org-babel-R-quote-tsv-field)))
+             (insert "\n"))
+           (format "%s <- read.table(\"%s\", header=%s, row.names=%s, sep=\"\\t\", as.is=TRUE)"
+                   name (org-babel-process-file-name transition-file 'noquote)
+                   (if (or (eq (nth 1 value) 'hline) colnames-p) "TRUE" "FALSE")
+                   (if rownames-p "1" "NULL")))
+       (format "%s <- %s"
+               name
+               (concat "c(" (mapconcat 'org-babel-R-quote-tsv-field value ",") ")")))
     (format "%s <- %s" name (org-babel-R-quote-tsv-field value))))
 
 (defvar ess-ask-for-ess-directory nil)

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [babel] creating simple vectors in R
  2010-10-05 20:37 [babel] creating simple vectors in R Dan Davison
@ 2010-10-05 21:35 ` Erik Iverson
  0 siblings, 0 replies; 2+ messages in thread
From: Erik Iverson @ 2010-10-05 21:35 UTC (permalink / raw)
  To: Dan Davison; +Cc: emacs org-mode mailing list

Hello,

Dan Davison wrote:
> I'd appreciate opinions from R users on the following org-babel-R
> details:
> 

I use R daily, with and without org-mode, but have never investigated
these features of passing tables and Lisp lists to source blocks, but
it looks interesting.  More below.

> Currently, Org tables, and lisp lists, are converted into data frames
> when they are sent from Org to R, and we have no way to create simple
> vectors such as c(1,2). I'd like to know whether users of org and R
> would approve of the following change that makes simple R vectors
> possible, or have other suggestions related to these issues.
> 
> With the patch below, there would be two ways to create a simple vector
> in R. The most direct way is to pass a non-nested lisp list:
> 
> #+begin_src R :var x='(1 2) :results output
> str(x)
> #+end_src
> 
> CURRENT OUTPUT:
> #+results:
> : 'data.frame':	1 obs. of  2 variables:
> :  $ V1: int 1
> :  $ V2: int 2
> 
> NEW OUTPUT:
> #+results:
> :  num [1:2] 1 2
> 

What happens with "non-atomic" lists that contain mixed types?
They could either be turned into a vector of the lowest common
type, e.g., '(1 "hi") is turned into a character vector, or this
could be turned into an R list.  Then you'd be going from
Lisp List -> R list data types.

> In addition, because babel's table-indexing code produces a non-nested
> list when taking a one-dimensional slice, this would be another
> situation in which a vector rather than data frame is created:
> 
> #+tblname: input-tab
>     | 1 | 3 |
>     | 2 | 4 |
> 
> #+begin_src R :var x=input-tab[0,] :results output
> str(x)
> #+end_src
> 
> CURRENT OUTPUT:
> #+results:
> : 'data.frame':	1 obs. of  2 variables:
> :  $ V1: int 1
> :  $ V2: int 3
> 
> NEW OUTPUT:
> #+results:
> :  num [1:2] 1 3
> 
> There's a possible argument that that's slightly at odds with R, since,
> in R, a single row slice of a data frame is still a data frame.
> 

Yes, only since data.frames may and almost always do contain
mixed types.  Which goes back to the first question about the
behavior of this code when there are mixed types.  I think for
this case, if you're taking a single row of an org-table,
turning it into a vector is an OK thing to do, and
is something I probably would rarely do.  For columns,
I definitely think it's an OK thing to do, and it's more likely
I'd be passing in a single column of an org-table as opposed
to a single row.

In R, for columns, subsets of data.frames only return data.frames
with certain indexing styles, and even then,
setting drop = TRUE will return a vector.

 > df1 <- data.frame(a = 1:10, b = 2:11)

 > is.vector(df1$a)
[1] TRUE

 > is.vector(df1[["a"]])
[1] TRUE

 > is.vector(df1[, "a"])
[1] FALSE

 > is.vector(df1[, "a", drop = TRUE])
[1] TRUE

> A related issue is translating an Org table into a matrix rather than a
> data frame in R. This can be done explicitly with a call to as.matrix in
> the user's code, but if anyone feels that it would be helpful for babel
> to automate this then do say so.
> 
> Dan
> 
> 
> diff --git a/lisp/ob-R.el b/lisp/ob-R.el
> index c709064..4b49af5 100644
> --- a/lisp/ob-R.el
> +++ b/lisp/ob-R.el
> @@ -141,16 +141,18 @@ This function is called by `org-babel-execute-src-block'."
>  (defun org-babel-R-assign-elisp (name value colnames-p rownames-p)
>    "Construct R code assigning the elisp VALUE to a variable named NAME."
>    (if (listp value)
> -      (let ((transition-file (org-babel-temp-file "R-import-")))
> -        ;; ensure VALUE has an orgtbl structure (depth of at least 2)
> -        (unless (listp (car value)) (setq value (list value)))
> -        (with-temp-file transition-file
> -          (insert (orgtbl-to-tsv value '(:fmt org-babel-R-quote-tsv-field)))
> -          (insert "\n"))
> -        (format "%s <- read.table(\"%s\", header=%s, row.names=%s, sep=\"\\t\", as.is=TRUE)"
> -                name (org-babel-process-file-name transition-file 'noquote)
> -               (if (or (eq (nth 1 value) 'hline) colnames-p) "TRUE" "FALSE")
> -               (if rownames-p "1" "NULL")))
> +      (if (listp (car value))
> +         (let ((transition-file (org-babel-temp-file "R-import-")))
> +           (with-temp-file transition-file
> +             (insert (orgtbl-to-tsv value '(:fmt org-babel-R-quote-tsv-field)))
> +             (insert "\n"))
> +           (format "%s <- read.table(\"%s\", header=%s, row.names=%s, sep=\"\\t\", as.is=TRUE)"
> +                   name (org-babel-process-file-name transition-file 'noquote)
> +                   (if (or (eq (nth 1 value) 'hline) colnames-p) "TRUE" "FALSE")
> +                   (if rownames-p "1" "NULL")))
> +       (format "%s <- %s"
> +               name
> +               (concat "c(" (mapconcat 'org-babel-R-quote-tsv-field value ",") ")")))
>      (format "%s <- %s" name (org-babel-R-quote-tsv-field value))))
>  
>  (defvar ess-ask-for-ess-directory nil)
> 
> _______________________________________________
> Emacs-orgmode mailing list
> Please use `Reply All' to send replies to the list.
> Emacs-orgmode@gnu.org
> http://lists.gnu.org/mailman/listinfo/emacs-orgmode

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2010-10-05 21:35 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-10-05 20:37 [babel] creating simple vectors in R Dan Davison
2010-10-05 21:35 ` Erik Iverson

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).