9月7日-8日,相约 2023 腾讯全球数字生态大会!聚焦产业未来发展新趋势! 了解详情
写点什么

R 和 Python 可以兼得吗?

  • 2021-06-26
  • 本文字数:3694 字

    阅读完需:约 12 分钟

R和Python可以兼得吗?

本文最初发布于 towards data science 网站,经原作者授权由 InfoQ 中文站翻译并分享。


R 和 Python 有很多相似之处,也有很多不同之处。两种语言的数据结构的大多数基础概念都非常相似,并且现在这两种语言都有许多数据科学包可用。


但 R 的设计在我看来是“数据第一,应用第二”,而 Python 从一开始就给人感觉更多是应用程序开发驱动的。例如,纯粹从语法和环境管理的角度来看,Javascript 程序员上手 Python 的速度要比上手 R 的速度快一些。


最近,我在工作中用到 R 和 Python 的次数越来越多,并且遇到了想要同时使用两者的情况。出现这种情况的原因有很多,但最常见的一个场景是你正在用 R 构建某些东西,同时需要自己或其他人之前用 Python 编写的功能。当然,你可以用 R 重写它,但这不是很 DRY 吗?


R 中的 reticulate 这个包让你可以在 R 会话中执行 Python 代码。它实际上已经出来几年了,并且一直在不断改进,所以我想写一个关于它具体用法的简短教程。


如果你是 R 的开发者,要启动和运行 reticulate 需要你了解一些 Python 的运行机制—以及它管理环境的典型做法—所以本教程可以帮助你更快地完成设置,这样就不用你自己去费劲研究了。

R 和 Python 中的环境


任何编程项目都运行在一个环境中,它在这个环境里存储和访问自己在执行过程中需要或创建的所有东西。在 R 中,所有项目都可以使用一个通用的全局环境,在这个环境里可以访问 R 基础语言和所有已安装的包。从这个意义上说,R 中的所有项目通常都运行在相同的公共核心环境中。


换一种方式来看待这个景象,你可以想象你家中所有成员的 iPhone 都共享同一个充电站;他们必须离开自己的房间给手机充电;如果他们出售自己的 iPhone,买家需要自己解决充电问题。


但在 Python 中,每个项目通常都设置为完全自包含的—也就是说有自己的环境、自己的 Python 基础副本和它需要执行的所有模块的独立副本。你可以把这种景象想象成每个人在他们的房间里都有自己的 iPhone 充电器;他们不必走到外面找到统一的充电站来充电;如果他们出售手机,也会附上手机自己的充电器。


Python 的这种模式在安装过程和磁盘/内存资源消耗方面开销更大,但它能让开发者以最少的配置更轻松地在不同人之间转移项目。不难看出,它是直接从软件开发思维中发展出来的,这就是为什么我认为 Python 更像是“应用程序驱动的”。


这里我应该提一下,对于这两种语言的大多数日常用户来说,我所描述的是“典型的”场景。这些模式不是完全不变的,而且如果你知道该怎么做的话,在两种语言中都可以使用两种类型的项目流程。我们还看到 R 语言最近在朝着 Python 风格的环境管理模型迈进——例如 renv 包。


下面是我画的一个小草图,它以简单的方式展示 R 和 Python 中常见环境机制之间的区别。



R 和 Python 中的典型环境工作流


现在,如果你想让 Python 与 R 对话,前者仍然需要找到它自己的环境—你不能告诉它,让它去访问 R 的全局环境。这就像是让一个只会说英语的美国人去找一个只会说中文的中国人问路。


所以,要让 Python 在你的 R 项目中跑起来,你需要做两件事:


  1. 在 R 项目中设置一个 Python 环境,让 Python 可以认出自己的路。

  2. 用于翻译 Python 代码以使其在 R 中工作的 reticulate 包。

设置 Python 环境


从现在开始我会使用一个简单的例子来做说明。


假设我在 RStudio 中有一个 R 项目,它需要使用我用 Python 编写的函数。所以这里有一个简单的函数,我将它保存在我的 R 项目目录 test_python 中的一个名为 light_years.py 的 Python 脚本中(是的,RStudio 允许你创建 Python 脚本!)。


这个函数接收公里或英里为单位的距离作为输入,并计算以光速行进这段距离需要多少年。换句话说,以光年为单位的距离是多少。


from scipy.constants import cdef light_years(dist, unit = "km"):        c_per_year = c * 60 * 60 * 24 * 365.25        if unit == "km":            dist_meters = dist * 1000            elif unit == "mi":              dist_meters = dist * 1.60934 * 1000        else:              sys.exit("Cannot use that unit!")                    return dist_meters/c_per_year
复制代码


我在这里使用了一个非常简单的函数示例,以免让这篇文章太过冗长。所以它有点不切实际,也有点蠢,因为我导入整个 scipy 包只是为了获取一个常量的值,但希望它能帮助你领会我的意思。


现在正像我们上面所讨论的,我们需要为这段代码提供一个环境。它需要:


  1. 要使用的 Python 版本

  2. 访问 scipy 包,从而可以获得常数 c=光速


为你的 R 项目设置一个 Python 环境并不难。鉴于项目环境在 Python 中的重要性,市面上存在许多易用的环境管理工具。


我最喜欢的是 Anaconda。它有两个版本可用。完整版包含环境可能需要的所有一大堆东西,包括所有最常用的 Python 模块。然后是 Miniconda,它占用的磁盘空间少很多,更适合条件有限的 Python 用户。


你可以在此处https://docs.conda.io/en/latest/miniconda.html获取适用于你操作系统的 Miniconda。请为要使用的 Python 版本下载对应的 Conda。


安装完 Conda 后,如果你使用的是 macOS 或 Linux,通常会使用命令行来设置环境。只需转到终端中你的 R 项目目录(在我的例子中是 test_python)并使用以下命令:


conda create --name test_python
复制代码


就这么简单,你现在已经创建了一个 python 环境。我通常将我的环境命名为与项目文件夹相同的名称,以免将来混淆。


现在你需要告诉 Conda,让它为这个项目使用这个环境。当你仍在命令行的 test_python 目录中时,使用以下命令:


conda activate test_python
复制代码


现在你已将此项目链接到了 Python 环境,并且其中有 Python 基础的一个副本供你的代码运行使用。


最后,我们的函数需要 scipy 包,所以我们需要把它放在环境中。只需在激活的项目文件夹中输入以下内容即可:


conda install scipy
复制代码


然后,Conda 会将 scipy 及它认为可能需要的所有依赖项安装到你的活动环境中,你就可以开始使用了——可以这么说,就像 scipy 一样简单。


稍后你需要告诉 R,在这个环境中在哪里可以找到 Python。用这条命令可以获得所有环境的列表以及安装环境的路径:


conda info --envs
复制代码


例如,这能告诉我,我的环境安装在/Users/keithmcnulty/opt/miniconda3/envs/test_python。我总能在 bin 子目录中找到 Python 可执行文件——所以我的项目的 Python 可执行文件的完整路径是/Users/keithmcnulty/opt/miniconda3/envs/test_python/bin/python3,因为我使用的是 Python 3。我们需要告诉 R 的就是这些,这样它就知道在哪里可以找到 Python 环境了。

在 R 中运行你的 Python 函数


现在,无论你是像我一样用 Conda 设置了 Python 环境,还是使用了 virtualenv,你都已经完成了最艰巨的部分。剩下的操作很简单,因为 reticulate 会接手。


首先,当 R 加载项目时,你需要告诉 R,在正确的环境中在哪里可以找到 Python 可执行文件。为此,请启动一个空文本文件并添加以下内容,将我的路径替换为与你创建的项目环境中的 Python 可执行文件匹配的路径。


Sys.setenv(RETICULATE_PYTHON = "/Users/keithmcnulty/opt/miniconda3/envs/test_python/bin/python3")
复制代码


现在将这个文本文件保存在你的项目目录中,名称为.Renv。这是一个隐藏文件,每当你在 RStudio 中启动项目时,R 都会执行该文件。所以现在关闭 RStudio 并在打开 test_python 项目的同时重新启动它,它现在将指向 Python 环境。


如果你还没有安装 reticulate R 包,你应该在这个时候安装。安装后,你可以在终端中尝试一些测试,看看是否一切正常。


首先,你可以测试 R 是否知道 Python 在哪里。reticulate::py_available()应该返回“TRUE”。你还可以测试项目是否安装了你需要的 Python 模块:reticulate::py_module_available("scipy")应返回“TRUE”。假设一切正常,你已准备好将你的函数引入 R 了。


你可以使用简单的一条命令来获取 Python 脚本:


reticulate::source_python("light_years.py")
复制代码


现在你可以将 light_years()函数用作 R 函数。让我们看看以光速行驶一千万英里需要多少年:


> light_years(1000000000000000, "mi")[1] 170.1074
复制代码


很好!显然,这是一个非常简单的示例,但它确实告诉了你关于如何将 Python 代码集成到 R 脚本中的所有信息。你现在可以自由引入目前仅支持 Python 的各种功能或包,并让它们在 R 中工作,这非常令人兴奋。


如果你想查看一些高级示例,进一步了解如何使用 reticulate 将 Python 和 R 结合在一起使用,请查看我最近的几篇文章:


在同一项目中无缝切换R和Python的五种方法https://towardsdatascience.com/five-ways-to-work-seamlessly-between-r-and-python-in-the-same-project-bf173e35fdef


生成参数化Powerpoint文档https://towardsdatascience.com/generating-parameterized-powerpoint-documents-in-python-and-r-333368479038


在R中运行XGBoosthttps://towardsdatascience.com/how-to-run-python-ml-algorithms-easily-in-r-7e3b0f7c7aee

作者介绍


一开始我是一名纯数学家,然后我成为了心理咨询师和数据科学家。我很喜欢将所有这些学科的严谨思想应用在复杂的人性问题上。我也是一位编码极客,还是日本 RPG 的忠实粉丝。可以在LinkedInTwitter上找到我。还可以查看我在 drkeithmcnulty.com 上的博客或我即将发布的关于人类分析的教科书


原文链接:


https://towardsdatascience.com/why-choose-between-r-and-python-b12bf409d0d0

活动推荐:

2023年9月3-5日,「QCon全球软件开发大会·北京站」 将在北京•富力万丽酒店举办。此次大会以「启航·AIGC软件工程变革」为主题,策划了大前端融合提效、大模型应用落地、面向 AI 的存储、AIGC 浪潮下的研发效能提升、LLMOps、异构算力、微服务架构治理、业务安全技术、构建未来软件的编程语言、FinOps 等近30个精彩专题。咨询购票可联系票务经理 18514549229(微信同手机号)。

2021-06-26 10:002567
用户头像
刘燕 InfoQ高级技术编辑

发布了 1112 篇内容, 共 458.2 次阅读, 收获喜欢 1946 次。

关注

评论

发布
暂无评论
发现更多内容

互联网大厂100道Android面试题助你冲关金三银四!附小技巧

欢喜学安卓

android 程序员 面试 移动开发

音频互动连麦使用手册

anyRTC开发者

ios android 音视频 WebRTC RTC

程序开发必备的六个信条

这就是编程

程序开发

五年磨一剑,海外运营商数字化转型与新一代OSS

鲸品堂

方法论 数字化转型 运营商

通过序列号Sequence零代码实现订单流水号

crudapi

低代码 流水号 crud crudapi 序列号

nginx配置日志为json格式,nginx按照天实现日志分割,nginx配置负载均衡

Ng

图解 | 原来这就是 IO 多路复用

Java 程序员 架构 面试

vue+element中引入百度地图

尔嵘

Vue Element 百度地图

MySQL四大属性(特性) 底层实现原理

java_wxid

Java MySQL 数据库 面试 底层实现原理

Python实现excel公式格式化工具

小小明

Python Excel

剖析Android开发未来的出路在哪里,终局之战

欢喜学安卓

android 程序员 面试 移动开发

AI技术在小程序生态质量保障方向的落地实践

百度Geek说

小程序 AI

高并发下的Redis分布式锁

java_wxid

Java redis 高并发 分布式锁 setnx

Hello World !!!

潮湿了我押韵的心情

关于 JavaScript 闭包

程序员海军

JavaScript 大前端 闭包

Kubernetes弃用Docker运行时,小甜甜变牛夫人影响了谁?

TASKCTL

Docker 云计算 架构 容器 #Kubernetes#

单片机如何从上电复位执行到main函数?

不脱发的程序猿

28天写作 嵌入式软件 单片机 3月日更 上电复位执行到main函数

nginx做代理访问慢,优化方案

Ng

使用VUE和Element 创建一个dialog对话框组件的详细过程

尔嵘

Java岗位阿里+字节+滴滴+美团+腾讯+百度+京东12万字面试题总结

Java架构追梦

Java 阿里巴巴 架构 腾讯 面试

封装变化的内容

这就是编程

程序开发

第 9 周作业 _ 数据分析

园子

产品经理训练营 - 作业六

胡小湖

APK反编译

行者AI

编译

批量从Word中提取图片

小小明

Python

大侠请留步!欢迎有极客精神的你

Lily

layui使用templet格式化表格数据

中国云基础设施支出创新高,增速全球第一;国内首个区块链特色司法鉴定机构在京成立

京东科技开发者

区块链 人工智能 开发者

力扣(LeetCode)刷题,简单题(第12期)

不脱发的程序猿

面试 LeetCode 28天写作 算法面经 3月日更

最火前端Web组态软件(可视化)

尔嵘

大前端 可视化数据分析搭建 web组态 托拉拽组态

Android内存泄漏检测之LeakCanary2.0(Kotlin版)的实现原理

vivo互联网技术

android kotlin 内存泄漏

  • 扫码添加小助手
    领取最新资料包
R和Python可以兼得吗?_语言 & 开发_Keith McNulty_InfoQ精选文章