Rpy2 和 Pandas:将预测的输出连接到 pandas 数据帧
Rpy2 and Pandas: join output from predict to pandas dataframe
我正在通过 RPy2
在 R 中使用 randomForest
库。我想传回使用 caret
predict
方法计算的值,并将它们连接到原始的 pandas
数据框。请参阅下面的示例。
import pandas as pd
import numpy as np
import rpy2.robjects as robjects
from rpy2.robjects import pandas2ri
pandas2ri.activate()
r = robjects.r
r.library("randomForest")
r.library("caret")
df = pd.DataFrame(data=np.random.rand(100, 10), columns=["a{}".format(i) for i in range(10)])
df["b"] = ['a' if x < 0.5 else 'b' for x in np.random.sample(size=100)]
train = df.ix[df.a0 < .75]
withheld = df.ix[df.a0 >= .75]
rf = r.randomForest(robjects.Formula('b ~ .'), data=train)
pr = r.predict(rf, withheld)
print pr.rx()
哪个returns
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
a a b b b a a a a b a a a a a b a a a a
Levels: a b
但是 join
如何将其添加到 withheld
数据框或与原始值进行比较?
我试过这个:
import pandas.rpy.common as com
com.convert_robj(pr)
但是这个 returns 一个字典,其中的键是字符串。我想有一个 withheld.reset_index()
的解决方法,然后将 dict 键转换为整数,然后将两者连接起来,但必须有更简单的方法!
有a pull-request that adds R factor to Pandas Categorical functionality
到 Pandas。它还没有被合并到 Pandas master 分支。什么时候,
import pandas.rpy.common as rcom
rcom.convert_robj(pr)
会将 pr
转换为 Pandas 分类。
在此之前,您可以使用以下解决方法:
def convert_factor(obj):
"""
Taken from jseabold's PR: https://github.com/pydata/pandas/pull/9187
"""
ordered = r["is.ordered"](obj)[0]
categories = list(obj.levels)
codes = np.asarray(obj) - 1 # zero-based indexing
values = pd.Categorical.from_codes(codes, categories=categories,
ordered=ordered)
return values
例如,
import pandas as pd
import numpy as np
import rpy2.robjects as robjects
from rpy2.robjects import pandas2ri
pandas2ri.activate()
r = robjects.r
r.library("randomForest")
r.library("caret")
def convert_factor(obj):
"""
Taken from jseabold's PR: https://github.com/pydata/pandas/pull/9187
"""
ordered = r["is.ordered"](obj)[0]
categories = list(obj.levels)
codes = np.asarray(obj) - 1 # zero-based indexing
values = pd.Categorical.from_codes(codes, categories=categories,
ordered=ordered)
return values
df = pd.DataFrame(data=np.random.rand(100, 10),
columns=["a{}".format(i) for i in range(10)])
df["b"] = ['a' if x < 0.5 else 'b' for x in np.random.sample(size=100)]
train = df.ix[df.a0 < .75]
withheld = df.ix[df.a0 >= .75]
rf = r.randomForest(robjects.Formula('b ~ .'), data=train)
pr = convert_factor(r.predict(rf, withheld))
withheld['pr'] = pr
print(withheld)
函数predict
返回的R对象pr
是一个"vector",你可以认为是Pythonarray.array
,或者numpy一维数组。
"Joining" 不是必需的,因为 pr
中元素的排序对应于 table withheld
中的行。只需要将 pr
作为附加列添加到 withheld
(参见 Adding new column to existing DataFrame in Python pandas):
withheld['predictions'] = pd.Series(pr,
index=withheld.index)
默认情况下,这将添加一列整数(因为 R 因子被编码为整数)。可以相当简单地自定义 rpy2 的转换
(参见 http://rpy.sourceforge.net/rpy2/doc-2.5/html/robjects_convert.html):
注意: rpy2 的 2.6.0 版本将包括对 pandas Categorical
向量的处理,使得下面描述的转换器的定制变得不必要.
@robjects.conversion.ri2py.register(robjects.rinterface.SexpVector)
def ri2py_vector(vector):
# based on
# https://bitbucket.org/rpy2/rpy2/src/a75413b09852991869332da615fa754923c32039/rpy/robjects/pandas2ri.py?at=default#cl-73
# special case for factors
if 'factor' in vector.rclass:
res = pd.Categorical.from_codes(np.asarray(vector) - 1,
categories = vector.do_slot('levels'),
ordered = 'ordered' in vector.rclass)
else:
# use the numpy converter first
res = numpy2ri.ri2py(obj)
if isinstance(res, recarray):
res = PandasDataFrame.from_records(res)
return res
这样,只要存在 R 因子,任何 rpy2 对象到非 rpy2 对象的转换都将返回 pandas Categorical
:
robjects.conversion.ri2py(pr)
您可以决定将最后一次转换的结果添加到您的数据中 table。
请注意,到非 rpy2 对象的转换必须是显式的(一个是调用转换器)。如果您使用的是 ipython,则有一种方法可以使其隐含:
https://gist.github.com/lgautier/e2e8709776e0e0e93b8d
(和原始线程 https://bitbucket.org/rpy2/rpy2/issue/230/rmagic-specific-conversion)。
我正在通过 RPy2
在 R 中使用 randomForest
库。我想传回使用 caret
predict
方法计算的值,并将它们连接到原始的 pandas
数据框。请参阅下面的示例。
import pandas as pd
import numpy as np
import rpy2.robjects as robjects
from rpy2.robjects import pandas2ri
pandas2ri.activate()
r = robjects.r
r.library("randomForest")
r.library("caret")
df = pd.DataFrame(data=np.random.rand(100, 10), columns=["a{}".format(i) for i in range(10)])
df["b"] = ['a' if x < 0.5 else 'b' for x in np.random.sample(size=100)]
train = df.ix[df.a0 < .75]
withheld = df.ix[df.a0 >= .75]
rf = r.randomForest(robjects.Formula('b ~ .'), data=train)
pr = r.predict(rf, withheld)
print pr.rx()
哪个returns
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
a a b b b a a a a b a a a a a b a a a a
Levels: a b
但是 join
如何将其添加到 withheld
数据框或与原始值进行比较?
我试过这个:
import pandas.rpy.common as com
com.convert_robj(pr)
但是这个 returns 一个字典,其中的键是字符串。我想有一个 withheld.reset_index()
的解决方法,然后将 dict 键转换为整数,然后将两者连接起来,但必须有更简单的方法!
有a pull-request that adds R factor to Pandas Categorical functionality 到 Pandas。它还没有被合并到 Pandas master 分支。什么时候,
import pandas.rpy.common as rcom
rcom.convert_robj(pr)
会将 pr
转换为 Pandas 分类。
在此之前,您可以使用以下解决方法:
def convert_factor(obj):
"""
Taken from jseabold's PR: https://github.com/pydata/pandas/pull/9187
"""
ordered = r["is.ordered"](obj)[0]
categories = list(obj.levels)
codes = np.asarray(obj) - 1 # zero-based indexing
values = pd.Categorical.from_codes(codes, categories=categories,
ordered=ordered)
return values
例如,
import pandas as pd
import numpy as np
import rpy2.robjects as robjects
from rpy2.robjects import pandas2ri
pandas2ri.activate()
r = robjects.r
r.library("randomForest")
r.library("caret")
def convert_factor(obj):
"""
Taken from jseabold's PR: https://github.com/pydata/pandas/pull/9187
"""
ordered = r["is.ordered"](obj)[0]
categories = list(obj.levels)
codes = np.asarray(obj) - 1 # zero-based indexing
values = pd.Categorical.from_codes(codes, categories=categories,
ordered=ordered)
return values
df = pd.DataFrame(data=np.random.rand(100, 10),
columns=["a{}".format(i) for i in range(10)])
df["b"] = ['a' if x < 0.5 else 'b' for x in np.random.sample(size=100)]
train = df.ix[df.a0 < .75]
withheld = df.ix[df.a0 >= .75]
rf = r.randomForest(robjects.Formula('b ~ .'), data=train)
pr = convert_factor(r.predict(rf, withheld))
withheld['pr'] = pr
print(withheld)
函数predict
返回的R对象pr
是一个"vector",你可以认为是Pythonarray.array
,或者numpy一维数组。
"Joining" 不是必需的,因为 pr
中元素的排序对应于 table withheld
中的行。只需要将 pr
作为附加列添加到 withheld
(参见 Adding new column to existing DataFrame in Python pandas):
withheld['predictions'] = pd.Series(pr,
index=withheld.index)
默认情况下,这将添加一列整数(因为 R 因子被编码为整数)。可以相当简单地自定义 rpy2 的转换 (参见 http://rpy.sourceforge.net/rpy2/doc-2.5/html/robjects_convert.html):
注意: rpy2 的 2.6.0 版本将包括对 pandas Categorical
向量的处理,使得下面描述的转换器的定制变得不必要.
@robjects.conversion.ri2py.register(robjects.rinterface.SexpVector)
def ri2py_vector(vector):
# based on
# https://bitbucket.org/rpy2/rpy2/src/a75413b09852991869332da615fa754923c32039/rpy/robjects/pandas2ri.py?at=default#cl-73
# special case for factors
if 'factor' in vector.rclass:
res = pd.Categorical.from_codes(np.asarray(vector) - 1,
categories = vector.do_slot('levels'),
ordered = 'ordered' in vector.rclass)
else:
# use the numpy converter first
res = numpy2ri.ri2py(obj)
if isinstance(res, recarray):
res = PandasDataFrame.from_records(res)
return res
这样,只要存在 R 因子,任何 rpy2 对象到非 rpy2 对象的转换都将返回 pandas Categorical
:
robjects.conversion.ri2py(pr)
您可以决定将最后一次转换的结果添加到您的数据中 table。
请注意,到非 rpy2 对象的转换必须是显式的(一个是调用转换器)。如果您使用的是 ipython,则有一种方法可以使其隐含: https://gist.github.com/lgautier/e2e8709776e0e0e93b8d (和原始线程 https://bitbucket.org/rpy2/rpy2/issue/230/rmagic-specific-conversion)。