本文最初發布於 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 中,所有項目都可以使用一個通用的全局環境,在這個環境裡可以訪問 R 基礎語言和所有已安裝的包。從這個意義上說,R 中的所有項目通常都運行在相同的公共核心環境中。
換一種方式來看待這個景象,你可以想像你家中所有成員的 iPhone 都共享同一個充電站;他們必須離開自己的房間給手機充電;如果他們出售自己的 iPhone,買家需要自己解決充電問題。
但在 Python 中,每個項目通常都設置為完全自包含的—也就是說有自己的環境、自己的 Python 基礎副本和它需要執行的所有模塊的獨立副本。你可以把這種景象想像成每個人在他們的房間裡都有自己的 iPhone 充電器;他們不必走到外面找到統一的充電站來充電;如果他們出售手機,也會附上手機自己的充電器。
Python 的這種模式在安裝過程和磁碟 / 內存資源消耗方面開銷更大,但它能讓開發者以最少的配置更輕鬆地在不同人之間轉移項目。不難看出,它是直接從軟體開發思維中發展出來的,這就是為什麼我認為 Python 更像是「應用程式驅動的」。
這裡我應該提一下,對於這兩種語言的大多數日常用戶來說,我所描述的是「典型的」場景。這些模式不是完全不變的,而且如果你知道該怎麼做的話,在兩種語言中都可以使用兩種類型的項目流程。我們還看到 R 語言最近在朝著 Python 風格的環境管理模型邁進——例如 renv 包。
下面是我畫的一個小草圖,它以簡單的方式展示 R 和 Python 中常見環境機制之間的區別。
R 和 Python 中的典型環境工作流
現在,如果你想讓 Python 與 R 對話,前者仍然需要找到它自己的環境—你不能告訴它,讓它去訪問 R 的全局環境。這就像是讓一個只會說英語的美國人去找一個只會說中文的中國人問路。
所以,要讓 Python 在你的 R 項目中跑起來,你需要做兩件事:
在 R 項目中設置一個 Python 環境,讓 Python 可以認出自己的路。
用於翻譯 Python 代碼以使其在 R 中工作的 reticulate 包。
從現在開始我會使用一個簡單的例子來做說明。
假設我在 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 包只是為了獲取一個常量的值,但希望它能幫助你領會我的意思。
現在正像我們上面所討論的,我們需要為這段代碼提供一個環境。它需要:
要使用的 Python 版本
訪問 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 環境了。
現在,無論你是像我一樣用 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 中運行 XGBoost:https://towardsdatascience.com/how-to-run-python-ml-algorithms-easily-in-r-7e3b0f7c7aee
一開始我是一名純數學家,然後我成為了心理諮詢師和數據科學家。我很喜歡將所有這些學科的嚴謹思想應用在複雜的人性問題上。我也是一位編碼極客,還是日本 RPG 的忠實粉絲。可以在 LinkedIn 或 Twitter 上找到我。還可以查看我在 drkeithmcnulty.com 上的博客或我即將發布的關於人類分析的 教科書。
原文連結:
https://towardsdatascience.com/why-choose-between-r-and-python-b12bf409d0d0
你也「在看」嗎?👇