从R调用Python

概述

这个网状的包提供了一个R接口Python模块、类和函数。例如,此代码导入Python操作系统模块并调用其中的一些函数它:

图书馆(网状)
操作系统<- 进口(“操作系统”)
操作系统$列表目录(".")
[1] “.git”“.gitignore”“.Rbuildignore”“.RData”[5] “.Rhistory”“.Rproj.user”“.travis.yml”“appveyor.yml”[9] “DESCRIPTION”“docs”“external”“index.html”[13] “index.Rmd”“inst”“发布”“LICENSE”“[17] “man”“NAMESPACE”“NEWS.md”“pkgdown”[21]“R”“README.md”“reticulate.Rproj”“src”[25]“测试”“想定案例”

Python模块和类中的函数和其他数据可以是通过访问$操作符(类似于与R列表、环境或引用类交互)。

这个网状的包与所有Python版本>=2.7。与NumPy集成是可选的需要NumPy>=1.6。

Python版本

默认情况下,reticulate使用您的路径(即Sys.which(“python”)). 这个use_python()函数允许您指定备用版本,例如:

图书馆(网状)
使用python(“/usr/local/bin/python”)

这个use_virtualenv()use_condaenv()函数使您能够在virtual或conda中指定Python的版本环境,例如:

图书馆(网状)
使用虚拟机(“梅耶夫”)

请参阅上的文章Python版本配置了解更多详细信息。

Python包

您可以使用标准shell安装任何必需的Python包工具,如管道康达。或者,reticulate包含一组用于管理和安装的功能virtualenvs和Conda环境中的包。请参阅上的文章正在安装Python包了解更多详细信息。

类型转换

调用Python时,R数据类型自动转换为它们的等效Python类型。当值从Python返回到R时它们被转换回R类型。类型转换如下:

R(右) 蟒蛇 示例
单元素向量 标量 1,1升,真的,“foo”
多元素向量 列表 c(1.0、2.0、3.0),c(1升、2升、3升)
多种类型列表 薄纱 列表(1L,TRUE,“foo”)
命名列表 Dict公司 列表(a=1L,b=2.0),dict(x=x数据)
矩阵/阵列 数字日历 矩阵(c(1,2,3,4),nrow=2,ncol=2)
数据帧 熊猫数据帧 数据帧(x=c(1,2,3),y=c(“a”、“b”、“c”))
功能 Python函数 函数(x)x+1
原始 Python字节数组 原始(c(1:10))
空、真、假 无、正确、错误 无效的,真的,错误的

如果返回自定义类的Python对象,则返回R引用返回到该对象。您可以调用方法和访问属性就像它是R引用类的实例一样。

导入模块

这个导入()函数可用于导入任何Python模块。例如:

difflib<- 进口(“difflib”)
difflib$ndiff公司(foo,bar)

文件cmp<- 进口(“文件cmp”)
文件cmp$化学机械抛光(目录1,目录2)

这个import_main()import_builtins()函数使您可以访问执行代码的主模块默认值和内置Python函数的集合。对于例子:

主要的<- import_main(导入_主)()

内置<- 导入内置项()
内置$打印(“foo”)

如果您执行了Python代码,那么主模块通常很有用并希望访问其结果(请参见有关更多详细信息,请参阅下面的部分)。

寻找脚本

这个source_python()函数将源代码为Python脚本并使其创建的对象在R环境中可用(通过默认调用环境)。例如,考虑以下内容Python脚本:

定义添加(x,y):
  返回x个+

我们使用source_python()函数,然后可以调用添加()直接来自R的功能:

源python('添加.py')
添加(5,10)
[1] 15

正在执行代码

您可以使用副本文件(_R)py_运行_字符串功能。然后可以访问使用第页对象由reticulate出口:

图书馆(网状)

py_运行文件(“script.py”)

py_运行_字符串(“x=10”)

#通过“py”对象访问python主模块
第页$x个

对象转换

默认情况下,当Python对象返回到R时,它们将被转换对应的R型。然而,如果您愿意进行转换默认情况下,从Python到R显式并处理本机Pythons对象你可以通过convert=假进口功能。在这种情况下,Python到R的转换将被禁用模块返回自进口。例如:

#导入numpy并指定无自动Python到R转换
净现值<- 进口(“numpy”,转换= 错误的)

#使用NumPy进行一些数组操作
<-净现值$阵列(c(c)(1:4))
总和<-$累加()

#在末尾显式转换为R
py_to_r(总和)

如上所示,如果您需要在结束时访问R对象您可以调用py_to_r()功能明确地。

获取帮助

您可以使用py_help()功能。例如:

操作系统<- 进口(“操作系统”)
py_help(_H)(操作系统$chdir)

列表、元组和字典

R类型到Python类型的自动转换在大多数情况下,但有时您需要在R上更明确side提供Python所需的类型。

例如,如果Python API需要一个列表,并且您传递了一个元素R向量,它将被转换为Python标量。克服这只需使用R列表函数明确:

foo公司$酒吧(索引= 列表(42L(左)))

类似地,Python API可能需要元组相当地而不是列表。在这种情况下,您可以使用元组()功能:

元组(“a”,“b”,“c”)

R命名列表被转换为Python字典,但您可以还使用dict()功能:

字典(foo公司= “酒吧”,索引= 42L(左))

如果需要传递使用更复杂的对象(相对于字符串)作为其键。

数字类型和索引

R和Python有不同的默认数字类型。如果你写42在R中,它被视为浮点数,而42在Python中被视为整数。

这意味着当Python API需要整数时,您需要一定要使用L(左)后缀在R中。例如,如果foo公司函数需要一个整数作为其指数你会这样做:

foo公司$酒吧(索引= 42L(左))

Python集合使用基于0的索引进行寻址,而不是从R中您可能熟悉的基于1的指数。为了解决您将在R中写入数组的第一项:

个项目[[1]]

然而,如果您通过网状结构调用Python中的方法取一个索引,你可以写下它来处理第一项:

项目$得到(0L(左))

请注意基于0的索引以及L(左)指示t该值是一个整数。

阵列

R矩阵和数组自动转换为数字Py数组。

从R转换为NumPy时,直接映射NumPy数组到R数组的底层内存(不进行复制)。在这种情况下,NumPy数组使用兼容的基于列的内存布局使用R(即Fortran样式而不是C样式)。从转换时NumPy到R,R接收NumPy数组的按列排序的副本。

您还可以使用np_array()功能。例如,如果您需要使用C而不是Fortran样式创建NumPy数组内存中布局(在面向行的计算中实现更高的性能)或者如果您想更多地控制NumPy数组的数据类型明确地。以下是一些示例用法np_array():

<- np_阵列(c(c)(1:8),数据类型= “浮点16”)
<- np_阵列(c(c)(1:8),订单= “C”)

关于使用不同内存顺序的数组的推理可以是很棘手。这个R和Python中的数组文章提供了其他详细信息。

另外,请记住,在调用NumPy方法数组索引时基于0而不是1,并且需要L(左)后缀到表示它们是整数。

数据帧

R数据帧可以自动转换为熊猫数据帧。默认情况下,使用控制R数组的相同规则转换列NumPy数组转换,但提供了几个扩展:

R(右) 蟒蛇
系数 分类变量
POSIXt公司 具有数据类型的NumPy数组=日期时间64[ns]

如果R数据帧具有行名称,则生成的Pandas DataFrame将使用这些行名称重新标识(反之亦然)。特殊也可用于日期时间索引相关使用Pandas DataFrame;然而,因为R只支持字符行名称的向量首先转换为字符。

使用Pandas可为null的数据类型

Pandas对可为null的数据类型有实验性的支持。那些数据类型具有对缺失值的内置支持,由pd编号使用它们可以更好地表示R值。

用户可以选择使用Pandas可为null的数据类型,而不是numpy通过设置网状.pandas_use_nullable_dypes真的。例如:

数据流<- 数据帧(
  整数= c(c)(,1:4),
  num个= c(c)(,rnorm公司(4)),
  lgl公司= c(c)(,代表(c(c)(真的,错误的),2)),
  字符串= c(c)(,个字母[1:4])
)
选项(网状.pandas_use_nullable_data_types= 真的)
收件人(_to)(df)
#>int num lgl字符串
#>0<NA><NA><NA><NA>
#>1 1-0.697855 True真
#>2 2-0.253042假b
#>3 3 0.385421真c
#>4 4 0.519933假d

稀疏矩阵

稀疏矩阵由创建矩阵R包可以转换Scipy公司CSC矩阵反之亦然。当您想将稀疏矩阵传递给接受Scipy CSC矩阵的Python函数利用这种格式,例如高效的列切片和快速矩阵向量乘积。

例如,我们首先使用矩阵::稀疏矩阵():

库(矩阵)N<-5dgc_矩阵<-稀疏矩阵(i=样品(N,N),j=样品(N,N),x=运行(N),dims=c(N,N))

稀疏矩阵如下所示:

>dgc矩阵“dgCMatrix”类的5 x 5稀疏矩阵[1,] 0.2264952 .          .          .         .        [2,] .         .          .          .         0.3927282[3,] .         .          .          0.9215908 .        [4,] .         .          0.01777771 .         .        [5,] .         0.05885743 .          .         .

让我们使用将其转换为Scipy CSC矩阵r_to_py():

>csc矩阵<-r-to_py(x)>csc矩阵(0, 0)    0.226495201467(4, 1)    0.0588574311696(3, 2)    0.0177777127828(2, 3)    0.921590822982(1, 4)    0.392728160601

请注意,右侧包含矩阵,而左侧表示它们在矩阵。

我们还可以使用py_to_r()将CSC矩阵转换回矩阵::dgC矩阵然后可以在与原始稀疏矩阵相同的R中易于操作我们之前使用创建的矩阵::稀疏矩阵():

>py_to_r(csc矩阵)“dgCMatrix”类的5 x 5稀疏矩阵[1,] 0.2264952 .          .          .         .        [2,] .         .          .          .         0.3927282[3,] .         .          .          0.9215908 .        [4,] .         .          0.01777771 .         .        [5,] .         0.05885743 .          .         .

带上下文

R具有泛型函数可用于与Python上下文管理器对象具有关键字进行相同操作)。例如:

第页<- 导入内置项()
具有(第页$打开(“output.txt”,“w”)%作为%文件{
文件$(“你好!”)
})

此示例打开一个文件并确保其自动关闭位于with块的末尾。注意使用%作为%运算符对上下文管理器创建的对象进行别名。

遍历器

如果Python API返回迭代器或生成器,则可以进行交互使用迭代()功能。这个迭代()函数可用于将R函数应用于迭代器生成的每个项:

迭代(iter,打印)

如果不将函数传递给迭代结果将收集到R矢量中:

结果<- 迭代(iter)

请注意遍历器将耗尽其价值通过迭代():

<- 迭代(iter)#结果不为空
b条<- 迭代(iter)#结果为空,因为项目已被清空

元素级迭代

您还可以使用iter_next()功能。例如:

虽然(真的) {
项目<- iter_next(_N)(iter)
  如果(is.完整(项目)
    打破
}

默认情况下iter_next()将返回无效的当迭代完成,但您可以提供自定义完整的它将被返回。对于例子:

虽然(真的) {
项目<- iter_next(_N)(iter、,已完成= )
  如果(国际标准编号(项目)
    打破
}

注意,Python中的一些迭代器/生成器是无限的。在那里面case调用方将需要自定义逻辑来确定何时终止循环。

发电机

蟒蛇发电机实现Python迭代器协议的函数。类似地网状的发电机()函数使您能够创建来自R函数的Python迭代器。

在Python中,生成器使用产量关键字。在R中,值只是从函数返回的。一个好处产量关键字是启用连续迭代以使用以前迭代的状态。在R中,这可以是通过返回一个通过改变其封闭环境的函数来完成<<-运算符。例如:

#定义生成器函数
序列生成器<-功能(开始){
价值<-开始
  功能() {
价值<<-价值+ 1
价值
}
}

#将函数转换为python迭代器
国际单位<- py_致畸剂(序列生成器(10))

如果要指示迭代的结束,请返回无效的从函数:

序列生成器<-功能(开始){
价值<-开始
  功能() {
价值<<-价值+ 1
    如果(值< 100)
价值
    其他的
      无效的
}
}

请注意,您可以更改指示迭代使用完整的参数(例如py_iterator(函数,已完成=NA)).

功能

签名

默认情况下,R函数通过泛型转换为Python签名(函数(…)),其中既没有关键字参数或参数的默认值。

例如,下面我们应用r_to_py()到R函数然后我们使用检查Python模块以获取转换后的函数的参数规范。您可以看到包装函数的签名看起来与原始R函数的签名。

>检查<- 进口(“检查”)
>已转换的func<- 收件人(_to)(功能(a),b条= 1.5) {})
>检查$获取argspec(已转换为func)
ArgSpec标准(参数=[],变量='参数',关键字=“夸格斯”,默认值=无)

此默认转换通常工作良好,但有些Python图书馆严格检查用户的函数签名提供了回调。在这些情况下,通用函数(…)签名将无法通过此检查。

对于这些情况,您可以使用py_func()包裹R函数,以便包装的函数具有与原始R函数的参数,例如一个参数没有默认值和其他参数b条使用默认值值1.5。

>包装func<- 副本(_F)(功能(a),b条= 1.5) {})
>检查$获取argspec(wrapped_func)
ArgSpec标准(参数=[“a”,“b”],变量=无,关键字=无,默认值=(1.5,))

注意,R函数的签名不能包含深奥的Python不兼容的构造。例如,我们不能有R函数带有类似签名的函数(a=1,b)自Python以来函数要求没有默认值的参数出现在具有默认值的参数。

背景线程

在某些情况下,Python库会调用Python背景线程。因为R代码必须在主线程上运行,所以这不会默认情况下,当您将R函数作为回调传递时,它将起作用。

要解决此问题,可以使用py_main_thread_func(),它将为您的R函数提供一个特殊的包装器,以确保它将仅在主线程上调用。

高级

有几个更高级的功能可用主要是在为Python创建高级R接口时库。

Python对象

通常与来自R的Python对象交互涉及使用$运算符访问函数的任何属性你需要的对象。使用时$,Python对象是在可能的情况下自动转换为R等价物。这个以下函数使您能够在较低级别(例如,除非显式调用这个py_to_r功能):

功能 描述
py_has_attr() 检查对象是否具有指定的属性。
py_get_attr() 获取Python对象的属性。
py_set_attr() 设置Python对象的属性。
py_list_attributes() 列出Python对象的所有属性。
py_len() Python对象的长度。
py_call() 使用指定的参数调用Python可调用对象。
py_to_r() 将Python对象转换为其R等效对象
r_to_py() 将R对象转换为其Python等效对象

泡菜

可以使用py_save_object(保存对象)py加载对象功能:

功能 描述
py_save_object() 使用pickle将Python对象保存到文件中。
py_load_object() 从文件中加载以前保存的Python对象。

配置

以下函数使您能够查询有关当前系统上可用的Python配置。

功能 描述
py_available() 检查此系统上是否有Python接口。
py_numpy_available() 检查NumPy的R接口是否可用(需要NumPy>= 1.6)
py模块可用() 检查此系统上是否有Python模块。
py_config() 获取有关正在使用的Python的位置和版本的信息。

输出控制

这些函数使您能够从蟒蛇:

功能 描述
py_capture_output() 捕获指定表达式的Python输出并将其返回为R字符向量。
py_suppress_warnings() 执行指定的表达式,取消显示Python警告。

其他

这些功能提供其他低级别的杂项能力:

功能 描述
py_set_seed() 设置Python和NumPy随机种子。
py_unicode() 将字符串转换为Python unicode对象。
py_str(),py_repr() 获取Python对象的字符串表示。
py_id() 获取Python对象的唯一标识符
py_is_null_xptr() 检查Python对象是否为null externalptr。
py_validate_xptr() 检查Python对象是否为空externalptr并抛出如果是,则返回错误。

了解更多信息

以下文章涵盖了使用的其他方面网状的: