Python调用R(rpy2的基本使用)

一:rpy2安装

相关环境为:Windows,anaconda3.0,R-3.4.4

1)打开cmd,直接安装。安装过程中下载对应版本的R以及R包。

 conda install rpy2

2)配置环境变量(添加环境变量)

不是在path中添加环境变量,而是新建单独的环境变量,如下图所示:

                  

                     

3)接下来可以通过导入rpy2的包,看是否安装成功并可使用:

import rpy2.robjects as robjects

 

二:rpy2的使用介绍

以下内容详见:rpy2的文档

1、python调用R对象(函数、包)

有三种方法调用R对象,分别“相当于”把r实例当作字典、把r实例当作方法、把r实例当作一个类对象

注:通过r实例,我们可以读取R的内置变量、调用R的函数、甚至直接把它当作R的解析器来用。

#‘pi’为R的内置变量
# 第一种
t0=robjects.r['pi']
print(t0[0])
# 第二种
t1=robjects.r('pi')# 这种方法从某种程度上讲是万能的,因为可以将任意大小和长度的R代码写成一个python字符串,之后通过robjects.r('Rcode')调用执行
print(t1[0])
a = robjects.r('a<-c(1,2,3)')
print(a)
#第三种
t2=robjects.r.pi# 这种方法对于名称中有“点号”的变量会出问题,比如data.frame/read.csv等
print(t2[0])

要注意:robjects.r("r_script") 可以执行r代码,比如 pi = robjects.r('pi') 就可以得到 R 中的PI(圆周率),返回的变量pi是一个向量,或者理解为python中的列表,通过pi[0] 就可以取出圆周率的值

对于一些特殊的R对象比如list和matrix,如果python要调去其中的部分数据,可以通过其rx()和rx2()方法操作。对于list,可以查看其name属性,以获得列表个个元素名称。rx()和相当于"["操作(注意取出的是R的list对象),而rx2()相当于"[["操作。一个例子:
 

tmp = robjects.r("list(a = matrix(1:10, nrow = 2), b = 'Hello')")
print(tmp)
print(tmp.names)
print(tmp.rx('a'))
print(tmp.rx(1))
print(tmp.rx2(1))
print(tmp.rx2('a').rx(1, 1)) # first element of 'a'
print(tmp.rx2('a').rx(1, True))# first row of 'a'

 

2、调用R函数

1)调用自定义函数

# creat an R function,自定义R函数
robjects.r('''
           f <- function(r){pi * r}
           ''')
t3=robjects.r['f'](3)
print('%.3f'%t3[0])

#一个复杂的例子如下:
r_script = '''
library(randomForest) # 导入随机森林包
## use data set iris
data = iris # 使用鸢尾花数据集
table(data$Species)
## create a randomForest model to classfy the iris species
# 创建随机森林模型给鸢尾花分类
iris.rf <- randomForest(Species~., data = data, importance=T, proximity=T)
print('--------here is the random model-------')
print(iris.rf)
print('--------here is the names of model-----')
print(names(iris.rf))
confusion = iris.rf$confusion
print(confusion)
'''
robjects.r(r_script)


2)调用R自带的函数

# internal function in R
t4=robjects.r['ls']()#可使用 ls()函数列出工作区中的所有变量;ls() 函数可以使用模式来匹配变量名称,eg:ls(pattern="var"),列出以“var”模式开头的变量
print(t4[0])

# another internal function
l = robjects.r['letters']
print(len(l))
print(robjects.r['paste'](l, collapse = '-'))

# an alternative way of getting 'paste' function in R
# eval the R code
coder = 'paste(%s, collapse = "-")' % (l.r_repr())
print(robjects.r(coder))

plot_data =robjects.r['read.csv']('data/iris.txt',header=False)
print(robjects.r.head(plot_data))
mtx = robjects.r['data.matrix'](plot_data)#把data转变成矩阵
#robjects.rdotchart(mtx)# 用矩阵的数据画点图
#robjects.r['dev.off']()#关闭设备

注:1)和2)两部分实际是上小节“python调用R对象”内容的使用

3)执行R的脚本文件

robjects.r.source(“file.r”)可以执行r脚本文件

robjects.r.source('D:/Rcode/Python_R/test01.r')
x = robjects.r('x')#获取脚本里的变量
y = robjects.r('y')
print(x)#[1] 1 2 3 4
print(y)#[1]  1  4  9 16

test01.r的内容如下:

x <- c(1,2,3,4)
y <- x*x
jpeg(file="plot.jpg") # 保存图像
plt <- plot(x,y) # 画散点图
dev.off() # 关闭设备

运行后会看到一张保存的图片。

4)载入和使用R包

 使用rpy2.robjects.packages.importr对象载入和使用R包,示例如下:

from rpy2.robjects.packages import importr

stats = importr('stats')
print('stats.rnorm(10):',stats.rnorm(10))

 

3、Python与R的对象转换

1)python对象转换成R对象

      通常,可以将python的list对象,转换成为R的vector对象【robjects.ListVector()将python的字典(或list)转换成R的列表】,之后直接使用R函数调用。rpy2提供了几个函数,供我们把将python的list转化成R的不同数据类型的vector,对应的函数有 robjects.IntVector(),robjects.FloatVector()等,具体如下:详见:rpy2的vector相关的官方文档

robjects.StrVector()#字符
robjects.IntVector()#整数
robjects.FloatVector()#浮点
robjects.complexVector()#复数
robjects.FactorVector()#因子
robjects.BoolVector()#布尔向量
robjects.ListVector()#列表


需注意:使用vector系列函数时,输入的只能是python的列表,而不能是数字或者字符串。

print(robjects.IntVector([1,2,3]))
print(robjects.FactorVector(['a','a','b','c']))
print(robjects.FloatVector([1.2,2.3]))
print(robjects.baseenv) # 基本环境空间
print(robjects.DataFrame({'a':[1,2],'b':[3,4]}))

testmatrix = robjects.IntVector([1, 2, 3, 4])
print(robjects.r['matrix'](testmatrix, nrow = 2))

'''
#结果如下:
[1] 1 2 3

[1] a a b c
Levels: a b c

[1] 1.2 2.3

<environment: namespace:base>

a.1L a.2L b.3L b.4L
1 1 2 3 4

  [,1] [,2]
[1,]    1    3
[2,]    2    4
'''

 

如果R的函数参数用到向量,有两种解决办法:
1.使用robject.**Vector()函数(如上)先将python对象转换成R对象,然后带入函数;
2.直接使用python对象(如下,目前我尝试的报错)

a = robjects.r['matrix'](range(10), nrow = 2)#报错NotImplementedError: Conversion 'py2ri' not defined for objects of type '<class 'range'>'
print(a)

2)R对象转换成python对象

推荐使用tuple()或者list()函数,将R对象转换成tuple或者list类型

a = robjects.r('c(1, 2, 3)')
print(a)         #[1] 1 2 3
print(str(a))    #[1] 1 2 3
print(tuple(a))  #(1.0, 2.0, 3.0)
print(list(a))   #[1.0, 2.0, 3.0]
b = robjects.r('matrix(1:6, 2, 3)')
print(b)
'''
    [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6
'''
print(tuple(b))  #(1, 2, 3, 4, 5, 6)
print(list(b))   #[1, 2, 3, 4, 5, 6]

 

三:进行Python调用R的代码实现

测试Python调用R传递并返回不同数据类型(是上面内容的使用,有些赘余,仅为记录)

Python的共同头文件等:

import rpy2.robjects as robjects

robjects.r.source('D:/Rcode/Python_R/first_pythonR.R')

1、R函数的参数有默认值

R部分:

testDefault <- function(a=3){
  result = a*2
  ## here should be NOTICE: must be return 'result'. must not return (a*2). 
  ## if do, it will error: arg would not be used
  return(result)
}

Python部分:

res_def =robjects.r.testDefault()
res_Notdef=robjects.r.testDefault(5)
print(res_def,res_Notdef)

运行结果:

[1] 6
 [1] 10

2、传递并返回数字

R部分:

add <- function(x,y){
  sum_=x+y
  cat('In R:\t',x,'+',y,'=',sum_,sep = ' ')
  return(sum_)
}

Python部分:

x=4
y=5
res_int =robjects.r.add(x,y)
print(type(res_int))
print(type(res_int[0]))
print(x,' + ',y,' = ',res_int[0])

运行结果:

<class 'rpy2.robjects.vectors.IntVector'>
<class 'int'>
4  +  5  =  9

In R:	 4 + 5 = 9

注:R代码的运行结果在后面

3、传递并返回字符串

R部分:

Hello <- function(s){
  reStr="Hello python!!"
  cat('\nIn R:\t',s)
  return(reStr)
}

Python部分:

s = 'Hello R!!'
res_str =robjects.r.Hello(s)
print(type(res_str))
print(res_str[0])

运行结果:

<class 'rpy2.robjects.vectors.StrVector'>
Hello python!!

In R:	 Hello R!!

4、传递并返回一维数组

R部分:

szTest <- function(sz){
  cat("\n")
  print(sz)
  cat(typeof(sz),mode(sz),class(sz))#integer numeric integer
  for(i in 1:length(sz)){
    sz[i]=sz[i]+2L
  }
  return(sz)
}

Python部分:

#sz_In=[1,2,3]#如这样传参数,则在R中为list类型
sz_Int=robjects.IntVector([1,2,3])
res_SzInt=robjects.r.szTest(sz_Int)
print(type(res_SzInt))#在R中一定要注意对于int型要在后面加'L',否则会被转化为float
print(res_SzInt)
res_ListInt=list(res_SzInt)
print(res_ListInt)

运行结果:

<class 'rpy2.robjects.vectors.IntVector'>
[1] 3 4 5
[3, 4, 5]


[1] 1 2 3
integer numeric integer

5、传递并返回矩阵

R部分:

matrixTest <- function(mat){
  cat("\n")
  print(mat)
  cat(typeof(mat),mode(mat),class(mat))#integer numeric matrix
  row_=nrow(mat)
  col_=ncol(mat)
  for(i in 1:row_){
    for(j in 1:col_){
      mat[i,j]=mat[i,j]+2L
    }
  }
  return(mat)
}

Python部分:

testmatrix = robjects.IntVector([1, 2, 3, 4,5,6])
mat_Int=robjects.r['matrix'](testmatrix, nrow = 2)
res_MatInt=robjects.r.matrixTest(mat_Int)
print(type(res_MatInt))
print(res_MatInt)

运行结果:

<class 'rpy2.robjects.vectors.Matrix'>
     [,1] [,2] [,3]
[1,]    3    5    7
[2,]    4    6    8


     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6
integer numeric matrix

6、传递并返回list

R部分:

listTest <- function(list_x){
  cat("\n")
  print(list_x)
  cat(typeof(list_x),mode(list_x),class(list_x))
  list_x[[1]][1]=list_x[[1]][1]+2L
  list_x[[2]][1]=list_x[[2]][1]+2.0
  list_x[[3]][1]=paste(list_x[[3]][1],"add")

  for(i in 1:length(list_x[[4]])){
     list_x[[4]][i]=list_x[[4]][i]+2
  }

  row_=nrow(list_x[[5]])
  col_=ncol(list_x[[5]])
  cat('\nrow_',row_,'col_',col_)
  for(i in 1:row_){
     for(j in 1:col_){
       #print(list_x[[5]][row_*(j-1)+i])
       list_x[[5]][row_*(j-1)+i]=list_x[[5]][row_*(j-1)+i]+2
     }
  }
  
  return(list_x)
}

Python部分:

testmatrix = robjects.FloatVector([1, 2, 3, 4,5,6])
x=robjects.ListVector([('first',1),('second',2.0),('third','string'),
                       ('fouth',robjects.FloatVector([ 3.0,4.0,5.0])),
                       ('fifth', robjects.r['matrix'](testmatrix, nrow = 2))])
res=robjects.r.listTest(x)
print(res)
print(type(res) ,type(res.rx2('fifth')))
#在这里注意如何获取从R返回的list的各元素
print(res.rx2('first')[0],res.rx2('third')[0],list(res.rx2('fouth')))
res_Listlist=list(res.rx2('fifth'))
print(res_Listlist)#注意在输出'符号时,使用\'(转义字符)

运行结果:

$first
[1] 3
$second
[1] 4
$third
[1] "string add"
$fouth
[1] 5 6 7
$fifth
     [,1] [,2] [,3]
[1,]    3    5    7
[2,]    4    6    8

<class 'rpy2.robjects.vectors.ListVector'> <class 'rpy2.robjects.vectors.Matrix'>
3   string add  [5.0, 6.0, 7.0]
[3.0, 4.0, 5.0, 6.0, 7.0, 8.0]




$first
[1] 1
$second
[1] 2
$third
[1] "string"
$fouth
[1] 3 4 5
$fifth
     [,1] [,2] [,3]
[1,]    1    3    5
[2,]    2    4    6

list list list
row_ 2 col_ 3

注:在传递给R函数list的数据时,可以有两种定义方法:

# if the order of the element does not matter,如果元素的顺序无关紧要
seasonal = robjects.ListVector({'order': robjects.IntVector((0,0,0)), 'period': scalar})#字典dict
# if the order matters,即如果顺序重要的话
seasonal = robjects.ListVector([('order', robjects.IntVector([0,0,0])), ('period', scalar)])#列表list

 

 

本文参考的文章:

rpy2安装

Python调用R语言

python中调用R (3)

Python&R语言-rpy2使用示例(4)

注:(3)的内容已经较详细了,(4)可以稍作参考

  • 36
    点赞
  • 156
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值