一、问题背景与适用场景

做数据分析或者机器学习的朋友,大概率会遇到过这种情况:R语言画图好看、统计分析顺手,但做数据爬取、文本处理的时候,又觉得Python的库更全、更方便;反过来,Python做机器学习强,但统计建模的细节处理又不如R灵活。那能不能把俩语言的优势结合起来?答案是可以,用R的reticulate包就能直接调用Python的模块,不用来回切换环境、复制粘贴数据,省老鼻子事了。

但很多人刚用reticulate的时候,都会踩两个大坑:一个是版本冲突——比如R里指定调用Python3.9,结果实际跑的时候用的是Python3.10,或者Python里装的库在R里找不到;另一个是路径问题——明明电脑里装了Python,reticulate就是找不到,或者找不到自己装的第三方库。这俩问题一卡,本来想提高效率的工具,反而变成了麻烦。

这个方法适合所有需要同时用R和Python的开发者:比如做数据科学的学生写论文,既要用Python爬数据、用PyTorch训练模型,又要用R做统计检验、画 publication 级别的图;比如企业里的分析师,既要用R处理业务数据,又要调用Python的NLP库做文本分析;甚至是刚入门的新手,想同时学俩语言,不用来回切换环境。

二、版本冲突的成因与解决方法

2.1 版本冲突的常见表现

版本冲突最常见的表现有两种:第一种是R里设置的Python版本和实际运行的版本对不上,比如你明明指定用Python3.9,结果跑代码的时候,报错说某个库不存在,查一下发现实际用的是Python3.10,而这个库只装在3.9里;第二种是同一个Python版本下,R里找不到你装的第三方库,比如你在Python里装了pandas,结果R里调用的时候提示“ModuleNotFoundError: No module named 'pandas'”。

造成版本冲突的核心原因,是电脑里装了多个Python版本,而reticulate默认找的Python不是你想要的那个。比如Windows系统里,可能同时装了Python3.8、3.9、3.10,还有Anaconda自带的Python;Mac系统里,系统自带的Python2.7(旧版本)、brew装的Python、Anaconda的Python混在一起,reticulate不知道该用哪个。

2.2 版本冲突的解决步骤(带完整示例)

首先,先明确自己要用的Python版本,比如我们要指定用Python3.9,而且这个版本里装了pandas、numpy这些常用库。整个过程的技术栈统一用R(带reticulate包),具体步骤如下:

第一步,先在R里安装并加载reticulate包,代码如下:

# 安装reticulate包(如果已经装过可以跳过)
install.packages("reticulate")
# 加载reticulate包
library(reticulate)

第二步,先查看电脑里所有可用的Python版本,确认自己要的版本存在,代码如下:

# 列出电脑里所有可用的Python版本
py_discover_config()

跑这段代码之后,会输出很多信息,重点看“python”那一行,比如输出里可能有:

python:         /usr/bin/python3.9
libpython:      /usr/lib/python3.9/config-3.9-x86_64-linux-gnu/libpython3.9.so
pythonhome:     /usr:/usr
version:        3.9.7 (default, Sep 16 2021, 13:09:58)  [GCC 7.5.0]

或者Windows里可能是:

python:         C:\Python39\python.exe
libpython:      C:\Python39\python39.dll
pythonhome:     C:\Python39
version:        3.9.7 (tags/v3.9.7:1016ef3, Aug 30 2021, 20:19:38) [MSC v.1929 64 bit (AMD64)]

确认自己要的Python3.9的路径是对的,比如上面的路径是/usr/bin/python3.9(Mac/Linux)或者C:\Python39\python.exe(Windows)。

第三步,指定reticulate用这个Python版本,代码如下:

# 指定用Python3.9,替换成自己电脑里的实际路径
use_python("/usr/bin/python3.9", required = TRUE)
# required = TRUE表示如果指定的Python不存在,直接报错,避免用默认的版本

第四步,验证指定的版本是否生效,同时验证能不能调用Python的库,代码如下:

# 导入Python的sys模块,查看实际用的Python版本
sys <- import("sys")
# 打印Python版本,看是不是3.9
print(sys$version)
# 导入pandas库,看能不能正常调用
pandas <- import("pandas")
# 用pandas创建一个测试数据框,验证功能
df <- pandas$DataFrame(data = list(a = c(1, 2, 3), b = c(4, 5, 6)))
# 打印数据框,看是不是正常输出
print(df)

如果这段代码跑出来的Python版本是3.9,而且pandas能正常创建数据框,说明版本冲突解决了。

如果还是找不到pandas,那可能是你指定的Python版本里没装pandas,这时候可以用reticulate直接给这个Python版本装库,不用单独开Python环境,代码如下:

# 给指定的Python版本装pandas,不用自己去Python里装
py_install("pandas")

装完之后再重新运行上面的验证代码,就能正常调用了。

三、路径问题的成因与解决方法

3.1 路径问题的常见表现

路径问题最常见的表现是:reticulate找不到Python,跑py_discover_config()的时候,输出里的Python路径是错的,或者干脆找不到;或者能找到Python,但找不到自己装的第三方库,比如你在Python里装了requests,结果R里调用的时候提示找不到。

造成路径问题的核心原因,是电脑里的环境变量没配置对,或者多个Python版本的路径冲突。比如Windows系统里,你装了Python3.9,但没把它的路径加到系统的PATH环境变量里,reticulate就找不到;或者你装了Anaconda,Anaconda的Python路径在PATH里排在前面,reticulate默认用了Anaconda的Python,而不是你想要的。

3.2 路径问题的解决步骤(带完整示例)

首先,先明确自己要的Python的路径,比如Python3.9的路径是C:\Python39\python.exe(Windows)或者/usr/bin/python3.9(Mac/Linux),如果不知道路径,可以在电脑里搜索“python.exe”(Windows)或者在终端里跑which python3.9(Mac/Linux)找到。

第一步,先配置系统的环境变量(以Windows为例,Mac/Linux的步骤类似):

  1. 打开“此电脑”,右键点击“属性”,选择“高级系统设置”;
  2. 点击“环境变量”,在“系统变量”里找到“Path”,点击“编辑”;
  3. 点击“新建”,把Python3.9的路径(比如C:\Python39)和Python的Scripts路径(比如C:\Python39\Scripts)加进去;
  4. 把这两个路径移到所有其他Python路径的前面,比如原来的Anaconda路径在前面,就把Python3.9的路径往上移;
  5. 点击“确定”保存,然后重启电脑(一定要重启,不然环境变量不会生效)。

第二步,在R里验证路径配置是否生效,代码如下:

# 重新加载reticulate包,避免缓存
detach("package:reticulate", unload = TRUE)
library(reticulate)
# 重新查看可用的Python版本,确认路径是对的
py_discover_config()

如果输出里的Python路径是你想要的,说明路径配置对了。

第三步,指定路径并验证,代码和版本冲突的验证代码一样:

# 指定用Python3.9的路径
use_python("/usr/bin/python3.9", required = TRUE)
# 验证版本
sys <- import("sys")
print(sys$version)
# 验证调用库
requests <- import("requests")
# 用requests爬一个测试网页,验证功能
response <- requests$get("https://www.baidu.com")
# 打印状态码,看是不是200(正常)
print(response$status_code)

如果状态码是200,说明路径问题解决了。

四、技术的优缺点与注意事项

4.1 技术的优缺点

优点主要有三个:第一,不用来回切换环境,直接在R里调用Python,数据可以直接在俩语言之间传递,比如把R里的数据框直接传给Python处理,处理完再传回来,不用复制粘贴,省时间;第二,能同时用俩语言的优势,比如Python的爬取、NLP、深度学习库,R的统计、画图功能,结合起来用;第三,不用额外装复杂的环境,只要装了R和Python,用reticulate就能直接用,入门门槛低。

缺点也有两个:第一,版本和路径问题容易踩坑,很多新手刚用的时候会被卡很久;第二,性能上比单独用R或者Python稍差,因为俩语言之间的传递数据有一定的开销,处理超大数据集的时候可能会慢一点。

4.2 注意事项

第一,一定要指定Python版本,不要用默认的,不然很容易出现版本冲突;第二,指定版本的时候一定要用绝对路径,不要用相对路径,避免路径问题;第三,装Python库的时候,尽量用py_install(),不要单独在Python里装,因为py_install()会自动装到你指定的Python版本里,避免装错版本;第四,如果用Anaconda的Python,一定要注意虚拟环境的路径,指定虚拟环境的Python路径的时候,要指定虚拟环境里的python.exe,不是Anaconda主环境的。

五、应用场景与文章总结

5.1 应用场景

除了开头说的学生写论文、分析师做业务分析,还有几个常见的场景:比如做深度学习的人,用Python训练模型,然后用R做模型的可视化和解释,比如用R的ggplot2画模型的混淆矩阵、特征重要性图;比如做文本分析的人,用Python的jieba分词、word2vec处理文本,然后用R做文本的聚类、主题模型分析;比如做统计建模的人,用R做模型的参数估计,然后用Python的scikit-learn做模型的评估和预测。

5.2 文章总结

用reticulate包结合R和Python,是一个非常实用的方法,但版本冲突和路径问题是新手最容易踩的两个坑。解决版本冲突的核心是指定自己要的Python版本,解决路径问题的核心是配置好系统的环境变量。只要把这两个问题解决了,就能充分发挥俩语言的优势,提高自己的工作效率。