R 教學#
關於新增 lubridate 綁定的 R 教學#
在本教學中,我們將記錄如何依照指南的快速參考章節以及更詳細的首次 PR 的步驟章節中指定的步驟,貢獻 Arrow R 套件的綁定。當您發現此處缺少某些資訊時,請隨時查閱這些章節。
此綁定將新增至 R 套件中的 expression.R
檔案。但是,如果您要新增的綁定將位於其他位置,您也可以按照這些步驟操作。
本教學與首次 PR 的步驟不同,因為我們將處理一個特定的案例。本教學並非旨在作為逐步指南。
開始吧!
設定#
讓我們設定 Arrow 儲存庫。我們在此假設 Git 已經安裝。否則,請參閱設定章節。
一旦 Fork 了 Apache Arrow 儲存庫 (請參閱Fork 儲存庫),我們將複製它並將主要儲存庫的連結新增到我們的上游。
$ git clone https://github.com/<your username>/arrow.git
$ cd arrow
$ git remote add upstream https://github.com/apache/arrow
建置 R 套件#
建置 R 套件的步驟會因您使用的作業系統而異。因此,在本教學中,我們僅參考建置過程的說明。
問題#
在本教學中,我們將處理一個問題,即實作一個簡單的 mday()
函數的綁定,該函數將與 lubridate
中現有的 R 函數相符。
注意
如果您沒有問題並且需要協助尋找問題,請參閱指南的尋找適合新手入門的問題 🔎部分。
一旦您選定了一個問題並分配給自己,就可以繼續下一步。
開始在新分支上工作#
在開始新增綁定之前,我們應該從更新後的主分支建立一個新分支。
$ git checkout main
$ git fetch upstream
$ git pull --ff-only upstream main
$ git checkout -b ARROW-14816
現在我們可以開始研究 R 函數和我們想要公開或連接的 C++ Arrow 計算函數。
檢查 lubridate mday() 函數
瀏覽 lubridate 文件,我們可以看到 mday()
接受日期物件並傳回月份中的日期作為數值物件。
我們可以在 R 主控台中執行一些範例,以幫助我們更好地理解該函數
> library(lubridate)
> mday(as.Date("2000-12-31"))
[1] 31
> mday(ymd(080306))
[1] 6
檢查 Arrow C++ day() 函數
從計算函數文件中,我們可以看到 day
是一個一元函數,這表示它接受單一資料輸入。資料輸入必須是 Temporal class
,傳回值是 Integer/numeric
類型。
Temporal class
指定為:日期類型 (Date32, Date64)、時間類型 (Time32, Time64)、Timestamp、Duration、Interval。
我們可以從 R 主控台使用 call_function
呼叫 Arrow C++ 函數,以查看其運作方式
> call_function("day", Scalar$create(lubridate::ymd("2000-12-31")))
Scalar
31
我們可以看到 lubridate 和 Arrow 函數運作於並傳回等效的資料類型。lubridate 的 mday()
函數沒有額外的引數,並且 Arrow C++ 函數 day()
也沒有相關聯的選項類別。
查看 expressions.R
中的程式碼,我們可以看到 day 函數已經在 R 套件端指定/對應:apache/arrow
我們只需要將 mday()
新增到表達式列表中,將其連接到 C++ day
函數。
# second is defined in dplyr-functions.R
# wday is defined in dplyr-functions.R
"mday" = "day",
"yday" = "day_of_year",
"year" = "year",
新增測試#
現在我們需要新增一個測試,以檢查一切是否運作良好。如果還有其他選項或邊緣情況,我們將必須新增更多測試。查看類似函數 (例如 yday()
或 day())
的測試,我們可以看到新增兩個測試的好地方是在 test-dplyr-funcs-datetime.R
中
test_that("extract mday from timestamp", {
compare_dplyr_binding(
.input %>%
mutate(x = mday(datetime)) %>%
collect(),
test_df
)
})
而且
test_that("extract mday from date", {
compare_dplyr_binding(
.input %>%
mutate(x = mday(date)) %>%
collect(),
test_df
)
})
現在我們需要查看測試是否通過,或者我們是否需要進行更多研究和程式碼修正。
devtools::test(filter="datetime")
> devtools::test(filter="datetime")
ℹ Loading arrow
See arrow_info() for available features
ℹ Testing arrow
See arrow_info() for available features
✔ | F W S OK | Context
✖ | 1 230 | dplyr-funcs-datetime [1.4s]
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Failure (test-dplyr-funcs-datetime.R:187:3): strftime
``%>%`(...)` did not throw the expected error.
Backtrace:
1. testthat::expect_error(...) test-dplyr-funcs-datetime.R:187:2
2. testthat:::expect_condition_matching(...)
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
══ Results ═════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
Duration: 1.4 s
[ FAIL 1 | WARN 0 | SKIP 0 | PASS 230 ]
我們在 strftime
函數中遇到一個失敗,但是查看程式碼,我們發現它與我們的工作無關。我們可以繼續前進,並詢問其他人在執行測試時是否也遇到類似的失敗。可能我們只需要重新建置函式庫。
檢查風格#
我們也應該執行程式碼風格檢查器,以檢查程式碼的風格是否遵循 tidyverse 風格。為此,我們在 Shell 中執行以下命令
$ make style
R -s -e 'setwd(".."); if (requireNamespace("styler")) styler::style_file(setdiff(system("git diff --name-only | grep r/.*R$", intern = TRUE), file.path("r", source("r/.styler_excludes.R")$value)))'
Loading required namespace: styler
Styling 2 files:
r/R/expression.R ✔
r/tests/testthat/test-dplyr-funcs-datetime.R ℹ
────────────────────────────────────────────
Status Count Legend
✔ 1 File unchanged.
ℹ 1 File changed.
✖ 0 Styling threw an error.
────────────────────────────────────────────
Please review the changes carefully!
建立 Pull Request#
首先,讓我們使用 Shell 中的 git status
檢閱我們的變更,以查看哪些檔案已變更,並僅提交我們正在處理的檔案。
$ git status
On branch ARROW-14816
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: R/expression.R
modified: tests/testthat/test-dplyr-funcs-datetime.R
然後使用 git diff
查看檔案中的變更,以便發現我們可能犯的任何錯誤。
$ git diff
diff --git a/r/R/expression.R b/r/R/expression.R
index 37fc21c25..0e71803ec 100644
--- a/r/R/expression.R
+++ b/r/R/expression.R
@@ -70,6 +70,7 @@
"quarter" = "quarter",
# second is defined in dplyr-functions.R
# wday is defined in dplyr-functions.R
+ "mday" = "day",
"yday" = "day_of_year",
"year" = "year",
diff --git a/r/tests/testthat/test-dplyr-funcs-datetime.R b/r/tests/testthat/test-dplyr-funcs-datetime.R
index 359a5403a..228eca56a 100644
--- a/r/tests/testthat/test-dplyr-funcs-datetime.R
+++ b/r/tests/testthat/test-dplyr-funcs-datetime.R
@@ -444,6 +444,15 @@ test_that("extract wday from timestamp", {
)
})
+test_that("extract mday from timestamp", {
+ compare_dplyr_binding(
+ .input %>%
+ mutate(x = mday(datetime)) %>%
+ collect(),
+ test_df
+ )
+})
+
test_that("extract yday from timestamp", {
compare_dplyr_binding(
.input %>%
@@ -626,6 +635,15 @@ test_that("extract wday from date", {
)
})
+test_that("extract mday from date", {
+ compare_dplyr_binding(
+ .input %>%
+ mutate(x = mday(date)) %>%
+ collect(),
+ test_df
+ )
+})
+
test_that("extract yday from date", {
compare_dplyr_binding(
.input %>%
一切看起來都沒問題。現在我們可以進行提交 (將我們的變更儲存到分支歷史記錄)
$ git commit -am "Adding a binding and a test for mday() lubridate"
[ARROW-14816 ed37d3a3b] Adding a binding and a test for mday() lubridate
2 files changed, 19 insertions(+)
我們可以使用 git log
檢查提交歷史記錄
$ git log
commit ed37d3a3b3eef76b696532f10562fea85f809fab (HEAD -> ARROW-14816)
Author: Alenka Frim <frim.alenka@gmail.com>
Date: Fri Jan 21 09:15:31 2022 +0100
Adding a binding and a test for mday() lubridate
commit c5358787ee8f7b80f067292f49e5f032854041b9 (upstream/main, upstream/HEAD, main, ARROW-15346, ARROW-10643)
Author: Krisztián Szűcs <szucs.krisztian@gmail.com>
Date: Thu Jan 20 09:45:59 2022 +0900
ARROW-15372: [C++][Gandiva] Gandiva now depends on boost/crc.hpp which is missing from the trimmed boost archive
See build error https://github.com/ursacomputing/crossbow/runs/4871392838?check_suite_focus=true#step:5:11762
Closes #12190 from kszucs/ARROW-15372
Authored-by: Krisztián Szűcs <szucs.krisztian@gmail.com>
Signed-off-by: Sutou Kouhei <kou@clear-code.com>
如果我們在不久前啟動了分支,我們可能需要 Rebase 到上游主分支,以確保沒有合併衝突
$ git pull upstream main --rebase
現在我們可以將我們的工作推送到 GitHub 上名為 origin 的 Fork Arrow 儲存庫。
$ git push origin ARROW-14816
Enumerating objects: 233, done.
Counting objects: 100% (233/233), done.
Delta compression using up to 8 threads
Compressing objects: 100% (130/130), done.
Writing objects: 100% (151/151), 35.78 KiB | 8.95 MiB/s, done.
Total 151 (delta 129), reused 33 (delta 20), pack-reused 0
remote: Resolving deltas: 100% (129/129), completed with 80 local objects.
remote:
remote: Create a pull request for 'ARROW-14816' on GitHub by visiting:
remote: https://github.com/AlenkaF/arrow/pull/new/ARROW-14816
remote:
To https://github.com/AlenkaF/arrow.git
* [new branch] ARROW-14816 -> ARROW-14816
現在我們必須前往 GitHub 上的 Arrow 儲存庫 以建立 Pull Request。在 GitHub Arrow 頁面 (主要或 Fork) 上,我們將看到一個黃色通知欄,其中註明我們最近推送了到 ARROW-14816 分支的內容。太棒了,現在我們可以點擊 Compare & pull request 來建立 Pull Request。

Apache Arrow 儲存庫上的通知欄。#
首先,我們需要將標題更改為 ARROW-14816: [R] 實作 lubridate::mday() 的綁定,以便與問題相符。請注意,已新增標點符號!
額外說明:在本教學建立時,我們一直使用 Jira 問題追蹤器。由於我們目前使用 GitHub Issues,因此標題將以 GH-14816: [R] 實作 lubridate::mday() 的綁定 為前綴.
我們也將新增描述,以向其他人清楚說明我們嘗試做的事情。

編輯我們的 Pull Request 的標題和描述。#
一旦我們點擊 Create pull request,我們的程式碼就可以在 Apache Arrow 儲存庫中作為 Pull Request 進行審閱。

這就是我們的 Pull Request!#
Pull Request 已連接到問題,並且 CI 正在執行。經過一段時間並收到審閱後,我們可以更正程式碼、評論、解決對話等等。
另請參閱
有關 Pull Request 工作流程的更多資訊,請參閱 Pull Request 的生命週期。
我們建立的 Pull Request 可以在這裡查看。