Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I am trying to extract the data table itself from an RLink-generated RDataFrame:

Needs["RLink`"];
InstallR[];
REvaluate["require(datasets);"];
REvaluate["data(airquality);"]
airquality = REvaluate["as.data.frame(airquality)"]

RDataFrame Output

but now I would like to extract out the goodies like RNames and RData so that I may work with them independently. (BTW, TableForm on an RDataFrame is awesome!)

I tried messing around with its InputForm, but I got stuck. How do I extract RNames, RData, etc. into standard Mathematica lists?

share|improve this question

1 Answer 1

up vote 9 down vote accepted

Short answer

From the documentation - example

df=REvaluate["
   {
      age <- 18:23
      height <- c(76.1,77,78.1,78.2,78.8,79.7)
      name <- c(\"John Young\",\"Jane Ty\",\"john Ed\",\"Mary Ann\",\"Thomas Ed\",\"John Wood\")
      village <- data.frame(age=age,height=height,name=name)
      as.data.frame(village)
   }
"]

(*
    RDataFrame[RNames[age,height,name],RData[{18,19,20,21,22,23}, 
         {76.1,77.,78.1,78.2,78.8,79.7},RFactor[{4,1,2,5,6,3},
         RFactorLevels[Jane Ty,john Ed,John Wood,John Young,Mary Ann,Thomas Ed]]],
         RRowNames[1,2,3,4,5,6]
    ] 
*)

Now,

RGetData[df]

(*
   {{18,19,20,21,22,23}, 76.1,77.,78.1,78.2,78.8,79.7},
   RFactor[{4,1,2,5,6,3},RFactorLevels[Jane Ty,john Ed,John Wood,John Young,
      Mary Ann,Thomas Ed]]}
*)

This extracts the names.

RGetNames[df]

(*  {age,height,name}   *)

This extracts the row names.

RGetRowNames[df]

(*  {1,2,3,4,5,6} *)

Long answer

RDataFrame (as well as RFactor) are two data types implemented via RLink type extension mechanism. In this sense, there is no difference between them being implemented by the RLink developer, or the user. The relevant tutorial is R Data types in RLink, the second large section on type extension mechanism. It contains a detailed walk-through for the procedure of defining new types.

The support for data frames and factors currently is very basic. Basically, apart from a few simple data transformations and display functions, such as TableForm, not much is in there. In time, this support will probably become better, but you don't have to wait until then - you can implement your own extensions or extend those implementations. The full source code for RDataFrame and RFactor implementation is available at

FileNameJoin[{$InstallationDirectory,"SystemFiles","Links","RLink","Kernel","DataTypes","Base.m"}]

To answer your specific question, the relevant part of this implementation for a data frame looks like

RDataFrame /: RGetNames[ RDataFrame[RNames[names___],__]] := {names};

RDataFrame /: RGetAttributes[ RDataFrame[__,a : (_RAttributes | None) : None]]:=
   RGetAllAttributes[a];


RDataFrame /: 
  RGetRowNames[
     RDataFrame[
         _,
         RData[data__],
         rnames : (RRowNames[rn__] | Automatic) : Automatic,
         a : (RAttributes[__] | None) : None
     ]]:=
   If[rnames === Automatic, Range[Length[{data}]],{rn}];

RDataFrame /: RGetData[RDataFrame[_, RData[data__],___]]:= {data};

which both tells you how to extract the data parts (which heads are responsible for this), and how this has been implemented. That's all there is to it currently. The data extractors like RGetNames, RGetAttributes, RGetData, RGetRowNames are universal heads which are overloaded by various data types, and currently placed at

FileNameJoin[{$InstallationDirectory,"SystemFiles","Links","RLink","Kernel","DataTypes","Common.m"}]

The overloading for specific data types is done via UpValues, which is the recommended way to do this for user-defined types. This way such implementations will be independent for 2 different users.

How these data extractor heads work for data frames is illustrated in the mentioned tutorial. If you want to extend the current functionality, you have two choices: either create a package that would extend the current functionality, or unregister current implementations of RDataFrame etc via RDataTypeUnregister function and create a package with your own implementations, which would replace the existing ones and which you can inform Rlink about via the "AddToRDataTypePath" option (which is accepted by both InstallR and RDataTypeDefinitionsReload - the latter being a specific tool to enable to to pick up new definitions from files without quitting the RLink session).

It has been discussed in chat already that it would be nice to have a way to share such new data type implementations between RLink users. All I can say at the moment is that work is underway to enable that.

share|improve this answer
    
...and with this answer, I just kicked my Emacs/StarterKit/org-mode/ESS/pgfSweave/ggplot2 "Frankenstein monster" to the curb. –  Eric Brown Dec 1 '12 at 2:29
    
@EricBrown Thanks for the accept:). I updated it with explicit example taken from the docs. –  Leonid Shifrin Dec 1 '12 at 2:30

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.