Adding support for column names (header line) when using R.

Unlike the other languages, it's central to R to be able to index
columns of a data frame d, either by d[,"columnname"] of d$columnname.

With this change, if colnames are present in the *input* from
org-babel, the corresponding R variable is *always* constructed with
the colnames.

In addition, with the :colnames header arg, the *output* to elisp/org
buffer contains the colnames separated from the rest of the table by
'hline. This behaviour is not default because other languages may
expect a simple table without the 'hline.
This commit is contained in:
Dan Davison 2009-07-19 01:07:07 -04:00
parent 2aa721a7dc
commit 062bc09d84
2 changed files with 22 additions and 19 deletions

View File

@ -45,8 +45,9 @@ called by `org-babel-execute-src-block' via multiple-value-bind."
(lambda (pair)
(org-babel-R-assign-elisp (car pair) (cdr pair)))
vars "\n") "\n" body "\n"))
(session (org-babel-R-initiate-session session)))
(org-babel-R-evaluate session full-body result-type))))
(session (org-babel-R-initiate-session session))
(colnames (cdr (assoc :colnames params))))
(org-babel-R-evaluate session full-body result-type colnames))))
(defun org-babel-prep-session:R (session params)
"Prepare SESSION according to the header arguments specified in PARAMS."
@ -71,8 +72,8 @@ called by `org-babel-execute-src-block' via multiple-value-bind."
(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=FALSE, sep=\"\\t\", as.is=TRUE)"
name transition-file))
(format "%s <- read.table(\"%s\", header=%s, sep=\"\\t\", as.is=TRUE)"
name transition-file (if (eq (second value) 'hline) "TRUE" "FALSE")))
(format "%s <- %s" name (org-babel-R-quote-tsv-field value))))
(defun org-babel-R-initiate-session (session)
@ -89,9 +90,9 @@ called by `org-babel-execute-src-block' via multiple-value-bind."
(defvar org-babel-R-eoe-indicator "'org_babel_R_eoe'")
(defvar org-babel-R-eoe-output "[1] \"org_babel_R_eoe\"")
(defvar org-babel-R-wrapper-method "main <- function ()\n{\n%s\n}
write.table(main(), file=\"%s\", sep=\"\\t\", na=\"nil\",row.names=FALSE, col.names=FALSE, quote=FALSE)")
write.table(main(), file=\"%s\", sep=\"\\t\", na=\"nil\",row.names=FALSE, col.names=%s, quote=FALSE)")
(defun org-babel-R-evaluate (buffer body result-type)
(defun org-babel-R-evaluate (buffer body result-type colnames)
"Pass BODY to the R process in BUFFER. If RESULT-TYPE equals
'output then return a list of the outputs of the statements in
BODY, if RESULT-TYPE equals 'value then return the value of the
@ -108,15 +109,15 @@ last statement in BODY, as elisp."
(with-temp-buffer (insert-file-contents out-tmp-file) (buffer-string)))
(value
(with-temp-file in-tmp-file
(insert (format org-babel-R-wrapper-method body out-tmp-file)))
(insert (format org-babel-R-wrapper-method
body out-tmp-file (if colnames "TRUE" "FALSE"))))
(shell-command (format "R --no-save < '%s'" in-tmp-file))
(org-babel-import-elisp-from-file out-tmp-file))))
(org-babel-import-elisp-from-file out-tmp-file colnames))))
;; comint session evaluation
(org-babel-comint-in-buffer buffer
(let* ((tmp-file (make-temp-file "org-babel-R"))
(last-value-eval
(format "write.table(.Last.value, file=\"%s\", sep=\"\\t\", na=\"nil\",row.names=FALSE, col.names=FALSE, quote=FALSE)"
tmp-file))
(format "write.table(.Last.value, file=\"%s\", sep=\"\\t\", na=\"nil\",row.names=FALSE, col.names=%s, quote=FALSE)" tmp-file (if colnames "TRUE" "FALSE")))
(full-body (mapconcat #'org-babel-chomp
(list body last-value-eval org-babel-R-eoe-indicator) "\n"))
(raw (org-babel-comint-with-output buffer org-babel-R-eoe-output nil
@ -138,7 +139,7 @@ last statement in BODY, as elisp."
(mapcar #'org-babel-trim raw))))))
(case result-type
(output (org-babel-trim (mapconcat #'identity results "\n")))
(value (org-babel-import-elisp-from-file tmp-file)))))))
(value (org-babel-import-elisp-from-file tmp-file colnames)))))))
(provide 'org-babel-R)

View File

@ -566,7 +566,7 @@ This is taken almost directly from `org-read-prop'."
(if (string-match "^[[:digit:]]*\\.?[[:digit:]]*$" string)
(string-to-number string)))
(defun org-babel-import-elisp-from-file (file-name)
(defun org-babel-import-elisp-from-file (file-name &optional colnames)
"Read the results located at FILE-NAME into an elisp table. If
the table is trivial, then return it as a scalar."
(let (result)
@ -578,14 +578,16 @@ the table is trivial, then return it as a scalar."
(setq result (mapcar (lambda (row)
(mapcar #'org-babel-string-read row))
(org-table-to-lisp))))
(error nil))
(error nil)))
(if colnames
(setq result (cons (car result) (cons 'hline (cdr result))))
(if (null (cdr result)) ;; if result is trivial vector, then scalarize it
(if (consp (car result))
(if (null (cdr (car result)))
(caar result)
result)
(car result))
result))))
(if (consp (car result))
(if (null (cdr (car result)))
(caar result)
result)
(car result))
result))))
(defun org-babel-string-read (cell)
"Strip nested \"s from around strings in exported R values."