2014-06-10 134 views
12

等價於R中命名列表的自然Python是字典,但RPy2爲您提供ListVector對象。將RPy2 ListVector轉換爲Python字典

import rpy2.robjects as robjects 

a = robjects.r('list(foo="barbat", fizz=123)') 

此時,a是ListVector對象。

<ListVector - Python:0x108f92a28/R:0x7febcba86ff0> 
[StrVector, FloatVector] 
    foo: <class 'rpy2.robjects.vectors.StrVector'> 
    <StrVector - Python:0x108f92638/R:0x7febce0ae0d8> 
[str] 
    fizz: <class 'rpy2.robjects.vectors.FloatVector'> 
    <FloatVector - Python:0x10ac38fc8/R:0x7febce0ae108> 
[123.000000] 

我想要的是我可以像普通的Python字典一樣對待。我暫時下鍋周圍是這樣的:

def as_dict(vector): 
    """Convert an RPy2 ListVector to a Python dict""" 
    result = {} 
    for i, name in enumerate(vector.names): 
     if isinstance(vector[i], robjects.ListVector): 
      result[name] = as_dict(vector[i]) 
     elif len(vector[i]) == 1: 
      result[name] = vector[i][0] 
     else: 
      result[name] = vector[i] 
    return result 

as_dict(a) 
{'foo': 'barbat', 'fizz': 123.0} 

b = robjects.r('list(foo=list(bar=1, bat=c("one","two")), fizz=c(123,345))') 
as_dict(b) 
{'fizz': <FloatVector - Python:0x108f7e950/R:0x7febcba86b90> 
[123.000000, 345.000000], 
'foo': {'bar': 1.0, 'bat': <StrVector - Python:0x108f7edd0/R:0x7febcba86ea0> 
    [str, str]}} 

所以,問題是...有沒有內置RPy2更好的方法或東西,我應該使用?

回答

15

我想獲得A R載體引入dictionary不必如此涉及,這個怎麼樣:

In [290]: 

dict(zip(a.names, list(a))) 
Out[290]: 
{'fizz': <FloatVector - Python:0x08AD50A8/R:0x10A67DE8> 
[123.000000], 
'foo': <StrVector - Python:0x08AD5030/R:0x10B72458> 
['barbat']} 
In [291]: 

dict(zip(a.names, map(list,list(a)))) 
Out[291]: 
{'fizz': [123.0], 'foo': ['barbat']} 

和當然,如果你不介意使用pandas,它是更容易。其結果將有numpy.array代替list,但是這將是確定在大多數情況下:

In [294]: 

import pandas.rpy.common as com 
com.convert_robj(a) 
Out[294]: 
{'fizz': [123.0], 'foo': array(['barbat'], dtype=object)} 
+1

不錯!字典(zip(...方法不處理嵌套列表(我的第二個例子),但它簡單得多,我喜歡它。 – cbare

+0

是否可以在'DataFrame'做到這一點是安全的那麼? –

+1

這個版本是否有更新? –

2

我有同樣的問題,不同的rpy2載體類型的深度嵌套結構。我找不到在stackoverflow上的任何地方的直接答案,所以這是我的解決方案。 使用CT朱的回答,我想出了下面的代碼,將整個結構遞歸地轉換爲python類型。

from rpy2.robjects.vectors import DataFrame, FloatVector, IntVector, StrVector, ListVector 
import numpy 
from collections import OrderedDict 

def recurList(data): 
    rDictTypes = [ DataFrame,ListVector] 
    rArrayTypes = [FloatVector,IntVector] 
    rListTypes=[StrVector] 
    if type(data) in rDictTypes: 
     return OrderedDict(zip(data.names, [recurList(elt) for elt in data])) 
    elif type(data) in rListTypes: 
     return [recurList(elt) for elt in data] 
    elif type(data) in rArrayTypes: 
     return numpy.array(data) 
    else: 
     if hasattr(data, "rclass"): # An unsupported r class 
      raise KeyError('Could not proceed, type {} is not defined'.format(type(data))) 
     else: 
      return data # We reached the end of recursion 
8

簡易R列表Python字典:

>>> import rpy2.robjects as robjects 
>>> a = robjects.r('list(foo="barbat", fizz=123)') 
>>> d = { key : a.rx2(key)[0] for key in a.names } 
>>> d 
{'foo': 'barbat', 'fizz': 123.0} 

任意ř目的是,使用R RJSONIO JSON序列化/反序列

在R服務器Python對象: 「RJSONIO」 install.packages(, dependencies = TRUE)

>>> ro.r("library(RJSONIO)") 
<StrVector - Python:0x300b8c0/R:0x3fbccb0> 
[str, str, str, ..., str, str, str] 
>>> import rpy2.robjects as robjects 
>>> rjson = robjects.r(' toJSON(list(foo="barbat", fizz=123, lst=list(33,"bb"))) ') 
>>> pyobj = json.loads(rjson[0]) 
>>> pyobj 
{u'lst': [33, u'bb'], u'foo': u'barbat', u'fizz': 123} 
>>> pyobj['lst'] 
[33, u'bb'] 
>>> pyobj['lst'][0] 
33 
>>> pyobj['lst'][1] 
u'bb' 
>>> rjson = robjects.r(' toJSON(list(foo="barbat", fizz=123, lst=list(key1=33,key2="bb"))) ') 
>>> pyobj = json.loads(rjson[0]) 
>>> pyobj 
{u'lst': {u'key2': u'bb', u'key1': 33}, u'foo': u'barbat', u'fizz': 123} 
+0

JSON作爲中介的巧妙使用 – cbare

0

一個簡單的函數將嵌套的R命名列表轉換爲ne STED Python字典:

def rext(r): 
    """ 
    Returns a R named list as a Python dictionary 
    """ 
    # In case `r` is not a named list 
    try: 
     # No more names, just return the value! 
     if r.names == NULL: 
      # If more than one value, return numpy array (or list) 
      if len(list(r)) > 1: 
       return np.array(r) 
      # Just one value, return the value 
      else: 
       return list(r)[0] 
     # Create dictionary to hold named list as key-value 
     dic = {} 
     for n in list(r.names): 
      dic[n] = rext(r[r.names.index(n)]) 
     return dic 
    # Uh-oh `r` is not a named list, just return `r` as is 
    except: 
     return r 
1

隨着大熊貓的新版本,我們也可以做,

import rpy2.robjects as robjects 
a = robjects.r('list(foo="barbat", fizz=123)') 

from rpy2.robjects import pandas2ri 
print(pandas2ri.ri2py(a.names)) 
temp = pandas2ri.ri2py(a) 
print(temp[0]) 
print(temp[1]) 
+0

上面的代碼之後,你怎樣得到'> type(temp)'?我仍然看到temp是一個'rpy2.robjects。 vectors.ListVector' – cbare