Python Pandas convert_to_r_数据帧函数KeyError

Python Pandas convert_to_r_数据帧函数KeyError,python,numpy,pandas,rpy2,Python,Numpy,Pandas,Rpy2,我创建一个数据帧: import pandas as pd df = pd.DataFrame(x.toarray(), columns = colnames) 然后我将其转换为R数据帧: import pandas.rpy.common as com rdf = com.convert_to_r_dataframe(df) 在具有此配置的Windows下,没有问题: >>> pd.show_versions() INSTALLED VERSIONS --------

我创建一个数据帧:

import pandas as pd

df = pd.DataFrame(x.toarray(), columns = colnames)
然后我将其转换为R数据帧:

import pandas.rpy.common as com

rdf = com.convert_to_r_dataframe(df)
在具有此配置的Windows下,没有问题:

>>> pd.show_versions()

INSTALLED VERSIONS
------------------
commit: None
python: 2.7.7.final.0
python-bits: 32
OS: Windows
OS-release: 7
machine: AMD64
processor: AMD64 Family 16 Model 4
byteorder: little
LC_ALL: None
LANG: None

pandas: 0.14.1
numpy: 1.8.2
rpy2: 2.4.4
...
但当我在Linux上以这种配置执行它时:

>>> pd.show_versions()

INSTALLED VERSIONS
------------------
commit: None
python: 2.7.3.final.0
python-bits: 64
OS: Linux
OS-release: 3.2.0-29-generic
machine: x86_64
processor: x86_64
byteorder: little
LC_ALL: None
LANG: en_US.UTF-8

pandas: 0.14.1
numpy: 1.8.2
rpy2: 2.4.4
...
我明白了:

Traceback (most recent call last):
  File "app.py", line 232, in <module>
    clf.global_cl(df, df2)
  File "/home/uzer/app/util/clftool.py", line 202, in global_cl
    rdf = com.convert_to_r_dataframe(df)
  File "/home/uzer/app/venv/local/lib/python2.7/site-packages/pandas/rpy/common.py", line 324, in convert_to_r_dataframe
    value = VECTOR_TYPES[value_type](value)
KeyError: <type 'numpy.int64'>
因此,我在
convert_to_r_dataframe
(在
。/pandas/rpy/common.py
)中打印了变量类型:

这就是结果:

value_type: <type 'numpy.int64'>
Is value_type == np.int64: False
致:

这起作用了

注意:我的数据帧包含utf-8特殊字符,作为列名,用unicode解码。调用
DataFrame
构造函数(包含在
rpy2/robjects/vectors.py
中)时,此行尝试将unicode字符串(包含特殊字符)编码为ascii字符串:

kv = [(str(k), conversion.py2ri(obj[k])) for k in obj]
这将生成一个错误:

UnicodeEncodeError: 'ascii' codec can't encode character u'\xe0' in position 4: ordinal not in range(128)
为了解决这一问题,我必须将这一行改为:

kv = [(k.encode('UTF-8'), conversion.py2ri(obj[k])) for k in obj]

Rpy2应该引入一种允许更改编码的方法。

考虑使用Rpy2自己的转换(它似乎在Linux上使用
int64
):

现在,数据帧对象将自动转换 在每次调用中使用嵌入的R调用rpy2/R数据帧对象。 例如:

from rpy2.robjects.packages import importr
# R's "base" package
base = importr('base')
# call the R function "summary"
print(base.summary(dataf))
还可以显式调用转换:

from rpy2.robjects import conversion
rpy2_dataf = conversion.py2ro(dataf)
编辑:(添加了自定义以解决
str(k)
问题)

如果与转换相关的任何内容需要本地定制,则可以相对容易地实现。单程 要更改R
数据帧的构建方式,请执行以下操作:

import pandas.DataFrame as PandasDataFrame
import rpy2.robjects.vectors.DataFrame as RDataFrame
from rpy2 import rinterface
@conversion.py2ro.register(PandasDataFrame)
def py2ro_pandasdataframe(obj):
    ri_dataf = conversion.py2ri(obj)
    # cast down to an R list (goes through a different code path
    # in the DataFrame constructor, avoiding `str(k)`) 
    ri_list = rinterface.SexpVector(ri_dataf)
    return RDataFrame(ri_list)
从现在起,当发生故障时,将使用上述转换功能
数据帧
存在:

rpy2_dataf = conversion.py2ro(dataf)

我需要显式调用转换,因此我尝试:
conversion.py2ro(df)
或交替调用
pandas2ri.pandas2ri(df)
,但结果是:
unicodeincoder错误:“ascii”编解码器无法对位置4处的字符u'\xe0'进行编码:序号不在范围内(128)
。这可能是因为列/行名称需要以“UTF-8”而不是“ascii”编码。有一种方法可以强制UTF-8编码?@MrMoog-如果没有完整的示例,很难重现。最近有一份报告显示Windows特有的编码问题()。看看这是否是一个相关的问题会很有趣。我忘了rpy2有一个缺陷。在
DataFrame
构造函数中(在
rpy2/robjects/vectors.py
中),字符串自动转换为ascii。在我的数据帧中,有一些unicode字符串,其列名是特殊字符(源自UTF-8编码)。我必须将obj中k的
kv=[(str(k),conversion.py2ri(obj[k])更改为
kv=[(k.encode('UTF-8'),conversion.py2ri(obj[k])。
字符串不能转换为ASCII。如您引用的代码所示,使用Python运行中定义的字符串表示法(method
str
)。在Python中,字符串2恰好是字节。也许有一种方法可以制作一个特定于Python 2的补丁,但我更倾向于建议更改默认编码(请参阅),或者转到Python 3。仔细查看代码后,
str(k)
的使用也不完全一致。快速修复方法是将其作为参数添加到
DataFrame
构造函数中,但这并不能完全解决问题。可能这正是Python3中字符串处理的巨大变化所要解决的问题。
# create a test DataFrame
import numpy
import pandas

i2d = numpy.array([[1, 2, 3], [4, 5, 6]], dtype="int64")
colnames = ('a', 'b', 'c')
dataf = pandas.DataFrame(i2d, 
                         columns = colnames)

# rpy2's conversion of pandas objects
from rpy2.robjects import pandas2ri
pandas2ri.activate()
from rpy2.robjects.packages import importr
# R's "base" package
base = importr('base')
# call the R function "summary"
print(base.summary(dataf))
from rpy2.robjects import conversion
rpy2_dataf = conversion.py2ro(dataf)
import pandas.DataFrame as PandasDataFrame
import rpy2.robjects.vectors.DataFrame as RDataFrame
from rpy2 import rinterface
@conversion.py2ro.register(PandasDataFrame)
def py2ro_pandasdataframe(obj):
    ri_dataf = conversion.py2ri(obj)
    # cast down to an R list (goes through a different code path
    # in the DataFrame constructor, avoiding `str(k)`) 
    ri_list = rinterface.SexpVector(ri_dataf)
    return RDataFrame(ri_list)
rpy2_dataf = conversion.py2ro(dataf)