rpy2 allows me to use some but not all of the returned values from a function (dea()) in library(Benchmarking) from R in Python because some of them return RTYPES.NILSXP instead of an ndarray or int. How do I get these data out from RTYPES.NILSXP object?
Set-up:
#imports
import pandas as pd
import rpy2
import rpy2.robjects as robjects
import rpy2.robjects.packages as rpackages
from rpy2.robjects.vectors import StrVector
from rpy2.robjects.packages import importr
utils = rpackages.importr('utils')
utils.chooseCRANmirror(ind=1)
#helps work with pd.DataFrame objects
from rpy2.robjects import pandas2ri
from rpy2.robjects.conversion import localconverter
#import the R library into Python
packnames = ('Benchmarking')
utils.install_packages(StrVector(packnames))
Benchmarking = importr('Benchmarking')
base = importr('base')
data = pd.read_csv("path/to_data.csv")
#call the function I want and store it in a variable
with localconverter(robjects.default_converter + pandas2ri.converter):
crs = Benchmarking.dea(data['Age'], data['CO2'], RTS='crs', ORIENTATION='in')
crs['eff'] or crs['lambda'] work fine and return ndarrays
crs
____________________________________________________________________
o{'eff': [1. 0.625 0.5 ], 'lambda': [[1. 0. 0. ]
[1.25 0. 0. ]
[1.5 0. 0. ]], 'objval': [1. 0.625 0.5 ], 'RTS': [1] "crs"
, 'primal': <rpy2.rinterface_lib.sexp.NULLType object at 0x00000220BCB0D1C0> [RTYPES.NILSXP], 'dual': <rpy2.rinterface_lib.sexp.NULLType object at 0x00000220BCB0D1C0> [RTYPES.NILSXP], 'ux': <rpy2.rinterface_lib.sexp.NULLType object at 0x00000220BCB0D1C0> [RTYPES.NILSXP], 'vy': <rpy2.rinterface_lib.sexp.NULLType object at 0x00000220BCB0D1C0> [RTYPES.NILSXP], 'gamma': function (x) .Primitive("gamma")
, 'ORIENTATION': [1] "in"
, 'TRANSPOSE': [1] FALSE
, 'param': <rpy2.rinterface_lib.sexp.NULLType object at 0x00000220BCB0D1C0> [RTYPES.NILSXP], }
So far so good.
However there is more useful data that I would like to extract eg.
crs['dual']
_______________________________________________________________
<rpy2.rinterface_lib.sexp.NULLType object at 0x00000220BCB0D1C0> [RTYPES.NILSXP]
What kind of object is this? <>
Searching up RTYPES.NILSXP in the 3.5.3 docs takes me to a page in the docs which is the only mention I have found.
I have no idea how to read this. The docs explains that datasets can be serialised R objects or serialised R code that produces the dataset. rpy2 employs 'lazy loading' and to load the data, one must use the method fetch() but I don't seem to be able to use it correctly to load the rest of the outputs from dea(x, y, *args)
Failed attempts to load data
rpy2.robjects.packages.PackageData.fetch(crs['dual'])
_______________________________________________________________
TypeError: PackageData.fetch() missing 1 required positional argument: 'name'
I've found fetch() method belongs to PackageData. I've tried to call it but now it asks me for the 'name' of this dataset?? I thought crs['dual'] was enough information. When I pass in 'dual' as the name parameter I get
rpy2.robjects.packages.PackageData.fetch(r_from_df_crs['dual'], 'dual')
File ~\anaconda3\envs\UROP_buildings_env\lib\site-packages\rpy2\robjects\packages.py:143, in PackageData.fetch(self, name)
136 def fetch(self, name):
137 """ Fetch the dataset (loads it or evaluates the R associated
138 with it.
139
140 In R, datasets are loaded into the global environment by default
141 but this function returns an environment that contains the dataset(s).
142 """
--> 143 if self._datasets is None:
144 self._init_setlist()
146 if name not in self._datasets:
AttributeError: 'NULLType' object has no attribute '_datasets
so I am stuck. How can I deserialise this <RTYPES.NILSXP> object from memory?
Edit:
So taking into account @igautier's answer, I've used the rpackages.data() method to instantiate the PacketData class and enable access to .fetch()
my_crs = rpackages.data(crs)
_________________________________
AttributeError Traceback (most recent call last)
Input In [7], in <cell line: 1>()
----> 1 my_crs = rpackages.data(crs)
File ~\anaconda3\envs\UROP_buildings_env\lib\site-packages\rpy2\robjects\packages.py:522, in data(package)
520 def data(package):
521 """ Return the PackageData for the given package."""
--> 522 return package.__rdata__
AttributeError: 'OrdDict' object has no attribute '__rdata__'
How can I now convert my 'OrdDict' into PacketData?
In a nutshell, the solution was that I had omitted the SLACK=True and DUAL=True arguments in the dea() function and hence the dual and slack results were given as null