13

我想将 pandas 与 numpy 一起用于我的所有分析,但使用 Rpy2 来绘制我的数据。我想使用熊猫数据框进行所有分析,然后通过 rpy2 使用 R 的完整绘图来绘制这些。py2,并且正在使用 ipython 进行绘图。这样做的正确方法是什么?

我尝试的几乎所有命令都失败了。例如:

  • 我正在尝试在 pandas DataFrame 的两列之间绘制散点图df。我希望df在 x/y 轴上使用的标签就像在 R 数据帧中使用的那样。有没有办法做到这一点?当我尝试使用 时r.plot,我得到了这个乱码:

In: r.plot(df.a, df.b) # df is pandas DataFrame

产量:

Out: rpy2.rinterface.NULL

导致情节:

在此处输入图像描述

如您所见,轴标签被弄乱了,它没有像应有的那样从 DataFrame 中读取轴标签(X 轴是 column aof df,Y 轴是 column b)。

  • 如果我尝试用 制作直方图r.hist,它根本不起作用,产生错误:

    In: r.hist(df.a)
    Out: 
    ...
    vectors.pyc in <genexpr>((x,))
        293         if l < 7:
        294             s = '[' + \
    --> 295                 ', '.join((p_str(x, max_width = math.floor(52 / l)) for x in self[ : 8])) +\
        296                 ']'
        297         else:
    
    vectors.pyc in p_str(x, max_width)
        287                     res = x
        288                 else:
    --> 289                     res = "%s..." % (str(x[ : (max_width - 3)]))
        290             return res
        291 
    
    TypeError: slice indices must be integers or None or have an __index__ method
    

并导致了这个情节:

在此处输入图像描述

知道错误是什么意思吗?再次在这里,轴都被弄乱了,到处都是乱七八糟的数据。

编辑:此错误仅在使用 ipython 时发生。当我从脚本运行命令时,它仍然会产生有问题的情节,但至少运行时没有错误。从 ipython 调用这些命令一定有问题。

  • 我还尝试按照df下面海报的建议将 pandas DataFrame 转换为 R DataFrame,但这也因此错误而失败:

    com.convert_to_r_dataframe(mydf) # mydf is a pandas DataFrame
    ----> 1 com.convert_to_r_dataframe(mydf)
    in convert_to_r_dataframe(df, strings_as_factors)
        275     # FIXME: This doesn't handle MultiIndex
        276 
    --> 277     for column in df:
        278         value = df[column]
        279         value_type = value.dtype.type
    
    TypeError: iteration over non-sequence
    

如何让这些基本绘图功能在 Pandas DataFrame 上工作(从 Pandas DataFrame 的标签中读取绘图标签),并让 Pandas DF 到 R DF 之间的转换工作?

EDIT2:这是一个完整的 csv 文件“test.txt”(http://pastebin.ca/2311928)示例和我回答@dale 评论的代码:

import rpy2
from rpy2.robjects import r
import rpy2.robjects.numpy2ri
import pandas.rpy.common as com
from rpy2.robjects.packages import importr
from rpy2.robjects.lib import grid
from rpy2.robjects.lib import ggplot2
rpy2.robjects.numpy2ri.activate()
from numpy import *
import scipy

# load up pandas df
import pandas
data = pandas.read_table("./test.txt")
# plotting a column fails
print "data.c2: ", data.c2
r.plot(data.c2)
# Conversion and then plotting also fails
r_df = com.convert_to_r_dataframe(data)
r.plot(r_df)

绘制“data.c2”列的调用失败,即使 data.c2 是 pandas df 的列,因此出于所有意图和目的应该是一个 numpy 数组。我使用了这个activate()调用,所以我认为它会将此列作为一个 numpy 数组处理并绘制它。

data转换为 R 数据帧后绘制数据帧的第二次调用也失败。这是为什么?如果我test.txt从 R 作为数据框加载,我可以这样plot()做,并且由于我的数据框已从 pandas 转换为 R,它似乎也应该在这里工作。

当我rmagic在 ipython 中尝试时,由于某种原因它不会启动绘图窗口,尽管它不会出错。即如果我这样做:

In [12]: X = np.array([0,1,2,3,4])

In [13]: Y = np.array([3,5,4,6,7])
In [14]: import rpy2

In [15]: from rpy2.robjects import r

In [16]: import rpy2.robjects.numpy2ri

In [17]: import pandas.rpy.common as com

In [18]: from rpy2.robjects.packages import importr

In [19]: from rpy2.robjects.lib import grid

In [20]: from rpy2.robjects.lib import ggplot2


In [21]: rpy2.robjects.numpy2ri.activate()

In [22]: from numpy import *

In [23]: import scipy

In [24]: r.assign("x", X)
Out[24]: 
<Array - Python:0x592ad88 / R:0x6110850>
[       0,        1,        2,        3,        4]

In [25]: r.assign("y", Y)
<Array - Python:0x592f5f0 / R:0x61109b8>
[       3,        5,        4,        6,        7]

In [27]: %R plot(x,y)

没有错误,但也没有绘图窗口。无论如何,我想坚持使用 rpy2 并且rmagic尽可能不依赖。

谢谢。

4

3 回答 3

7

[注意:您在“编辑 2”中的代码在这里工作(Python 2.7、rpy2-2.3.2、R-1.15.2)。]

正如@dale 提到的那样,只要 R 对象是匿名的(即对象不存在 R 符号),Rdeparse(substitute())最终将返回structure()R 对象的,一个可能的解决方法是指定“xlab”和“ylab”参数;对于某些情节,您还必须指定main(标题)。

解决这个问题的另一种方法是使用 R 的公式并提供数据框(在我们计算出转换部分之后更多内容如下)。

忘记里面有什么pandas.rpy。它既损坏又似乎忽略了 rpy2 中可用的功能。

使用 ipython 进行转换的早期快速修复可以很容易地转换为正确的转换。我正在考虑在 rpy2 代码库中添加一个(带有更多的花里胡哨),但与此同时,只需在代码示例中的所有导入之后添加以下代码片段。每当进行 R 调用时,它将透明地将 pandas 的DataFrame对象转换为 rpy2 的对象。DataFrame

from collections import OrderedDict
py2ri_orig = rpy2.robjects.conversion.py2ri
def conversion_pydataframe(obj):
    if isinstance(obj, pandas.core.frame.DataFrame):
        od = OrderedDict()
        for name, values in obj.iteritems():
            if values.dtype.kind == 'O':
                od[name] = rpy2.robjects.vectors.StrVector(values)
            else:
                od[name] = rpy2.robjects.conversion.py2ri(values)
        return rpy2.robjects.vectors.DataFrame(od)
    elif isinstance(obj, pandas.core.series.Series):
        # converted as a numpy array
        res = py2ri_orig(obj) 
        # "index" is equivalent to "names" in R
        if obj.ndim == 1:
            res.names = ListVector({'x': ro.conversion.py2ri(obj.index)})
        else:
            res.dimnames = ListVector(ro.conversion.py2ri(obj.index))
        return res
    else:
        return py2ri_orig(obj) 
rpy2.robjects.conversion.py2ri = conversion_pydataframe

现在以下代码将“正常工作”:

r.plot(rpy2.robjects.Formula('c3~c2'), data)
# `data` was converted to an rpy2 data.frame on the fly
# and the a scatter plot c3 vs c2 (with "c2" and "c3" the labels on
# the "x" axis and "y" axis).

我还注意到您正在导入ggplot2,而不使用它。目前,必须明确请求转换。例如:

p = ggplot2.ggplot(rpy2.robjects.conversion.py2ri(data)) +\
    ggplot2.geom_histogram(ggplot2.aes_string(x = 'c3'))
p.plot()
于 2013-02-09T15:17:40.383 回答
6

调用 r.plot 函数时,您需要显式传入标签。

r.plot([1,2,3],[1,2,3], xlab="X", ylab="Y")

当您在 R 中绘图时,它会抓取标签,通过deparse(substitute(x))该标签实际上从plot(testX, testY). 当您通过 rpy2 传入 python 对象时,它是一个匿名 R 对象,类似于 R 中的以下内容:

> deparse(substitute(c(1,2,3)))
[1] "c(1, 2, 3)"

这就是为什么你会得到疯狂的标签。

很多时候,使用 rpy2来回推送数据更明智。

r.assign('testX', df.A)
r.assign('testY', df.B)
%R plot(testX, testY)

rdf = com.convert_to_r_dataframe(df)
r.assign('bob', rdf)
%R plot(bob$$A, bob$$B)

http://nbviewer.ipython.org/4734581/

于 2013-02-07T22:55:16.463 回答
5

使用 rpy。转换是熊猫的一部分,所以你不需要自己做 http://pandas.pydata.org/pandas-docs/dev/r_interface.html

In [1217]: from pandas import DataFrame

In [1218]: df = DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6], 'C':[7,8,9]},
   ......:                index=["one", "two", "three"])
   ......:

In [1219]: r_dataframe = com.convert_to_r_dataframe(df)

In [1220]: print type(r_dataframe)
<class 'rpy2.robjects.vectors.DataFrame'>
于 2013-02-02T01:23:46.413 回答