原文:
www.kdnuggets.com/2015/10/integrating-python-r-executing-part2.html
作者:Chris Musselle (Mango Solutions)。
在上一篇文章中,我们讨论了为什么你可能想将 R 和 Python 集成到一个管道中,以及如何通过使用平面文件隔离来实现这一点。在此过程中,我们介绍了如何从命令行运行 Python 或 R 脚本,以及如何访问传入的任何附加参数。在这篇文章中,我们通过展示如何将两个脚本链接在一起,完成集成过程,方法是让 R 调用 Python,反之亦然。
1. 谷歌网络安全证书 - 快速进入网络安全职业生涯。
2. 谷歌数据分析专业证书 - 提升你的数据分析技能
3. 谷歌 IT 支持专业证书 - 支持你的组织 IT
为了更好地理解子进程执行时发生的情况,值得详细回顾在命令行上执行 Python 或 R 进程时发生的事情。当运行以下命令时,会启动一个新的 Python 进程来执行脚本。
python path/to/myscript.py arg1 arg2 arg3
在执行过程中,任何输出打印到标准输出和标准错误流的内容都会显示在控制台上。实现这一点最常见的方法是通过内置函数(Python 中的print()
和 R 中的cat()
或print()
),这些函数将给定的字符串写入stdout
流。Python 进程将在脚本执行完成后关闭。
以这种方式运行命令行脚本是有用的,但如果有多个顺序但独立的脚本需要以这种方式执行,则可能变得繁琐且容易出错。然而,Python 或 R 进程可以以类似于上述命令行方法的方式直接执行另一个进程。这是有益的,因为它允许,例如,父 Python 进程启动子 R 进程来运行特定的分析脚本。一旦 R 脚本完成,这个子 R 进程的输出可以传递回父 Python 进程,而不是打印到控制台。使用这种方法可以消除在命令行上手动逐步执行的需要。
为了说明一个进程如何执行另一个进程,我们将使用两个简单的示例:一个是 Python 调用 R,另一个是 R 调用 Python。每个案例中执行的分析故意简化,以便集中于实现这种调用机制的过程。
我们的简单示例 R 脚本将从命令行接收一系列数字并返回最大值。
# max.R
# 获取命令行参数 myArgs <- commandArgs(trailingOnly = TRUE)
# 转换为数字 nums = as.numeric(myArgs)
# cat 将结果写入 stdout 流 cat(max(nums))
要从 Python 执行此操作,我们使用 subprocess 模块,这是标准库的一部分。我们将使用 check_output
函数来调用 R 脚本,该函数执行一个命令并存储 stdout 的输出。
要从 Python 执行 max.R
脚本,你首先需要构建要执行的命令。这的格式类似于我们在 第一部分 的博文系列中看到的命令行语句,在 Python 中表示为一个字符串列表,其中的元素对应于以下内容:
['<command_to_run>', '<path_to_script>', 'arg1' , 'arg2', 'arg3', 'arg4']
从 Python 执行 R 脚本的一个示例见以下代码。
# run_max.py 导入 subprocess
# 定义命令和参数 command ='Rscript' path2script ='path/to your script/max.R'
# 列表中的变量数量 args = ['11','3','9','42']
# 构建 subprocess 命令 cmd = [command, path2script] + args
x = subprocess.check_output(cmd, universal_newlines=True)
print('这些数字的最大值是:', x)
参数 universal_newlines=True
告诉 Python 将返回的输出解释为文本字符串,并处理 Windows 和 Linux 的换行符。如果省略该参数,输出将以字节字符串形式返回,并且必须通过调用 x.decode()
将其解码为文本,才能进行进一步的字符串操作。
对于我们的简单 Python 脚本,我们将根据提供的子字符串模式(第二个参数)将给定字符串(第一个参数)分割成多个子字符串。结果将逐行打印到控制台。
# splitstr.py import sys
# 获取传递的参数 string = sys.argv[1] pattern = sys.argv[2]
# 执行分割 ans = string.split(pattern)
# 将结果元素列表连接成一个以换行符分隔的字符串并打印 print('\n'.join(ans))
执行 R 的子进程时,建议使用 R 的system2函数来执行和捕获输出。这是因为内置的system函数使用起来更复杂,且不具备跨平台兼容性。
构建要执行的命令类似于上述 Python 示例,但system2
期望命令与其参数分开解析。此外,这些参数的第一个必须始终是要执行的脚本的路径。
处理 R 脚本路径中的空格可能会带来一个最终的复杂问题。解决这个问题的最简单方法是将整个路径名用双引号括起来,然后用单引号将这个字符串包裹起来,以便 R 保留参数中的双引号。
执行 Python 脚本的 R 示例见以下代码。
# run_splitstr.R
command ="python
# 注意字符串中的单引号 + 双引号(如果路径中有空格需要) path2script='"path/to your script/splitstr.py"'
# 在向量中构建参数 string ="3523462---12413415---4577678---7967956---5456439" pattern ="---" args = c(string, pattern)
# 将脚本路径作为第一个参数添加 allArgs = c(path2script, args)
output = system2(command, args=allArgs, stdout=TRUE)
print(paste("子字符串为:\n", output))
要将标准输出捕获到字符向量中(每个元素一行),必须在system2
中指定stdout=TRUE
,否则仅返回退出状态。当stdout=TRUE
时,退出状态会存储在一个名为“status”的属性中。
可以通过使用子进程调用将 Python 和 R 集成到一个应用程序中。这些调用允许一个父进程调用另一个子进程,并捕获打印到 stdout 的任何输出。在这篇文章中,我们展示了如何使用这种方法让 R 脚本调用 Python 及反之亦然。
在未来的文章中将基于这篇文章的内容以及第一部分,展示一个实际的示例,说明如何在应用程序中将 Python 和 R 结合使用。
原文。
相关:
-
R 与 Python:正面交锋的数据分析
-
数据科学编程:Python 与 R
-
数据科学中的 R 与 Python:赢家是…
-
R 和 Python 用户表现出惊人的稳定性,但地区差异显著