arrow 套件提供了 reticulate 方法,用於在同一個程序中於 R 和 Python 之間傳遞資料。本文提供簡要概述。
本文中的程式碼假設 arrow 和 reticulate 都已載入
library(arrow, warn.conflicts = FALSE)
library(reticulate, warn.conflicts = FALSE)
動機
您可能想在 R 中使用 PyArrow 的一個原因是,利用 Python 在目前開發狀態下比 R 更好地支援的功能。例如,在某個時間點,R arrow 套件不支援 concat_arrays()
,但 PyArrow 支援,因此在當時這會是一個很好的用例。在撰寫本文時,PyArrow 比 R 套件更全面地支援 Arrow Flight – 但請參閱 關於 arrow 中 Flight 支援的文章 – 因此這將是 PyArrow 對 R 使用者有益的另一個例子。
R 使用者可能想要使用 PyArrow 的第二個原因是,有效率地在 R 和 Python 之間傳遞資料物件。對於大型資料集,執行複製和轉換操作以將 R 中的原生資料結構(例如,資料框)轉換為 Python 中的類似結構(例如,Pandas DataFrame)反之亦然,可能會非常耗時且消耗 CPU 週期。由於 Arrow 資料物件(例如 Table)在 R 和 Python 中具有相同的記憶體格式,因此可以執行「零複製」資料傳輸,其中只需要在語言之間傳遞 metadata。正如稍後所示,這大幅提高了效能。
安裝 PyArrow
若要在 Python 中使用 Arrow,需要安裝 pyarrow
函式庫。例如,您可能希望建立一個包含 pyarrow
函式庫的 Python 虛擬環境。虛擬環境是為一個專案或目的而建立的特定 Python 安裝。在 Python 中使用特定環境是一個好的做法,這樣更新一個套件就不會影響其他專案中的套件。
您可以從 R 中執行設定。假設您想將您的虛擬環境命名為類似 my-pyarrow-env
的名稱。您的設定程式碼看起來會像這樣
virtualenv_create("my-pyarrow-env")
install_pyarrow("my-pyarrow-env")
如果您想將 pyarrow
的開發版本安裝到虛擬環境中,請將 nightly = TRUE
新增到 install_pyarrow()
命令中
install_pyarrow("my-pyarrow-env", nightly = TRUE)
請注意,您不必使用虛擬環境。如果您偏好 conda 環境,您可以使用此設定程式碼
conda_create("my-pyarrow-env")
install_pyarrow("my-pyarrow-env")
若要瞭解更多關於從 R 安裝和設定 Python 的資訊,請參閱 reticulate 文件,其中更詳細地討論了該主題。
匯入 PyArrow
假設 arrow 和 reticulate 都已在 R 中載入,您的第一步是確保正在使用正確的 Python 環境。若要使用虛擬環境執行此操作,請使用類似這樣的命令
use_virtualenv("my-pyarrow-env")
對於 conda 環境,請使用以下命令
use_condaenv("my-pyarrow-env")
完成此操作後,下一步是將 pyarrow
匯入到 Python 會話中,如下所示
pa <- import("pyarrow")
在 R 中執行此命令相當於在 Python 中進行以下匯入
import pyarrow as pa
檢查您的 pyarrow
版本也是一個好主意,如下所示
pa$`__version__`
## [1] "8.0.0"
pyarrow
版本 0.17 及更高版本包含對傳遞資料到 R 和從 R 傳遞資料的支援。
使用 PyArrow
您可以使用 reticulate 函數 r_to_py()
將物件從 R 傳遞到 Python,類似地,您可以使用 py_to_r()
將物件從 Python 會話拉到 R 中。為了說明這一點,讓我們在 R 中建立兩個物件:df_random
是一個包含 1 億行隨機資料的 R 資料框,而 tb_random
是儲存為 Arrow Table 的相同資料
set.seed(1234)
nrows <- 10^8
df_random <- data.frame(
x = rnorm(nrows),
y = rnorm(nrows),
subset = sample(10, nrows, replace = TRUE)
)
tb_random <- arrow_table(df_random)
在沒有 Arrow 的情況下將資料從 R 傳輸到 Python 是一個耗時的過程,因為底層物件必須被複製並轉換為 Python 資料結構
system.time({
df_py <- r_to_py(df_random)
})
## user system elapsed
## 0.307 5.172 5.529
相反地,跨越傳送 Arrow Table 幾乎是瞬間完成的
system.time({
tb_py <- r_to_py(tb_random)
})
## user system elapsed
## 0.004 0.000 0.003
然而,「傳送」並不是真正正確的詞。在內部,我們是在同一個程序中一起執行的 R 和 Python 直譯器之間傳遞資料指標,而沒有複製任何內容。沒有任何東西被傳送:我們正在共享和存取相同的內部 Arrow 記憶體緩衝區。
也可以將資料向另一個方向傳送。例如,讓我們在 pyarrow 中建立一個 Array
。
a <- pa$array(c(1, 2, 3))
a
## Array
## <double>
## [
## 1,
## 2,
## 3
## ]
請注意,a
現在是您的 R 會話中的 Array
物件 – 即使您是在 Python 中建立它的 – 並且您可以在其上應用 R 方法
a[a > 1]
## Array
## <double>
## [
## 2,
## 3
## ]
同樣地,您可以將此物件與在 R 中建立的 Arrow 物件結合,並且您可以使用 PyArrow 方法(如 pa$concat_arrays()
)來執行此操作
## Array
## <double>
## [
## 1,
## 2,
## 3,
## 5,
## 6,
## 7,
## 8,
## 9
## ]
現在您在 R 中有一個單一的 Array。
延伸閱讀
- 若要瞭解更多關於從 R 安裝和設定 Python 的資訊,請參閱 reticulate 文件。
- 若要學習 PyArrow,請參閱官方 PyArrow 文件 和 Apache Arrow Python Cookbook。
- Arrow 中的 R/Python 整合也在 PyArrow 整合文件、這篇 關於 Arrow 中 reticulate 整合的部落格文章,以及這篇 關於 Arrow 中 rpy2 整合的部落格文章 中討論。
- R Arrow 和 PyArrow 之間的整合透過 Arrow C 資料介面 支援。
- 若要瞭解更多關於 Arrow 資料物件的資訊,請參閱資料物件文章。