为什么在R和Python之间选择?

为什么在R和Python之间选择?

R和Python有许多相似之处,也有很多不同之处。两种语言之间的数据结构的大多数基本概念都非常相似,并且现在有许多数据科学包以这两种语言存在。但是R的设置方式我认为是“数据第一,应用程序第二”,而Python从一开始就感觉更多的是应用程序开发。例如,纯粹从语法和环境管理的角度来看,Javascript程序员插入Python比插入R的速度要快一些。如果你想了解更多关于数据科学家的相关内容,可以阅读以下这些文章:
打好数据科学和机器学习的基础——6本书带你学数学
数据科学家或将成为历史?——无代码数据科学的诞生
每个数据科学家都必须遵循的技巧
数据科学面试中的机器学习问题类型以及如何准备这些问题?

我越来越多地使用R和Python工作,我遇到过想同时使用这两种语言的情况。出现这种情况的原因有很多,但最常见的是你正在用R构建一些东西,并且需要你或其他人以前用Python编写的功能。当然,你可以用R重写它,但这不是很枯燥吗?

R中的reticulate包允许你在R会话中执行Python代码。它实际上已经存在了几年并且一直在不断改进,所以我想写一个简要的教程来介绍它是如何工作的。如果你是R的原生用户,建立和运行reticulate需要你对Python的工作原理有一些了解——以及它通常如何进行环境管理——因此,本教程可能会帮助你更快地设置好它而不是你自己去解决。

R和Python中的环境

任何编程项目都是在特定环境中运行的,它在环境中存储和访问所有需要的东西或在执行过程中创建的东西。在R中,所有项目都可以使用一个通用的全局环境,在这个环境中可以访问R的基础语言和所有已安装的包。从这个意义上说,R中的所有项目通常都在同一个公共核心环境中运行。考虑这个问题的一种方法是想象一下,你家里的每个人都共用一个iphone充电中心。他们必须离开房间给手机充电,如果他们要出售手机,买家需要自己解决充电安排。

然而,在Python中,每个项目通常都被设置为完全独立的——有它自己的运行环境、自己的Python基础副本以及它需要执行的所有模块的独立副本。你可以把它想象成每个人在他们的房间里都有自己的iPhone充电器。他们不需要走到外面在其他地方充电,如果他们卖了手机,它就配备自己的充电器。

Python模型在安装过程和磁盘/内存资源方面更昂贵,但它允许以最少的配置在个人之间更轻松地转移项目,因此不难看出它是如何更直接地从软件开发思维模式中成长起来的,这就是为什么我认为Python更“应用程序驱动”。在这里我应该指出,我所描述的对于这些语言的大多数日常用户来说都是“典型的”。它不是通用的,如果你知道如何使用这两种语言来完成这两种类型的项目工作流是可能的。我们还看到了R语言最近更多地转向python风格的环境管理模型——例如使用renv包。

下面是我绘制的一个小图表,简单地解释了R和Python环境通常工作方式之间的区别。

R和Python中的典型环境工作流(作者生成)

现在,如果你想让Python与R对话,它仍然需要找到它的环境——你不能让它访问R的全局环境。这就像让一个说英语的人向一个说汉语的人问路一样。

因此,要让Python在你的R项目中工作,你需要做两件事:

  1. 在你的R项目中设置一个Python环境,让Python可以了解它的方向
  2. reticulate包可以翻译Python代码,使其在R中工作

设置Python环境

从现在开始,我将使用一个简单的例子。假设我在RStudio中有一个R项目,它需要使用我用Python编写的函数。这里有一个简单的函数,我将它保存在一个名为light_years.py的Python脚本中,该脚本位于我的R项目目录test_python中(是的,RStudio允许你创建Python脚本!)这个函数将千米或英里作为输入,并计算以光速走完这段距离需要多少年——换句话说,光年的距离是多少:

from scipy.constants import c

def 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用户。你可以在这里获得适用于你的操作系统的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加载你的项目时,你需要告诉它在正确的环境中到哪里去找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了。

首先,你可以测试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之间无缝工作的五种方法、生成参数化Powerpoint文档和在R中运行XGBoost。

感谢阅读!你还可以订阅我们的YouTube频道,观看大量大数据行业相关公开课:https://www.youtube.com/channel/UCa8NLpvi70mHVsW4J_x9OeQ;在LinkedIn上关注我们,扩展你的人际网络!https://www.linkedin.com/company/dataapplab/

原文作者:Keith McNulty
翻译作者:马薏菲
美工编辑:过儿
校对审稿:Chuang
原文链接:https://keith-mcnulty.medium.com/why-choose-between-r-and-python-890b678bee16