6  Quy trình làm việc: tập lệnh và dự án

Chương này sẽ giới thiệu cho bạn hai công cụ thiết yếu để tổ chức mã: tập lệnh (script) và dự án (project).

6.1 Tập lệnh

Cho đến nay, bạn đã sử dụng console để chạy mã. Đó là nơi tuyệt vời để bắt đầu, nhưng bạn sẽ thấy nó trở nên chật chội khá nhanh khi bạn tạo đồ họa ggplot2 phức tạp hơn và pipeline dplyr dài hơn. Để có thêm không gian làm việc, hãy sử dụng trình soạn thảo tập lệnh. Mở nó bằng cách nhấp vào menu File, chọn New File, rồi R script, hoặc sử dụng phím tắt Cmd/Ctrl + Shift + N. Bây giờ bạn sẽ thấy bốn bảng, như trong Hình 6.1. Trình soạn thảo tập lệnh là nơi tuyệt vời để thử nghiệm với mã. Khi bạn muốn thay đổi gì đó, bạn không phải gõ lại toàn bộ, bạn chỉ cần chỉnh sửa tập lệnh và chạy lại. Và khi bạn đã viết mã hoạt động đúng và làm những gì bạn muốn, bạn có thể lưu nó thành file tập lệnh để dễ dàng quay lại sau.

IDE RStudio với Editor, Console, và Output được đánh dấu.
Hình 6.1: Mở trình soạn thảo tập lệnh thêm một bảng mới ở phía trên bên trái của IDE.

6.1.1 Chạy mã

Trình soạn thảo tập lệnh là nơi tuyệt vời để xây dựng biểu đồ ggplot2 phức tạp hoặc string thao tác dplyr dài. Chìa khóa để sử dụng trình soạn thảo hiệu quả là ghi nhớ một trong những phím tắt quan trọng nhất: Cmd/Ctrl + Enter. Phím tắt này thực thi biểu thức R hiện tại trong console. Ví dụ, xem đoạn mã bên dưới.

library(dplyr)
library(nycflights13)

not_cancelled <- flights |>
  filter(!is.na(dep_delay)█, !is.na(arr_delay))

not_cancelled |>
  group_by(year, month, day) |>
  summarize(mean = mean(dep_delay))

Nếu con trỏ của bạn ở █, nhấn Cmd/Ctrl + Enter sẽ chạy toàn bộ lệnh tạo ra not_cancelled. Nó cũng sẽ di chuyển con trỏ đến lệnh tiếp theo (bắt đầu với not_cancelled |>). Điều này giúp dễ dàng chạy qua toàn bộ tập lệnh bằng cách nhấn Cmd/Ctrl + Enter liên tục.

Thay vì chạy mã từng biểu thức, bạn cũng có thể thực thi toàn bộ tập lệnh trong một bước với Cmd/Ctrl + Shift + S. Làm điều này thường xuyên là cách tuyệt vời để đảm bảo bạn đã nắm bắt tất cả các phần quan trọng của mã trong tập lệnh.

Chúng tôi khuyến nghị bạn luôn bắt đầu tập lệnh với các package bạn cần. Bằng cách đó, nếu bạn chia sẻ mã với người khác, họ có thể dễ dàng thấy những package nào cần cài đặt. Tuy nhiên, lưu ý rằng bạn không bao giờ nên đặt install.packages() trong tập lệnh bạn chia sẻ. Thật thiếu tế nhị khi giao một tập lệnh sẽ thay đổi thứ gì đó trên máy tính của họ nếu họ không cẩn thận!

Khi làm việc qua các chương trong tương lai, chúng tôi rất khuyến nghị bạn bắt đầu trong trình soạn thảo tập lệnh và thực hành phím tắt. Theo thời gian, việc gửi mã đến console theo cách này sẽ trở nên tự nhiên đến mức bạn không cần suy nghĩ.

6.1.2 Chẩn đoán của RStudio

Trong trình soạn thảo tập lệnh, RStudio sẽ đánh dấu lỗi cú pháp bằng đường gợn sóng đỏ và dấu chéo ở thanh bên:

Trình soạn thảo tập lệnh với mã x y <- 10. Dấu X đỏ cho biết có lỗi cú pháp. Lỗi cú pháp cũng được đánh dấu bằng đường gợn sóng đỏ.

Di chuột qua dấu chéo để xem vấn đề là gì:

Trình soạn thảo tập lệnh với mã x y <- 10. Dấu X đỏ cho biết có lỗi cú pháp. Lỗi cú pháp cũng được đánh dấu bằng đường gợn sóng đỏ. Di chuột qua X hiển thị hộp văn bản với nội dung unexpected token y và unexpected token <-.

RStudio cũng sẽ thông báo cho bạn về các vấn đề tiềm ẩn:

Trình soạn thảo tập lệnh với mã 3 == NA. Dấu chấm than vàng cho biết có thể có vấn đề tiềm ẩn. Di chuột qua dấu chấm than hiển thị hộp văn bản với nội dung use is.na to check whether expression evaluates to NA.

6.1.3 Lưu và đặt tên

RStudio tự động lưu nội dung trình soạn thảo tập lệnh khi bạn thoát, và tự động tải lại khi bạn mở lại. Tuy nhiên, bạn nên tránh Untitled1, Untitled2, Untitled3, v.v. và thay vào đó lưu tập lệnh và đặt tên mang tính mô tả.

Có thể hấp dẫn khi đặt tên file là code.R hay myscript.R, nhưng bạn nên suy nghĩ kỹ hơn trước khi chọn tên cho file. Ba nguyên tắc quan trọng cho việc đặt tên file như sau:

  1. Tên file nên máy đọc được: tránh dấu cách, ký hiệu, và ký tự đặc biệt. Không dựa vào phân biệt chữ hoa/thường để phân biệt file.
  2. Tên file nên người đọc được: sử dụng tên file để mô tả nội dung bên trong.
  3. Tên file nên hoạt động tốt với thứ tự sắp xếp mặc định: bắt đầu tên file bằng số để sắp xếp theo bảng chữ cái đặt chúng theo thứ tự sử dụng.

Ví dụ, giả sử bạn có các file sau trong thư mục dự án.

alternative model.R
code for exploratory analysis.r
finalreport.qmd
FinalReport.qmd
fig 1.png
Figure_02.png
model_first_try.R
run-first.r
temp.txt

Có nhiều vấn đề ở đây: khó tìm file nào cần chạy trước, tên file chứa dấu cách, có hai file cùng tên nhưng khác chữ hoa/thường (finalreport so với FinalReport1), và một số tên không mô tả nội dung (run-firsttemp).

Đây là cách đặt tên và tổ chức tốt hơn cho cùng bộ file:

01-load-data.R
02-exploratory-analysis.R
03-model-approach-1.R
04-model-approach-2.R
fig-01.png
fig-02.png
report-2022-03-20.qmd
report-2022-04-02.qmd
report-draft-notes.txt

Đánh số các tập lệnh chính giúp rõ ràng thứ tự chạy và sơ đồ đặt tên nhất quán giúp dễ thấy điều gì thay đổi. Ngoài ra, các hình được đánh nhãn tương tự, báo cáo được phân biệt bằng ngày trong tên file, và temp được đổi tên thành report-draft-notes để mô tả nội dung tốt hơn. Nếu bạn có nhiều file trong một thư mục, nên tổ chức thêm một bước bằng cách đặt các loại file khác nhau (tập lệnh, hình, v.v.) vào các thư mục khác nhau.

6.2 Dự án

Một ngày nào đó, bạn sẽ cần thoát R, đi làm việc khác, và quay lại phân tích sau. Một ngày nào đó, bạn sẽ làm việc trên nhiều phân tích đồng thời và muốn giữ chúng riêng biệt. Một ngày nào đó, bạn sẽ cần đưa dữ liệu từ thế giới bên ngoài vào R và gửi kết quả số và hình từ R ra thế giới bên ngoài.

Để xử lý các tình huống thực tế này, bạn cần đưa ra hai quyết định:

  1. Nguồn sự thật là gì? Bạn sẽ lưu gì như bản ghi lâu dài về những gì đã xảy ra?

  2. Phân tích của bạn nằm ở đâu?

6.2.1 Nguồn sự thật là gì?

Với người mới bắt đầu, có thể dựa vào Environment hiện tại để chứa tất cả đối tượng bạn đã tạo trong suốt quá trình phân tích. Tuy nhiên, để dễ dàng hơn khi làm việc trên dự án lớn hơn hoặc cộng tác với người khác, nguồn sự thật nên là các tập lệnh R. Với tập lệnh R (và file dữ liệu), bạn có thể tái tạo environment. Chỉ với environment, việc tái tạo tập lệnh R khó hơn nhiều: bạn sẽ phải gõ lại rất nhiều mã từ bộ nhớ (chắc chắn mắc lỗi) hoặc phải cẩn thận khai thác lịch sử R.

Để giúp giữ tập lệnh R là nguồn sự thật cho phân tích của bạn, chúng tôi rất khuyến nghị bạn hướng dẫn RStudio không bảo tồn không gian làm việc giữa các phiên. Bạn có thể làm điều này bằng cách chạy usethis::use_blank_slate()2 hoặc bằng cách mô phỏng các tùy chọn trong Hình 6.2. Điều này sẽ gây cho bạn chút khó chịu ngắn hạn, vì bây giờ khi khởi động lại RStudio, nó sẽ không còn nhớ mã bạn đã chạy lần trước cũng như các đối tượng bạn đã tạo hoặc tập dữ liệu bạn đã đọc sẽ không có sẵn. Nhưng nỗi khó chịu ngắn hạn này cứu bạn khỏi đau khổ dài hạn vì nó buộc bạn nắm bắt tất cả thủ tục quan trọng trong mã. Không có gì tệ hơn việc phát hiện ba tháng sau rằng bạn chỉ lưu kết quả của một phép tính quan trọng trong environment, không phải bản thân phép tính trong mã.

Cửa sổ RStudio Global Options trong đó tùy chọn Restore .RData into workspace at startup không được chọn. Ngoài ra, tùy chọn Save workspace to .RData on exit được đặt thành Never.
Hình 6.2: Sao chép các tùy chọn này trong tùy chọn RStudio để luôn bắt đầu phiên RStudio với bảng sạch.

Có một cặp phím tắt tuyệt vời hoạt động cùng nhau để đảm bảo bạn đã nắm bắt các phần quan trọng của mã trong trình soạn thảo:

  1. Nhấn Cmd/Ctrl + Shift + 0/F10 để khởi động lại R.
  2. Nhấn Cmd/Ctrl + Shift + S để chạy lại tập lệnh hiện tại.

Chúng tôi cùng nhau sử dụng mẫu này row trăm lần mỗi tuần.

Ngoài ra, nếu bạn không sử dụng phím tắt, bạn có thể vào Session > Restart R rồi bôi đen và chạy lại tập lệnh hiện tại.

Ghi chúRStudio server

Nếu bạn đang sử dụng RStudio server, phiên R của bạn mặc định không bao giờ được khởi động lại. Khi bạn đóng tab RStudio server, có thể cảm giác như bạn đang đóng R, nhưng server thực tế vẫn giữ nó chạy ngầm. Lần tiếp theo bạn quay lại, bạn sẽ ở đúng nơi bạn đã rời đi. Điều này khiến việc khởi động lại R thường xuyên càng quan trọng hơn để bạn bắt đầu với bảng sạch.

6.2.2 Phân tích của bạn nằm ở đâu?

R có khái niệm mạnh mẽ về thư mục làm việc (working directory). Đây là nơi R tìm kiếm file bạn yêu cầu tải, và nơi nó sẽ đặt bất kỳ file nào bạn yêu cầu lưu. RStudio hiển thị thư mục làm việc hiện tại ở đầu console:

Tab Console hiển thị thư mục làm việc hiện tại là ~/Documents/r4ds.

Và bạn có thể in ra trong mã R bằng cách chạy getwd():

getwd()
#> [1] "/Users/hadley/Documents/r4ds"

Trong phiên R này, thư mục làm việc hiện tại (nghĩ về nó như “nhà”) nằm trong thư mục Documents của hadley, trong thư mục con gọi là r4ds. Mã này sẽ trả về kết quả khác khi bạn chạy, vì máy tính của bạn có cấu trúc thư mục khác với máy Hadley!

Với người mới sử dụng R, việc để thư mục làm việc là thư mục home, thư mục documents, hoặc bất kỳ thư mục kỳ lạ nào trên máy tính là được. Nhưng bạn đã đi qua khá nhiều chương trong cuốn sách này, và bạn không còn là người mới nữa. Rất sớm thôi bạn nên phát triển sang tổ chức dự án thành thư mục và, khi làm việc trên một dự án, đặt thư mục làm việc của R thành thư mục tương ứng.

Bạn có thể đặt thư mục làm việc từ bên trong R nhưng chúng tôi không khuyến nghị:

setwd("/path/to/my/CoolProject")

Có cách tốt hơn; cách cũng đưa bạn lên con đường quản lý công việc R như chuyên gia. Cách đó là dự án RStudio.

6.2.3 Dự án RStudio

Giữ tất cả file liên quan đến một dự án (dữ liệu đầu vào, tập lệnh R, kết quả phân tích, và hình) cùng nhau trong một thư mục là thói quen khôn ngoan và phổ biến đến mức RStudio có hỗ trợ tích hợp cho điều này qua dự án (project). Hãy tạo một dự án cho bạn sử dụng khi làm việc qua phần còn lại của cuốn sách này. Nhấp File > New Project, rồi làm theo các bước trong Hình 6.3.

Ba ảnh chụp màn hình của menu New Project. Trong ảnh đầu tiên, cửa sổ Create Project được hiển thị và New Directory được chọn. Trong ảnh thứ hai, cửa sổ Project Type được hiển thị và Empty Project được chọn. Trong ảnh thứ ba, cửa sổ Create New Project được hiển thị và tên thư mục là r4ds và dự án đang được tạo như thư mục con của Desktop.
Hình 6.3: Để tạo dự án mới: (trên) đầu tiên nhấp New Directory, rồi (giữa) nhấp New Project, rồi (dưới) điền tên thư mục (dự án), chọn thư mục con tốt và nhấp Create Project.

Đặt tên dự án là r4ds và suy nghĩ kỹ về thư mục con nào bạn đặt dự án vào. Nếu bạn không lưu ở nơi hợp lý, sẽ khó tìm nó trong tương lai!

Khi quá trình này hoàn tất, bạn sẽ có một dự án RStudio mới dành cho cuốn sách này. Kiểm tra rằng “nhà” của dự án là thư mục làm việc hiện tại:

getwd()
#> [1] /Users/hadley/Documents/r4ds

Bây giờ nhập các lệnh sau vào trình soạn thảo tập lệnh, và lưu file với tên “diamonds.R”. Sau đó, tạo thư mục mới có tên “data”. Bạn có thể làm điều này bằng cách nhấp nút “New Folder” trong bảng Files của RStudio. Cuối cùng, chạy toàn bộ tập lệnh sẽ lưu file PNG và CSV vào thư mục dự án. Đừng lo về chi tiết, bạn sẽ học chúng sau trong cuốn sách.

library(tidyverse)

ggplot(diamonds, aes(x = carat, y = price)) +
  geom_hex()
ggsave("diamonds.png")

write_csv(diamonds, "data/diamonds.csv")

Thoát RStudio. Kiểm tra thư mục liên quan đến dự án — chú ý file .Rproj. Nhấp đúp vào file đó để mở lại dự án. Chú ý bạn quay lại nơi bạn đã rời đi: cùng thư mục làm việc và lịch sử lệnh, và tất cả file bạn đang làm việc vẫn mở. Vì bạn đã làm theo hướng dẫn ở trên, bạn sẽ có một environment hoàn toàn mới, đảm bảo bạn bắt đầu với bảng sạch.

Bằng cách ưa thích của hệ điều hành, tìm kiếm diamonds.png trên máy tính và bạn sẽ tìm thấy file PNG (không bất ngờ) nhưng cũng tìm thấy tập lệnh đã tạo ra nó (diamonds.R). Đây là chiến thắng lớn! Một ngày nào đó, bạn sẽ muốn tạo lại hình hoặc chỉ hiểu nó đến từ đâu. Nếu bạn nghiêm túc lưu hình vào file bằng mã R và không bao giờ bằng chuột hoặc clipboard, bạn sẽ có thể tái tạo công việc cũ dễ dàng!

6.2.4 Đường dẫn tương đối và tuyệt đối

Khi ở bên trong dự án, bạn chỉ nên sử dụng đường dẫn tương đối, không phải đường dẫn tuyệt đối. Sự khác biệt là gì? Đường dẫn tương đối là tương đối với thư mục làm việc, tức là “nhà” của dự án. Khi Hadley viết data/diamonds.csv ở trên, đó là viết tắt của /Users/hadley/Documents/r4ds/data/diamonds.csv. Nhưng quan trọng là, nếu Mine chạy mã này trên máy cô ấy, nó sẽ trỏ đến /Users/Mine/Documents/r4ds/data/diamonds.csv. Đây là lý do đường dẫn tương đối quan trọng: chúng hoạt động bất kể thư mục dự án R ở đâu.

Đường dẫn tuyệt đối trỏ đến cùng vị trí bất kể thư mục làm việc. Chúng trông hơi khác tùy theo hệ điều hành. Trên Windows chúng bắt đầu bằng ký tự ổ đĩa (ví dụ, C:) hoặc hai dấu gạch chéo ngược (ví dụ, \\servername) và trên Mac/Linux chúng bắt đầu bằng dấu gạch chéo “/” (ví dụ, /users/hadley). Bạn không bao giờ nên dùng đường dẫn tuyệt đối trong tập lệnh, vì chúng cản trở việc chia sẻ: không ai khác có cấu trúc thư mục giống hệt bạn.

Có sự khác biệt quan trọng khác giữa các hệ điều hành: cách bạn phân cách các thành phần của đường dẫn. Mac và Linux sử dụng dấu gạch chéo (ví dụ, data/diamonds.csv) và Windows sử dụng dấu gạch chéo ngược (ví dụ, data\diamonds.csv). R có thể hoạt động với cả hai loại (bất kể bạn đang dùng nền tảng nào), nhưng thật không may, dấu gạch chéo ngược có ý nghĩa đặc biệt trong R, và để có một dấu gạch chéo ngược trong đường dẫn, bạn cần gõ hai dấu gạch chéo ngược! Điều đó khiến cuộc sống khó chịu, vì vậy chúng tôi khuyến nghị luôn sử dụng kiểu Linux/Mac với dấu gạch chéo thuận.

6.3 Bài tập

  1. Truy cập tài khoản Twitter RStudio Tips, https://twitter.com/rstudiotips và tìm một mẹo có vẻ thú vị. Thực hành sử dụng nó!

  2. RStudio diagnostics báo cáo những lỗi phổ biến nào khác? Đọc https://support.posit.co/hc/en-us/articles/205753617-Code-Diagnostics để tìm hiểu.

6.4 Tóm tắt

Trong chương này, bạn đã học cách tổ chức mã R trong tập lệnh (file) và dự án (thư mục). Giống như phong cách mã, ban đầu điều này có thể cảm thấy như việc vặt. Nhưng khi bạn tích lũy nhiều mã hơn qua nhiều dự án, bạn sẽ học cách trân trọng việc tổ chức ban đầu có thể tiết kiệm rất nhiều thời gian sau này.

Tóm lại, tập lệnh và dự án mang lại cho bạn workflow vững chắc phục vụ tốt trong tương lai:

  • Tạo một dự án RStudio cho mỗi dự án phân tích dữ liệu.
  • Lưu tập lệnh (với tên mang tính mô tả) trong dự án, chỉnh sửa, chạy từng phần hoặc toàn bộ. Khởi động lại R thường xuyên để đảm bảo bạn đã nắm bắt mọi thứ trong tập lệnh.
  • Chỉ sử dụng đường dẫn tương đối, không sử dụng đường dẫn tuyệt đối.

Sau đó mọi thứ bạn cần đều ở một nơi và được tách biệt rõ ràng khỏi tất cả các dự án khác bạn đang làm.

Cho đến nay, chúng ta đã làm việc với các tập dữ liệu được đóng gói bên trong các package R. Điều này giúp dễ dàng hơn khi thực hành trên dữ liệu đã chuẩn bị sẵn, nhưng rõ ràng dữ liệu của bạn sẽ không có sẵn theo cách này. Vì vậy trong chương tiếp theo, bạn sẽ học cách tải dữ liệu từ đĩa vào phiên R bằng package readr.


  1. Chưa kể rằng bạn đang thách thức số phận khi dùng “final” trong tên 😆 Truyện tranh Piled Higher and Deeper có một mẩu truyện vui về điều này.↩︎

  2. Nếu bạn chưa cài đặt usethis, bạn có thể cài đặt bằng install.packages("usethis").↩︎