3 R Cơ bản

Chào mừng bạn!

Chương này sẽ mô tả những kỹ thuật cơ bản của R. Đây không phải là hướng dẫn sử dụng toàn diện, nhưng sẽ cung cấp những kiến thức cơ bản và có thể hữu ích trong việc làm mới hiểu biết của bạn. Phần Tài nguyên học liệu sẽ liên kết đến những hướng dẫn sử dụng R bao quát hơn.

Các phần của chương này đã được điều chỉnh dưới sự cho phép của Dự án R4Epis.

Xem chương Chuyển đổi sang R để biết các mẹo khi chuyển đổi từ STATA, SAS hoặc Excel sang R.

3.1 Tại sao sử dụng R?

Như đã được công bố trên trang web dự án R, R là một ngôn ngữ và môi trường lập trình cho tính toán và đồ họa thống kê. Nó rất linh hoạt, có khả năng mở rộng và hướng tới cộng đồng.

Chi phí

R được sử dụng miễn phí! Có sự tồn tại mạnh mẽ về đạo đức trong cộng đồng người sử dụng nguồn tài nguyên mở và miễn phí.

Khả năng tái lập

Thực hiện quản lý và phân tích dữ liệu của bạn thông qua một ngôn ngữ lập trình (so sánh với Excel hoặc công cụ khác mà thao tác chính là nhấp chuột/thao tác thủ công) giúp nâng cao khả năng tái lập, giúp phát hiện lỗi dễ dàng hơn và giảm bớt khối lượng công việc của bạn.

Cộng đồng

R có cộng đồng người dùng khổng lồ và có tính hợp tác. Các package và công cụ mới nhằm giải quyết các vấn đề thực tế được phát triển hàng ngày và được kiểm tra bởi cộng đồng người dùng. Ví dụ, R-Ladies là một tổ chức toàn cầu có sứ mệnh thúc đẩy sự đa dạng giới trong cộng đồng R và là một trong những tổ chức người dùng R lớn nhất. Thậm chí có thể có một phần của nhóm này đang ở gần bạn!

3.2 Các thuật ngữ chính

RStudio - RStudio là Giao diện đồ họa người dùng (GUI) giúp sử dụng R dễ dàng hơn. Đọc thêm trong mục RStudio.

Đối tượng - Bao gồm mọi thứ bạn lưu trữ trong R - bộ dữ liệu, biến, danh sách tên làng, quy mô dân số, thậm chí cả các kết quả đầu ra như đồ thị - là các đối tượng được gán têncó thể được tham chiếu trong các lệnh sau này. Đọc thêm trong mục Đối tượng.

Hàm - Mỗi hàm là một code hoạt động mà chấp nhận dữ liệu đầu vào và trả về kết quả đầu ra đã được biến đổi. Đọc thêm trong mục Các hàm.

Packages - Mỗi package R là một gói câu lệnh có khả năng chia sẻ. Đọc thêm trong mục Packages.

Scripts - Mỗi script là một tệp tài liệu chứa các lệnh của bạn. Đọc thêm trong mục Scripts

3.3 Tài nguyên học liệu

Tài nguyên trong RStudio

Tài liệu trợ giúp

Tìm kiếm tab “Help” của RStudio về tài liệu liên quan đến package R và các hàm cụ thể. Tab này nằm trong cửa sổ chứa các tab Files, Plots và Packages (thường ở cửa sổ phía dưới bên phải). Như một lối tắt, bạn cũng có thể nhập tên của một package hoặc câu lệnh vào R Console sau dấu hỏi chấm và không bao gồm dấu ngoặc đơn để mở trang trợ giúp liên quan.

Ví dụ: ?filter hoặc ?diagrammeR.

Các hướng dẫn có sự tương tác

R có thể được học thông qua một số tương tác trong RStudio.

RStudio cung cấp một cửa sổ Tutorial được hỗ trợ bởi package learnr. Chỉ cần cài đặt package này và mở hướng dẫn qua tab “Tutorial” trong cửa sổ RStudio phía trên bên phải (cũng chứa các tab Environment và History).

Package swirl cung cấp các nội dung học tương tác trong R Console. Cài đặt và tải package này, rồi chạy lệnh swirl() (dấu ngoặc đơn trống) trong R Console. Bạn sẽ thấy các thông báo xuất hiện trong cửa sổ Console. Phản hồi bằng cách nhập vào Console. Nó sẽ hướng dẫn bạn qua một nội dung học do bạn lựa chọn.

Cheatsheets

Có rất nhiều “cheatsheets” PDF có sẵn trên trang web của RStudio, ví dụ như:

  • Factors với package forcats
  • Ngày và thời gian với package lubridate
  • Chuỗi với package stringr
  • Các vòng lặp với package purrr
  • Nhập dữ liệu
  • Cheatsheet biến đổi dữ liệu với package dplyr
  • R Markdown (để tạo các tài liệu như PDF, Word, Powerpoint…)
  • Shiny (để xây dựng các ứng dụng web tương tác)
  • Trực quan hóa dữ liệu với package ggplot2
  • Bản đồ học (GIS)
  • Package leaflet (bản đồ tương tác)
  • Python với R (package reticulate)

Đây là tài nguyên R trực tuyến dành riêng cho Người dùng Excel

Twitter

R có một cộng đồng twitter sôi động, nơi bạn có thể tìm hiểu các mẹo, lối tắt và tin tức - hãy theo dõi các tài khoản sau:

Cũng như:

#epitwitter#rstats

Nguồn tài nguyên trực tuyến miễn phí

Cuốn sách R for Data Science (R dành cho Khoa học Dữ liệu) của Garrett Grolemund và Hadley Wickham

Trang web của dự án R4Epis nhằm mục đích “phát triển các công cụ làm sạch, phân tích và báo cáo dữ liệu được chuẩn hóa dùng trong các trường hợp bùng phát dịch phổ biến và các cuộc điều tra dựa trên dân số mà sẽ được tiến hành trong các ứng phó khẩn cấp của Tổ chức Bác sỹ không biên giới” Bạn có thể tìm thấy tài liệu đào tạo cơ bản về R, các mẫu báo cáo RMarkdown và khảo sát về các đợt bùng phát dịch, cũng như các hướng dẫn để giúp bạn thiết lập chúng.

3.4 Cài đặt

R và RStudio

Làm thế nào để cài đặt R

Truy cập vào trang web https://www.r-project.org/ và tải phiên bản mới nhất của R phù hợp với máy tính của bạn.

Làm thế nào để cài đặt RStudio

Truy cập vào trang web https://rstudio.com/products/rstudio/download/ và tải phiên bản Desktop mới nhất của RStudio phù hợp với máy tính của bạn.

Quyền truy cập
Lưu ý rằng bạn nên cài đặt R và RStudio vào một ổ đĩa mà bạn có quyền đọc và ghi lại. Nếu không, khả năng cài đặt các package R (thường xuyên xảy ra) của bạn sẽ bị ảnh hưởng. Nếu bạn gặp sự cố, hãy thử mở RStudio bằng cách nhấp chuột phải vào biểu tượng và chọn “Run as administrator”. Các mẹo khác có thể được tìm thấy trong chương R trên ổ cứng mạng.

Làm thế nào để cập nhật R và RStudio

Phiên bản R của bạn được in ra R Console khi khởi động. Bạn cũng có thể chạy lệnh sessionInfo().

Để cập nhật R, truy cập đến trang web được nhắc đến ở trên và cài đặt lại R. Ngoài ra, bạn có thể sử dụng package installr (trên Windows) bằng cách chạy câu lệnh installr::updateR(). Thao tác này sẽ mở ra các hộp thoại giúp bạn tải xuống phiên bản R mới nhất và cập nhật các package của bạn lên phiên bản R mới. Có thể tìm thấy thêm chi tiết trong tài liệu installr .

Lưu ý rằng phiên bản R cũ sẽ vẫn tồn tại trong máy tính của bạn. Bạn có thể tạm thời chạy phiên bản cũ hơn (“installation” cũ hơn) của R bằng cách nhấp vào “Tools” -> “Global Options” trong RStudio và chọn một phiên bản R. Điều này có thể hữu ích nếu bạn muốn sử dụng một package chưa được cập nhật để hoạt động trên phiên bản R mới nhất.

Để cập nhật RStudio, truy cập đến trang web được nhắc đến ở trên và cài đặt lại RStudio. Một tùy chọn khác là nhấp vào “Help” -> “Check for Updates” trong RStudio, nhưng điều này có thể dẫn đến việc không hiển thị các bản cập nhật mới nhất.

Để xem phiên bản R, RStudio hoặc package nào đã được sử dụng khi viết Sổ tay này, hãy xem chương Biên tập và ghi chú kỹ thuật.

Những phần mềm khác bạn có thể cần cài đặt

  • TinyTeX (để biên dịch tài liệu RMarkdown sang PDF)
  • Pandoc (để biên dịch tài liệu RMarkdown)
  • RTools (để xây dựng các package cho R)
  • phantomjs (để lưu ảnh tĩnh của mạng động, chẳng hạn như chuỗi lây truyền)

TinyTex

TinyTex là một bản phân phối LaTeX tùy chỉnh, hữu ích khi tạo các tệp PDF từ R.
Truy cập https://yihui.org/tinytex/ để tìm hiểu thêm thông tin.

Để cài đặt TinyTex từ R:

install.packages('tinytex')
tinytex::install_tinytex()
# to uninstall TinyTeX, run tinytex::uninstall_tinytex()

Pandoc

Pandoc là một công cụ chuyển đổi văn bản, một phần mềm tách biệt với R. Nó đi kèm với RStudio và không cần phải tải xuống. Nó hỗ trợ quá trình chuyển đổi văn bản từ Rmarkdown sang các định dạng như .pdf và có bổ sung thêm một số tính năng phức tạp.

RTools

RTools là một phần mềm được sử dụng để xây dựng package cho R

Cài đặt từ trang web: https://cran.r-project.org/bin/windows/Rtools/

phantomjs

Phần mềm này thường được sử dụng để chụp “chụp ảnh màn hình” trang web. Ví dụ khi bạn tạo một chuỗi lây truyền với package epicontacts, một tệp HTML có thể tương tác và chuyển động được tạo ra. Nếu bạn muốn có hình ảnh tĩnh, sử dụng package webshot để tự động hóa quá trình này. Việc này sẽ yêu cầu chương trình bên ngoài “phantomjs”. Bạn có thể cài đặt phantomjs thông qua package webshot bằng lệnh webshot::install_phantomjs().

3.5 RStudio

Làm quen

Đầu tiên, mở RStudio. Biểu tượng của chúng có sự tương đồng, hãy chắc chắn bạn đang mở RStudio chứ không phải R.

Để RStudio hoạt động bạn cũng cần phải cài đặt R trên máy tính (xem hướng dẫn cài đặt ở bên trên).

RStudio là một giao diện người dùng (GUI) giúp sử dụng R dễ dàng hơn. Bạn có thể coi R như một động cơ đang đảm đương công việc chính của một phương tiện và RStudio là phần thân của phương tiện (với ghế ngồi, các phụ kiện,…) giúp bạn sử dụng động cơ tiến về phía trước. Bạn có thể xem toàn bộ cheatsheet giao diện người dùng của RStudio (PDF) tại đây

RStudio mặc định hiển thị bốn cửa sổ hình chữ nhật.

MẸO: Nếu RStudio của bạn chỉ hiển thị một cửa sổ bên trái thì đó là do bạn chưa mở scripts nào.

Cửa sổ mã nguồn
Cửa sổ này, mặc định hiển thị phía trên bên trái, là một khoảng trống để chỉnh sửa, chạy và lưu các scripts của bạn. Script chứa các lệnh mà bạn muốn chạy. Cửa sổ này cũng có thể hiển thị thông tin dữ liệu (data frames).

Đối với người dùng Stata, cửa sổ này tương tự với các cửa sổ Do-file và Data Editor.

Cửa sổ R Console

R Console, mặc định ở cửa sổ bên trái hoặc phía dưới bên trái của RStudio, là ngôi nhà của “động cơ” R. Đây là nơi các lệnh thực sự được chạy, các kết quả đầu ra không phải là đồ họa và các thông báo lỗi/cảnh báo sẽ xuất hiện. Bạn có thể nhập và chạy các lệnh trực tiếp trong R Console, nhưng sẽ sớm nhận ra các lệnh này không được lưu như khi chạy lệnh từ một script.

Nếu bạn đã quen thuộc với Stata, R Console giống như cửa sổ Command Window và Results Window.

Cửa sổ Environment
Cửa sổ này, mặc định ở phía trên bên phải, thường được sử dụng để xem tóm tắt ngắn gọn về các đối tượng itrong R Environment ở phiên hiện tại. Các đối tượng này có thể bao gồm các tập dữ liệu đã được nhập, chỉnh sửa hoặc tạo mới, các tham số bạn đã xác định (ví dụ: một tuần dịch tễ cụ thể để phân tích), vectơ hoặc các danh sách bạn đã xác định trong quá trình phân tích (ví dụ: tên các vùng). Bạn có thể nhấp vào mũi tên bên cạnh tên của data frames để xem các biến số của nó.

Cửa sổ này gần giống với cửa sổ Variables Manager trong Stata.

Cửa sổ này cũng chứa History - nơi mà bạn có thể xem các lệnh đã làm trước đó. Nó cũng có một tab “Tutorial” - là nơi mà bạn có thể hoàn thành các hướng dẫn tương tác với R nếu bạn đã cài đặt package learnr. Nó cũng chứa một tab “Connections” cho phép các kết nối bên ngoài và có thể có cửa sổ “Git” nếu bạn chọn giao diện với Github.

Cửa sổ Plots, Viewer, Packages, và Help
Cửa sổ phía dưới bên phải bao gồm một số tab quan trọng. Các đồ họa chính điển hình bao gồm bản đồ sẽ được hiển thị trong Cửa sổ Plot. Các kết quả đầu ra tương tác hoặc HTML sẽ được hiển thị trong cửa sổ Viewer. Cửa sổ File là một trình duyệt có thể được sử dụng để mở hoặc xóa tệp. Cửa sổ Packages cho phép bạn xem, cài đặt, cập nhật, xóa, tải/dỡ các package R và xem bạn có phiên bản package nào. Để tìm hiểu thêm về các package hãy xem mục packages bên dưới.

Cửa sổ này chứa các nội dung tương đương với các cửa sổ Plots Manager và Project Manager trong Stata.

Các cài đặt của RStudio

Thay đổi các cài đặt và giao diện của RStudio trong thanh menu thả xuống Tools, bằng cách chọn Global Options. Ở đó, bạn có thể thay đổi cài đặt mặc định, bao gồm cả màu giao diện/nền.

Khởi động lại

Nếu R của bạn bị treo, bạn có thể khởi động lại R bằng cách di chuột đến menu Session và nhấp vào “Restart R”. Thao tác này giúp tránh rắc rối khi đóng và mở RStudio. Mọi thứ trong môi trường R của bạn sẽ bị xóa khi thực hiện thao tác này.

Các phím tắt

Dưới đây là một vài phím tắt rất hữu dụng. Tất cả các phím tắt cho Windows, Max và Linux nằm ở chương 2 cheatsheet giao diện người dùng của RStudio.

Windows/Linux Mac Hành động
Esc Esc Ngắt lệnh hiện tại (hữu ích nếu bạn vô tình chạy một lệnh chưa hoàn chỉnh và không thể thoát khỏi việc nhìn thấy “+” trong R console)
Ctrl+s Cmd+s Lưu (script)
Tab Tab Tự động điền
Ctrl + Enter Cmd + Enter Chạy (các) dòng/phần code đang được chọn
Ctrl + Shift + C Cmd + Shift + c Bình luận/bỏ bình luận các dòng được đánh dấu
Alt + - Option + - Chèn <-
Ctrl + Shift + m Cmd + Shift + m Chèn %>%
Ctrl + l Cmd + l Dọn dẹp R console
Ctrl + Alt + b Cmd + Option + b Chạy từ đầu đến dòng hiện tại
Ctrl + Alt + t Cmd + Option + t Chạy code chunk hiện tại (R Markdown)
Ctrl + Alt + i Cmd + Shift + r Chèn code chunk (vào R Markdown)
Ctrl + Alt + c Cmd + Option + c Chạy code chunk hiện tại (R Markdown)
up/down arrows in R console Tương tự Chuyển đổi qua các lệnh đã chạy gần đây
Shift + up/down arrows in script Tương tự Chọn nhiều dòng code
Ctrl + f Cmd + f Tìm và thay thế trong script hiện tại
Ctrl + Shift + f Cmd + Shift + f Tìm trong các tệp (tìm/thay thế trên nhiều script)
Alt + l Cmd + Option + l Thu gọn code đã chọn
Shift + Alt + l Cmd + Shift + Option+l Mở rộng code đã chọn

MẸO: Sử dụng phím Tab của bạn khi nhập để sử dụng chức năng tự động hoàn thành của RStudio. Điều này có thể giúp ngăn ngừa các lỗi chính tả. Nhấn Tab trong khi nhập để hiện ra menu thả xuống gồm các hàm và đối tượng có thể có, dựa trên những gì bạn đã nhập.

3.6 Hàm

Các hàm là phần cốt lõi của việc sử dụng R. Hàm là cách bạn thực hiện các tác vụ và hoạt động. Nhiều hàm được cài đặt sẵn với R, nhiều hàm khác sẵn sàng để tải xuống trong các packages (giải thích trong phần packages), và bạn thậm chí có thể viết các hàm tùy chỉnh của riêng mình!

Phần khái niệm cơ bản của hàm giải thích:

  • Thế nào là một hàm và cách mà chúng hoạt động
  • Thế nào là đối số của hàm
  • Làm cách nào để nhận được sự trợ giúp khi tìm hiểu một hàm

Lưu ý nhanh về cú pháp: Trong cuốn sổ tay này, các hàm được viết dưới dạng code văn bản với dấu mở ngoặc đơn như sau: filter(). Như đã giải thích trong phần packages, các hàm được tải xuống có sẵn trong các packages. Trong sổ tay này, tên các package được in đậm, ví dụ như dplyr. Đôi khi trong code ví dụ, bạn có thể thấy tên hàm được liên kết rõ ràng với tên package của chính hàm đó bằng hai dấu hai chấm (::) như thế này: dplyr::filter(). Mục đích của việc liên kết này sẽ được giải thích trong phần package.

Các hàm cơ bản

Một hàm giống như một cỗ máy nhận các dữ liệu đầu vào, thực hiện một số thao tác với dữ liệu đó và sản xuất kết quả đầu ra. Kết quả đầu ra như thế nào phụ thuộc vào hàm mà bạn sử dụng.

Các hàm thường hoạt động dựa trên các đối tượng được đặt trong dấu ngoặc đơn của hàm. Ví dụ, hàm sqrt() tính căn bậc hai của một số:

sqrt(49)
## [1] 7

Đối tượng được dùng cho một hàm cũng có thể là một cột trong tập dữ liệu (xem phần Đối tượng để biết chi tiết về tất cả các loại đối tượng). Vì R có thể lưu trữ nhiều tập dữ liệu, bạn sẽ cần xác định cả tập dữ liệu và cột. Một cách để làm điều này là sử dụng ký hiệu $ để liên kết tên của tập dữ liệu và tên của cột (dataset$column). Trong ví dụ dưới đây, hàm summary() được áp dụng cho cột age trong tập dữ liệu linelist, và kết quả đầu ra là bản tóm tắt các giá trị số và giá trị missing của cột.

# Print summary statistics of column 'age' in the dataset 'linelist'
summary(linelist$age)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##    0.00    6.00   13.00   16.07   23.00   84.00      86

LƯU Ý: Đằng sau một hàm là hệ thống code bổ sung phức tạp đã được gói gọn cho người dùng thành một lệnh đơn giản.

Hàm với nhiều đối số

Các hàm thường yêu cầu một số dữ liệu đầu vào, được gọi là đối số, đặt trong dấu ngoặc đơn của hàm, thường được phân tách bằng dấu phẩy.

  • Một vài đối số là bắt buộc để hàm hoạt động chính xác, những đối số khác là tùy chọn
  • Những đối số tùy chọn có thiết lập mặc định
  • Các đối số có thể nhận ký tự, số, logic (TRUE / FALSE) và các dữ liệu đầu vào khác

Dưới đây là một hàm giả định thú vị, được gọi là oven_bake(), là ví dụ về một hàm điển hình. Hàm này nhận một đối tượng đầu vào (ví dụ: một tập dữ liệu, hoặc trong ví dụ này là “bột”) và thực hiện các hoạt động được xác định bởi các đối số bổ sung (minutes = and temperature =). Kết quả đầu ra có thể được in ra cửa sổ console hoặc được lưu dưới dạng một đối tượng bằng cách sử dụng toán tử gán <-.

Trong một ví dụ thực tế hơn, hàm age_pyramid() dưới đây tạo một biểu đồ tháp tuổi dựa trên nhóm tuổi đã xác định và cột phân tách nhị phân, ví dụ như giới tính. Hàm được cung cấp bởi ba đối số trong dấu ngoặc đơn và được phân tách nhau bằng dấu phẩy. Các giá trị được cung cấp cho các đối số thiết lập linelist là dataframe được sử dụng, age_cat5 là cột để đếm và giới tính là cột nhị phân để sử dụng chia kim tự tháp theo màu.

# Create an age pyramid
age_pyramid(data = linelist, age_group = "age_cat5", split_by = "gender")

Lệnh trên có thể được viết tương tự như bên dưới, theo cách dài hơn với một dòng mới cho mỗi đối số. Phong cách này có thể dễ đọc và dễ viết “bình luận” hơn với # để giải thích từng phần (bình luận mở rộng là một thực hành tốt!). Để chạy lệnh dài hơn này, bạn có thể bôi đen toàn bộ lệnh và nhấp vào “Run” hoặc chỉ cần đặt con trỏ vào dòng đầu tiên rồi nhấn đồng thời phím Ctrl và phím Enter.

# Create an age pyramid
age_pyramid(
  data = linelist,        # use case linelist
  age_group = "age_cat5", # provide age group column
  split_by = "gender"     # use gender column for two sides of pyramid
  )

Không cần xác định nửa đầu của phép gán đối số (ví dụ: data =) nếu các đối số được viết theo một thứ tự cụ thể (được chỉ định trong tài liệu của hàm). Đoạn code dưới đây tạo ra cùng một kim tự tháp như ở trên, bởi vì hàm kì vọng thứ tự đối số là: data frame, biến age_group, biến split_by.

# This command will produce the exact same graphic as above
age_pyramid(linelist, "age_cat5", "gender")

Một lệnh age_pyramid() phức tạp hơn có thể bao gồm các đối số tùy chọn để:

  • Hiển thị tỷ lệ thay vì số lượng (đặt proportional = TRUE khi giá trị mặc định là FALSE)
  • Chỉ định hai màu để sử dụng (pal = là viết tắt của “bảng màu” và được cung cấp với một vectơ gồm hai tên màu. Xem chương đối tượng để biết cách hàm c() tạo ra một vectơ)

LƯU Ý: Đối với các đối số mà bạn xác định với cả hai phần của đối số (ví dụ: proportional = TRUE), thứ tự của chúng trong tất cả các đối số không quan trọng.

age_pyramid(
  linelist,                    # use case linelist
  "age_cat5",                  # age group column
  "gender",                    # split by gender
  proportional = TRUE,         # percents instead of counts
  pal = c("orange", "purple")  # colors
  )

Viết hàm

R là một ngôn ngữ được định hướng xung quanh hàm, vì thế bạn nên cảm thấy được trao quyền để tự viết các hàm của riêng mình. Việc tạo ra hàm mang đến một vài lợi thế:

  • Tạo điều kiện thuận lợi cho lập trình mô-đun - tách code thành các phần độc lập và có thể quản lý
  • Thay thế việc copy-and-paste lặp đi lặp lại, điều mà có thể dễ xảy ra lỗi
  • Đặt tên dễ nhớ cho các đoạn code

Cách viết một hàm được trình bày cụ thể trong chương Viết hàm.

3.7 Packages

Packages chứa các hàm.

Một package trong phần mềm R là một gói code và các tài liệu hướng dẫn có thể chia sẻ được chứa các hàm được định nghĩa trước. Cộng đồng người dùng phần mềm R luôn phát triển những package giúp giải quyết các vấn đề cụ thể, điều này có thể sẽ giúp bạn trong công việc của mình! Bạn sẽ có thể cần cài đặt và sử dụng hàng trăm package trong quá trình sử dụng phần mềm R.

Khi cài đặt, R đã có sẵn các package và hàm “cơ bản” giúp thực hiện các nhiệm vụ đơn giản. Nhưng nhiều người dùng R tạo ra các hàm chuyên biệt, được cộng đồng R kiểm chứng và bạn có thể tải xuống dưới dạng package để sử dụng theo cách của riêng mình. Trong sách này, tên package được viết in đậm. Một trong những khía cạnh thách thức hơn cả của R đó là thường có nhiều hàm hoặc package để lựa chọn nhằm hoàn thành một nhiệm vụ nhất định.

Cài đặt và Gọi

Các hàm được chứa trong packages có thể được tải (“cài đặt”) về máy tính của bạn từ internet. Khi một package được tải xuống, package đó sẽ được lưu trữ trong “thư viện” của bạn. Sau đó, bạn có thể truy cập các hàm mà nó chứa trong phiên làm việc hiện tại trên R của bạn bằng cách “Gọi” package.

Hãy coi R là thư viện cá nhân của bạn: Khi bạn tải xuống một package, thư viện của bạn nhận được một cuốn sách mới gồm các hàm, nhưng mỗi lần bạn muốn sử dụng một hàm trong cuốn sách đó, bạn phải mượn (“gọi”) cuốn sách đó từ thư viện của mình.

Tóm lại: để sử dụng các hàm có sẵn trong package R, phải thực hiện 2 bước:

  1. Package phải được cài đặt (một lần),
  2. Package phải được gọi (trong mỗi phiên làm việc của R)

Thư viện của bạn

“Thư viện” của bạn thực ra là một thư mục trên máy tính của bạn, bao gồm các thư mục chứa các package đã được cài đặt. Hãy tìm nơi R được cài đặt trong máy tính của bạn và tìm kiếm một thư mục có tên “win-library”. Ví dụ: R\win-library\4.0 (4.0 là phiên bản R - bạn sẽ có các thư viện khác nhau tùy theo phiên bản R mà bạn đã tải xuống).

Bạn có thể in ra đường dẫn tệp đến thư viện của mình bằng cách gõ lệnh .libPaths() (dấu ngoặc bỏ trống). Điều này trở nên đặc biệt quan trọng nếu làm việc với R trên ổ cứng mạng.

Cài đặt từ CRAN

Thông thường, người dùng R tải các package xuống từ CRAN. CRAN (Comprehensive R Archive Network - Mạng lưu trữ R toàn diện) là một kho công cộng trực tuyến gồm các package R đã được xuất bản bởi các thành viên cộng đồng R.

Bạn có cần lo lắng về vi-rút và bảo mật khi tải xuống một package từ CRAN? Đọc bài viết sau để hiểm thêm về chủ đề này.

Làm thế nào để cài đặt và gọi

Trong sách này, chúng tôi khuyên bạn nên sử dụng package pacman (viết tắt của “package manager”). Nó cung cấp một hàm thuận tiện p_load() mà sẽ cài đặt một package nếu cần gọi nó để sử dụng trong phiên làm việc hiện tại.

Cú pháp khá đơn giản. Chỉ cần liệt kê tên của các package trong dấu ngoặc đơn của hàm p_load() và phân tách chúng bằng dấu phẩy. Lệnh dưới đây sẽ cài đặt các package sau rio, tidyverse, và here nếu chúng chưa được cài đặt và sẽ gọi chúng ra để sử dụng. Điều này làm cho cách tiếp cận p_load() trở nên thuận tiện và ngắn gọn nếu chia sẻ scripts với người khác. Lưu ý rằng tên package có phân biệt chữ hoa chữ thường.

# Install (if necessary) and load packages for use
pacman::p_load(rio, tidyverse, here)

Lưu ý rằng chúng ta đã sử dụng cú pháp pacman::p_load() để viết rõ ràng tên package (pacman) trước tên hàm (p_load()), được nối với nhau bằng hai dấu hai chấm ::. Cú pháp này tiện dụng vì nó cũng gọi package pacman (giả sử package này đã được cài đặt).

Ngoài ra còn có các hàm base R thay thế mà bạn sẽ gặp thường xuyên. Hàm base R để cài đặt một package là install.packages(). Tên của package muốn cài đặt phải được đặt trong dấu ngoặc đơn bên trong dấu ngoặc kép. Nếu bạn muốn cài đặt nhiều package trong một lệnh, chúng phải được liệt kê trong một vectơ dạng ký tự c().

Lưu ý: lệnh này cài đặt một package, nhưng không gọi nó ra để sử dụng trong phiên làm việc hiện tại.

# install a single package with base R
install.packages("tidyverse")

# install multiple packages with base R
install.packages(c("tidyverse", "rio", "here"))

Việc cài đặt cũng có thể được thực hiện bằng cách chọn và nhấp chuột vào cửa sổ RStudio “Package” và chọn “Install”, sau đó tìm kiếm tên package mong muốn cài đặt.

Hàm base R để gọi một package ra sử dụng (sau khi nó đã được cài đặt) là library(). Hàm này chỉ có thể gọi một package tại một thời điểm (cách khác của lệnh p_load()). Bạn có thể nhập tên package có hoặc không có dấu ngoặc kép.

# load packages for use, with base R
library(tidyverse)
library(rio)
library(here)

Để kiểm tra xem một package đã được cài đặt và/hoặc đã được gọi hay chưa, bạn có thể xem Cửa số Package trong RStudio. Nếu package được cài đặt, nó sẽ hiển thị ở đó với số phiên bản. Nếu checkbox của nó được đánh dấu nghĩa là nó đã được gọi cho phiên làm việc hiện tại.

Cài đặt từ Github

Đôi khi, bạn cần cài đặt một package chưa có sẵn từ CRAN. Hoặc có lẽ package đã có sẵn trên CRAN nhưng bạn muốn phiên bản mới hơn với các tính năng mới chưa được cung cấp trong phiên bản cũ. Chúng thường được lưu trữ trên trang web github.com trong một “kho lưu trữ (repository)” code công khai và miễn phí. Đọc thêm về Github trong chương Version control với Git và Github.

Để download packages R từ Github, bạn có thể dụng hàm p_load_gh() từ pacman, hàm này sẽ cài đặt package nếu cần và gọi nó để sử dụng cho phiên làm việc R hiện tại. Cách khác để cài đặt bao gồm sử dụng package remotes hoặc devtools. Đọc thêm về các hàm của pacman tại Tài liệu về package.

Để cài đặt từ Github, bạn phải cung cấp thêm các thông tin sau:

  1. Github ID của chủ sở hữu
  2. Tên của repository chứa package
  3. (Tùy chọn) Tên của “nhánh” (phiên bản phát triển cụ thể) mà bạn muốn tải xuống

Trong các ví dụ dưới đây, từ đầu tiên trong dấu ngoặc kép là Github ID của chủ sở hữu kho lưu trữ, sau dấu gạch chéo là tên của kho lưu trữ (tên của package).

# install/load the epicontacts package from its Github repository
p_load_gh("reconhub/epicontacts")

Nếu bạn muốn cài đặt từ một “nhánh” (phiên bản) khác với nhánh chính, hãy thêm tên nhánh sau dấu “@”, được đặt phía sau tên kho lưu trữ.

# install the "timeline" branch of the epicontacts package from Github
p_load_gh("reconhub/epicontacts@timeline")

Nếu không có sự khác biệt giữa phiên bản Github và phiên bản trên máy tính của bạn, bạn không cần thực hiện thao tác này. Thay vào đó, bạn có thể “buộc” phải cài đặt lại bằng cách sử dụng p_load_current_gh() với đối số update = TRUE. Đọc thêm về pacman tại Minh họa trực tuyến

Cài đặt từ ZIP hoặc TAR

Bạn có thể cài đặt package từ một URL:

packageurl <- "https://cran.r-project.org/src/contrib/Archive/dsr/dsr_0.2.2.tar.gz"
install.packages(packageurl, repos=NULL, type="source")

Hoặc, tải xuống máy tính của bạn dưới dạng tệp nén:

Cách 1: sử dụng lệnh install_local() từ package remotes

remotes::install_local("~/Downloads/dplyr-master.zip")

Cách 2: sử dụng lệnh install.packages() của base R, cung cấp đường dẫn tệp đến tệp ZIP và thiết lập type = "sourcerepos = NULL.

install.packages("~/Downloads/dplyr-master.zip", repos=NULL, type="source")

Cú pháp code

Để tăng sự tường minh trong cuốn sách này, các hàm đôi khi sẽ được đặt sau tên package của chúng bằng cách sử dụng ký hiệu :: theo cách sau: package_name::function_name()

Khi một package được gọi cho một phiên làm việc, việc làm này là không cần thiết. Bạn chỉ cần sử dụng function_name(). Tuy nhiên, việc viết tên package sẽ hữu ích khi một tên hàm phổ biến và có thể tồn tại trong nhiều package (ví dụ: plot()). Việc viết tên package sẽ giúp gọi package trong trường hợp nó chưa được gọi ra.

# This command uses the package "rio" and its function "import()" to import a dataset
linelist <- rio::import("linelist.xlsx", which = "Sheet1")

Trợ giúp về hàm

Để đọc thêm thông tin về một hàm, bạn có thể tìm kiếm hàm đó trong cửa sổ Help của RStudio nằm ở góc dưới bên phải. Hoặc bạn cũng có thể chạy một lệnh chẳng hạn như ?thefunctionname (đặt tên của hàm sau dấu chấm hỏi) và trang Trợ giúp sẽ xuất hiện trong cửa sổ Help. Cuối cùng, hãy thử tìm kiếm trên internet.

Cập nhật packages

Bạn có thể cập nhật các packages bằng cách cài đặt lại chúng. Bạn cũng có thể bấm vào nút “Update” màu xanh lá cây trong cửa sổ packages của RStudio để xem packages nào có phiên bản mới để cài đặt. Lưu ý rằng code cũ của bạn có thể cần được cập nhật nếu có một bản sửa đổi lớn về cách hoạt động của một hàm!

Xóa packages

Sử dụng p_delete() từ pacman, hoặc remove.packages() từ base R. Ngoài ra, hãy tìm thư mục chứa thư viện của bạn và xóa thư mục theo cách thủ công.

Sự phụ thuộc

Các packages thường phụ thuộc vào các packages khác để hoạt động. Chúng được gọi là sự phụ thuộc. Nếu một package không cài đặt được, thì package phụ thuộc vào nó có khả năng cũng không thể cài đặt được.

Xem sự phụ thuộc của một package với lệnh p_depends(), và xem package nào phụ thuộc vào nó với p_depends_reverse()

Hàm bị che giấu

Không có gì lạ nếu hai hoặc nhiều packages chứa cùng một tên hàm. Ví dụ: packages dplyr có hàm filter(), nhưng package stats cũng vậy. Hàm filter() mặc định phụ thuộc vào thứ tự các package này được gọi lên trong phiên làm việc R - packages được gọi ra sau sẽ là mặc định cho hàm filter().

Bạn có thể kiểm tra thứ tự của chúng trong cửa sổ Environment của R Studio - nhấp vào menu thả xuống “Global Environment” và xem thứ tự của các packages. Các hàm thuộc các packages ở vị trí thấp hơn trong danh sách thả xuống đó sẽ che giấu các hàm cùng tên trong các packages xuất hiện ở vị trí bên trên trong danh sách thả xuống. Khi bạn vừa gọi một package, R sẽ cảnh báo bạn trong bảng điều khiển nếu xảy ra hiện tượng này, nhưng điều này rất hay bị bỏ quên.

Dưới đây là những cách bạn có thể sửa lỗi hàm bị che giấu:

  1. Ghi rõ tên package trong lệnh. Ví dụ, sử dụng dplyr::filter()
  2. Sắp xếp lại thứ tự mà các package được tải (ví dụ trong p_load()), và bắt đầu một phiên làm việc R mới

Gỡ package

Để gỡ (detach) một package, hãy sử dụng lệnh dưới đây, với tên package chính xác và chỉ có một dấu hai chấm. Lưu ý rằng điều này có thể không giải quyết được việc hàm bị che giấu.

detach(package:PACKAGE_NAME_HERE, unload=TRUE)

Cài đặt phiên bản cũ hơn

Xem hướng dẫn này để cài đặt phiên bản cũ hơn của một package cụ thể.

Packages đề xuất

Xem chương Package đề xuất để biết danh sách các packages thường được sử dụng trong dịch tễ học.

3.8 Scripts

Scripts là một phần cơ bản của lập trình. Chúng là các tài liệu chứa các câu lệnh của bạn (ví dụ: các hàm để tạo và chỉnh sửa bộ số liệu, các hàm để in các biểu đồ trực quan hóa số liệu, v.v.). Bạn có thể lưu một scripts và chạy lại sau này. Có nhiều lợi ích để lưu trữ và chạy các lệnh của bạn từ một scripts (so với nhập “từng lệnh” vào R console):

  • Tiện dụng - bạn có thể chia sẻ công việc của mình với người khác bằng cách gửi cho họ các tập lệnh của bạn
  • Khả năng tái lập - để bạn và những người khác biết chính xác những gì bạn đã làm
  • Kiểm soát phiên bản - để bạn có thể theo dõi các thay đổi do chính bạn hoặc đồng nghiệp thực hiện
  • Dễ dàng nhận xét/chú thích - để giải thích cho đồng nghiệp của bạn những gì bạn đã làm

Bình luận

Khi viết script, bạn có thể thêm các chú thích (“bình luận”) xung quanh code R của bạn. Bình luận là cần thiết để giải thích cho chính bạn và những người đọc khác hiểu những gì bạn đang làm. Bạn có thể thêm bình luận bằng cách nhập dấu thăng (#) và viết bình luận của bạn sau đó. Nội dung bình luận sẽ xuất hiện với màu khác với code R.

Bất kỳ code nào được viết sau dấu # sẽ không được chạy. Do đó, đặt dấu # trước dòng code cũng là một cách hữu ích để tạm thời vô hiệu hóa một dòng code (“comment out”) nếu bạn không muốn xóa nó). Bạn có thể comment out/in nhiều dòng cùng một lúc bằng cách bôi đen chúng và nhấn Ctrl + Shift + c (Cmd + Shift + c trong Mac).

# A comment can be on a line by itself
# import data
linelist <- import("linelist_raw.xlsx") %>%   # a comment can also come after code
# filter(age > 50)                          # It can also be used to deactivate / remove a line of code
  count()
  • Bình luận những gì bạn đang làm tại sao bạn làm như vậy.
  • Chia code của bạn thành các phần hợp lý
  • Kèm theo code của bạn với mô tả từng bước về những gì đang được thực hiện (ví dụ: các bước được đánh số)

Phong cách viết code

Phong cách viết code của bạn rất quan trọng - đặc biệt là khi làm việc theo nhóm. Chúng tôi khuyên bạn nên tuân theo hướng dẫn phong cách viết code tidyverse . Bên cạnh đó còn có các packages khác như stylerlintr để giúp bạn tuân theo phong cách này.

Một vài điểm rất cơ bản để làm cho code của bạn dễ dàng đọc được đối với người khác:
* Khi đặt tên cho các đối tượng, chỉ sử dụng các chữ cái viết thường, số và dấu gạch dưới _, ví dụ: my_data
* Thường xuyên sử dụng dấu cách, bao gồm cả xung quanh các toán tử, ví dụ: n = 1age_new <- age_old + 3

Ví dụ về Script

Dưới đây là một ví dụ về một đoạn ngắn R script. Hãy nhớ rằng, bạn càng giải thích ngắn gọn lệnh code của mình trong phần bình luận, thì đồng nghiệp của bạn sẽ càng thích bạn!

R markdown

R markdown là một dạng của R script và có khả năng xuất thành các tệp đầu ra (PDF, Word, HTML, Powerpoint, v.v.). Đây là những công cụ vô cùng hữu ích và linh hoạt thường được sử dụng để tạo các báo cáo tự động. Ngay cả trang web và cuốn sách này cũng được viết bằng R markdown!

Bạn cần biết rằng những người mới bắt đầu dùng R cũng có thể sử dụng R Markdown - do đó đừng sợ! Để tìm hiểu thêm, hãy xem chương Báo cáo với R Markdown trong cuốn sách này.

R notebooks

Không có sự khác biệt trong cách viết giữa R markdown và R notebook. Tuy nhiên, việc thực thi của hai loại file này hơi khác nhau một chút. Xem trang Web này để biết thêm chi tiết.

Shiny

Shiny apps/websites được chứa trong một script có tên app.R. Tệp này có ba thành phần:

  1. Giao diện người dùng (ui)
  2. Một hàm máy chú
  3. Một lệng gọi hàm shinyApp

Xem thêm trong cuốn sách này tại chương Dashboards với Shiny, hoặc hướng dẫn trực tuyến này: Shiny tutorial

Trước đây, tệp bên trên được chia thành 2 tệp con (ui.Rserver.R)

Thu gọn Code

Bạn có thể thu gọn các đoạn code để làm cho script của bạn dễ đọc hơn.

Để làm điều này, hãy tạo tiêu đề văn bản bằng dấu thăng #, viết tiêu đề của bạn và thêm vào phía sau nó ít nhất hoặc là 4 dấu gạch ngang (-), dấu thăng (#) hoặc dấu bằng (=). Ngay sau đó, một mũi tên nhỏ sẽ xuất bên cạnh ở bên phải số thự tự của dòng lệnh. Bạn có thể nhấp vào mũi tên này và phần code bên dưới sẽ được thu gọn cho đến trước tiêu đề tiếp theo và một mũi tên hai chiều xuất hiện ở đây.

Để mở rộng lại đoạn code đã thu gọn, hãy nhấp lại vào mũi tên hoặc biểu tượng mũi tên hai chiều. Ngoài ra còn có thể sử dụng thêm các phím tắt như đã được giải thích trong mục RStudio của chương này.

Bằng cách tạo tiêu đề bằng #, bạn cũng sẽ kích hoạt Mục lục ở cuối tập lệnh của mình (xem bên dưới) mà bạn có thể sử dụng để điều hướng tập lệnh của mình. Bạn có thể tạo tiêu đề phụ bằng cách thêm các ký hiệu #, ví dụ: # # cho tiêu đề chính, ## fcho tiêu đề thứ hai, và ### cho tiêu đề thứ ba.

Dưới đây là hai phiên bản của một ví dụ cho script. Ở bên trái là bản gốc với các tiêu đề được chú thích. Ở bên phải, bốn dấu gạch ngang đã được viết sau mỗi tiêu đề, làm cho chúng có thể thu gọn được. Hai trong số chúng đã được thu gọn và bạn có thể thấy Mục lục ở dưới cùng hiện hiển thị từng phần.

Các phần code khác mặc định đủ điều kiện để thu gọn bao gồm các phần “nằm giữa” hai dấu ngoặc nhọn { }, chẳng hạn như định nghĩa hàm hoặc các khối điều kiện (câu lệnh if else). Bạn có thể đọc thêm về cách thu gọn code tại trang của Rstudio.

3.9 Thư mục làm việc

Thư mục làm việc là vị trí thư mục gốc được R sử dụng cho công việc của bạn - nơi R tìm kiếm và lưu các tệp theo mặc định. Mặc định là, R sẽ lưu các tệp mới và xuất tệp vào vị trí này, đồng thời sẽ tìm kiếm các tệp để nhập dữ liệu (ví dụ: bộ dữ liệu) tại đây.

Thư mục làm việc xuất hiện bằng dòng chữ màu xám ở phía trên cửa sổ Rstudio Console. Bạn cũng có thể in thư mục làm việc hiện tại bằng cách chạy lệnh getwd() (để trống dấu ngoặc đơn).

Gợi ý cách tiếp cận

Xem thêm tại chương Dự án R để biết chi tiết về gợi ý các cách tiếp cận của chúng tôi trong việc quản lý thư mục làm việc của bạn.
Một cách phổ biến, hiệu quả và không gặp sự cố khi quản lý thư mục làm việc và đường dẫn tệp là kết hợp 3 yếu tố này trong một quy trình làm việc với Dự án R có định hướng :

  1. Một dự án R để lưu trữ tất cả tệp của bạn (xem chương Dự án R)
  2. Package here để định vị tệp (xem chương Nhập xuất dữ liệu)
  3. Packge rio để nhập/xuất tệp (xem chương Nhập xuất dữ liệu)

Thiết lập bằng lệnh

Cho tới gần đây, nhiều người học R đã được dạy để bắt đầu script của họ bằng lệnh setwd(). Hãy thay đổi thói quen đó bằng cách sử dụng Dự án R và đọc thêm tài liệu sau để hiểu lý do không nên sử dụng setwd(). Một cách ngắn gọn là, công việc của bạn chỉ thực hiện được trên máy tính của bạn, các đường dẫn tệp được sử dụng để nhập và xuất tệp trở nên “dễ lỗi” và điều này cản trở nghiêm trọng đến việc cộng tác và sử dụng code của bạn trên bất kỳ máy tính nào khác. Bạn có những lựa chọn khác dễ dàng hơn!

Như đã nói ở trên, mặc dù chúng tôi không khuyến nghị phương pháp này trong hầu hết các trường hợp, bạn vẫn có thể sử dụng lệnh setwd() với đường dẫn tệp thư mục mong muốn trong dấu ngoặc kép, ví dụ:

setwd("C:/Documents/R Files/My analysis")

NGUY HIỂM: thiết lập một thư mục làm việc với setwd() có thể dẫn đến “lỗi” nếu đường dẫn tệp dành riêng cho một máy tính. Thay vào đó, hãy sử dụng đường dẫn tệp liên quan đến thư mục gốc Dự án R (với package here).

Thiết lập thủ công

Để thiết lập thư mục làm việc một cách thủ công (trỏ và nhấp tương đương với setwd()), hãy chọn mục Session trên thanh công cụ và chọn “Set Working Directory”, sau đó chọn “Choose Directory”. Chú ý: nếu sử dụng phương pháp này, bạn sẽ phải thực hiện việc này theo cách thủ công mỗi khi mở RStudio.

Thiết lập bên trong một dự án R

Nếu bạn đang mở một dự án R, thư mục làm việc sẽ mặc định là thư mục gốc của dự án R có chứa tệp “.rproj”. Điều này sẽ áp dụng nếu bạn mở RStudio bằng cách nhấp vào mở R Project (tệp có phần mở rộng “.rproj”).

Thư mục làm việc với R markdown

Trong script ở R markdown, thư mục làm việc mặc định là thư mục chứa tệp R markdown (.Rmd). Nếu sử dụng dự án R và package here, điều này sẽ không được áp dụng. Để biết thư mục làm việc là gì, sử dụng lệnh here() như đã được giải thích tại chương Dự án R.

Nếu bạn muốn thay đổi thư mục làm việc của một tệp độc lập ở R markdown (không phải ở dự án R), nếu bạn sử dụng setwd() điều này sẽ chỉ áp dụng chỉ cho đoạn code đó. Để thực hiện thay đổi cho tất cả các đoạn code trong R markdown, hãy điều chỉnh ở bước thiết lập để thêm tham số root.dir =, như bên dưới:

knitr::opts_knit$set(root.dir = 'desired/directorypath')

Cách này dễ hơn nhiều so với chỉ sử dụng R markdown bên trong một dự án R và sử dụng package here.

Cung cấp đường dẫn tệp

Có lẽ điều khiến những người mới bắt đầu với R cảm thấy nản nhất (ít nhất là với người dùng máy tính Windows) đó là gõ đường dẫn tệp để nhập xuất dữ liệu. Chúng tôi có giải thích cặn kẽ về cách tạo đường dẫn tệp đầu vào tốt nhất trong chương Nhập xuất dữ liệu, nhưng dưới đây là một số điểm chính:

Đường dẫn tệp bị lỗi

Dưới đây là ví dụ về đường dẫn tệp “tuyệt đối” hoặc “địa chỉ đầy đủ”. Chúng có thể bị lỗi nếu được sử dụng bởi một máy tính khác. Một ngoại lệ là nếu bạn đang sử dụng ổ đĩa chia sẻ/mạng.

C:/Users/Name/Document/Analytic Software/R/Projects/Analysis2019/data/March2019.csv  

Đường dẫn với dấu gạch chéo

Nếu nhập đường dẫn tệp, hãy lưu ý hướng của các dấu gạch chéo. Sử dụng dấu gạch chéo xuôi (/) để tách các thành phần (“data/provincial.csv”). Đối với người dùng Windows, cách mặc định mà đường dẫn tệp được hiển thị là dấu gạch chéo ngược (\) - vì vậy bạn sẽ cần phải thay đổi hướng của mỗi dấu gạch chéo. Nếu bạn sử dụng package here được miêu tả ở Dự án R thì dấu gạch chéo không còn là vấn đề với bạn nữa.

Đường dẫn tệp tương đối

Nói chung, chúng tôi khuyên bạn nên cung cấp các đường dẫn tệp theo cách “tương đối” - nghĩa là, đường dẫn liên quan đến thư mục gốc Dự án R của bạn. Bạn có thể thực hiện việc này bằng cách sử dụng package here như được giải thích trong chương Dự án R. Một đường dẫn tệp tương đối sẽ trông như thế này:

# Import csv linelist from the data/linelist/clean/ sub-folders of an R project
linelist <- import(here("data", "clean", "linelists", "marin_country.csv"))

Ngay cả khi sử dụng đường dẫn tệp tương đối trong dự án R, bạn vẫn có thể sử dụng đường dẫn tuyệt đối để nhập/xuất dữ liệu ở bên ngoài dự án R của bạn.

3.10 Đối tượng

Mọi thứ trong R đều là một đối tượng, và R là một ngôn ngữ “lập trình hướng đối tượng”. Các phần dưới đây sẽ giải thích:

  • Cách tạo ra các đối tượng (<-)
  • Các loại đối tượng (ví dụ: data frames, vectors..)
  • Cách truy cập các tập con của đối tượng (ví dụ: các biến số trong một bộ dữ liệu)
  • Các loại đối tượng (ví dụ: numeric, logical, integer, double, character, factor)

Mọi thứ đều là một đối tượng

Phần này được dựa theo sách R4Epis project.
Mọi thứ bạn lưu trữ trong R - bao gồm bộ dữ liệu, biến số, danh sách tên làng, tổng số dân, thậm chí cả kết quả đầu ra như biểu đồ - đều là các đối tượng, được gán têncó thể được tham chiếu trong các lệnh sau đó.

Một đối tượng tồn tại khi bạn đã gán giá trị cho nó (xem phần gán bên dưới). Khi nó được gán một giá trị, đối tượng sẽ xuất hiện trong cửa sổ Environment (xem cửa sổ phía trên bên phải của RStudio). Sau đó, nó có thể được sử dụng, thao tác, thay đổi và định nghĩa lại.

Định nghĩa một đối tượng (<-)

Tạo ra một đối tượng bằng cách gán cho chúng một giá trị bằng toán tử <-.
Bạn có thể nghĩ về toán tử gán <- tương đương với từ “được định nghĩa là”. Các lệnh gán thường tuân theo một trật tự quy định:

tên đối tượng <- giá trị của đối tượng (hoặc quy trình / tính toán tạo ra giá trị)

Ví dụ: bạn muốn ghi nhận một báo cáo tuần dịch tễ học hiện tại dưới dạng một đối tượng để tham chiếu tới code của bạn sau này. Trong ví dụ này, đối tượng current_week được tạo khi nó được gán giá trị "2018-W10" (dấu ngoặc kép sẽ quy định đây là giá trị dạng chữ). Đối tượng current_week sẽ xuất hiện trong cửa sổ RStudio Environment (phía trên bên phải) và có thể được tham chiếu tới các lệnh sau này.

Xem các lệnh R và kết quả của chúng như dưới đây.

current_week <- "2018-W10"   # this command creates the object current_week by assigning it a value
current_week                 # this command prints the current value of current_week object in the console
## [1] "2018-W10"

CHÚ Ý: Lưu ý rằng số [1] trong kết quả ở R console đơn giản là chỉ ra rằng bạn đang xem mục đầu tiên của đầu ra

THẬN TRỌNG: Giá trị của một đối tượng có thể bị ghi đè bất kỳ lúc nào bằng cách chạy lệnh gán để định nghĩa lại giá trị của nó. Do đó, thứ tự của các lệnh được chạy rất quan trọng.

Lệnh sau sẽ định nghĩa lại giá trị của đối tượng current_week:

current_week <- "2018-W51"   # assigns a NEW value to the object current_week
current_week                 # prints the current value of current_week in the console
## [1] "2018-W51"

Dấu bằng =

Bạn cũng sẽ thấy các dấu bằng trong R code:

  • Hai dấu bằng == giữa hai đối tượng hoặc giá trị dùng để đặt một câu hỏi logic: “cái này có bằng cái kia không?”.
  • Bạn cũng sẽ thấy các dấu bằng trong các hàm được sử dụng để xác định giá trị của các đối số của hàm (đọc thêm ở các phần bên dưới), ví dụ: max(age, na.rm = TRUE).
  • Bạn có thể sử dụng một dấu bằng = thay cho dấu <- để tạo và định nghĩa các đối tượng, nhưng điều này không được khuyến khích. Bạn có thể đọc về lý do tại sao điều này không được khuyến khích ở đây.

Bộ dữ liệu

Bộ dữ liệu (datasets) cũng là một đối tượng (thường là một “dataframes”) và phải được gán tên khi chúng được nhập. Trong đoạn mã dưới đây, đối tượng linelist được tạo và gán giá trị từ tệp CSV, tệp này được nhập bằng package rio và hàm import() của package này.

# linelist is created and assigned the value of the imported CSV file
linelist <- import("my_linelist.csv")

Bạn có thể đọc thêm về nhập và xuất dữ liệu trong chương Nhập xuất dữ liệu.

THẬN TRỌNG: Lưu ý nhanh về cách đặt tên đối tượng:

  • Tên đối tượng không được chứa dấu cách, nhưng bạn nên sử dụng dấu gạch dưới (_) hoặc dấu chấm (.) thay vì dấu cách.
  • Tên đối tượng phân biệt chữ hoa và chữ thường (nghĩa là Dataset_A khác với dataset_A).
  • Tên đối tượng phải bắt đầu bằng chữ cái (không được bắt đầu bằng số như 1, 2 hoặc 3).

Kết quả đầu ra

Các kết quả đầu ra như bảng và biểu đồ cung cấp một ví dụ về cách các kết quả đầu ra có thể được lưu dưới dạng đối tượng hoặc chỉ được in ra mà không cần lưu. Ví dụ, một bảng chéo giữa giới tính và biến kết cục được tạo ra bởi hàm table() trong base R, có thể được in trực tiếp vào R console (mà không cần lưu).

# printed to R console only
table(linelist$gender, linelist$outcome)
##    
##     Death Recover
##   f  1227     953
##   m  1228     950

Nhưng bảng này cũng có thể được lưu dưới dạng một đối tượng được đặt tên. Sau đó, bạn có thể in nó ra.

# save
gen_out_table <- table(linelist$gender, linelist$outcome)

# print
gen_out_table
##    
##     Death Recover
##   f  1227     953
##   m  1228     950

Cột

Các cột trong tập dữ liệu cũng là các đối tượng và có thể được định nghĩa, ghi đè và tạo như được mô tả bên dưới trong phần Cột.

Bạn có thể sử dụng toán tử gán từ base R để tạo một cột mới. Dưới đây, cột mới bmi (Body Mass Index) được tạo, và giá trị mới ứng với mỗi hàng là kết quả của một phép toán trên giá trị của các hàng trong cột wt_kg và cột ht_cm.

# create new "bmi" column using base R syntax
linelist$bmi <- linelist$wt_kg / (linelist$ht_cm/100)^2

Tuy nhiên, trong cuốn sách này, chúng tôi tập trung vào một cách tiếp cận khác để định nghĩa cột, sử dụng hàm mutate() trong package dplyrpiping với toán tử pipe (%>%). Cú pháp dễ đọc hơn và có những ưu điểm khác đã được giải thích trong cuốn sách này ở chương Làm sạch số liệu và các hàm quan trọng. Bạn có thể đọc thêm về piping trong phần Piping phía bên dưới.

# create new "bmi" column using dplyr syntax
linelist <- linelist %>% 
  mutate(bmi = wt_kg / (ht_cm/100)^2)

3.10.1 Cấu trúc đối tượng

Các đối tượng có thể là một phần dữ liệu đơn lẻ (ví dụ: my_number <- 24), hoặc chúng có thể bao gồm dữ liệu có cấu trúc.

Hình ảnh dưới đây được tham khảo từ hướng dẫn R trực tuyến này. Nó cho thấy một số cấu trúc dữ liệu phổ biến và tên của chúng. Hình ảnh này không bao gồm dữ liệu không gian. Bạn có thể xem thêm về dữ liệu không gian tại chương GIS cơ bản.

Trong dịch tễ học (và đặc biệt là dịch tễ học thực địa), bạn sẽ thường xuyên phải tiếp xúc với data frames và vectors:

Cấu trúc thường gặp Giái thích Ví dụ
Vectors Một vùng chứa cho một chuỗi các đối tượng đơn lẻ, tất cả đều thuộc cùng một loại (e.g. số, chữ). “Biến” (Cột) trong dữ liệu là vectors (ví dụ: cột age_years).
Data Frames Vectors (ví dụ: các cột) được liên kết với nhau mà tất cả đều có cùng số hàng. `linelist` là một data frame.

Lưu ý rằng để tạo một vectơ “độc lập” (mà không phải là một phần của data frame), hàm c() được sử dụng để kết hợp các phần tử khác nhau. Ví dụ: nếu tạo một vectơ màu sắc thang màu của biểu đồ: vector_of_colors <- c("blue", "red2", "orange", "grey")

Kiểu đối tượng

Tất cả các đối tượng được lưu trữ trong R đều có một kiểu dữ liệu cho biết cách nó được xử lý. Có nhiều kiểu đối tượng, nhưng những kiểu phổ biến bao gồm:

Kiểu Giải thích Ví dụ
Ký tự Là các chữ/từ/câu được đặt “trong dấu ngoặc kép”. Đối tượng kiểu ký tự thì không thể tính toán “Những ký tự nằm trong dấu ngoặc kép”
Số nguyên Các số nguyên (không có phần thập phân) -5, 14, hoặc 2000
Số thực Bao gồm các số nguyên và có thể bao gồm phần thập phân. Nếu trong dấu ngoặc kép, chúng sẽ được coi là dạng ký tự 23.1 hoặc 14
Factor Đây là các vector có trật tự xác định hoặc các giá trị có nhiều danh mục Biến số của tình trạng kinh tế với các giá trị theo tứ tự
Ngày tháng Khi R được thông báo rằng một dữ liệu ở dạng ngày tháng R, những dữ liệu này có thể được thao tác và hiển thị theo những cách đặc biệt. Xem thêm về biến ngày tháng tại chương Làm việc với ngày tháng. 2018-04-12 hoặc 15/3/1954 hoặc Wed 4 Jan 1980
Logic Giá trị của biến chỉ có thể là hai giá trị đặc biệt sau TRUE hoặc FALSE (lưu ý đây không phải là “TRUE” và”FALSE” trong dấu ngoặc kép) TRUE hoặc FALSE
data.frame Một data.frame trong R lưu trữ một tập dữ liệu điển hình. Data.frame bao gồm các vector (cột) dữ liệu được liên kết với nhau, tất cả chúng đều có cùng một số lượng quan sát (hàng). Tập dữ liệu mẫu AJS có tên là linelist_rawchứa 68 biến với 300 quan sát (mỗi hàng)
tibble tibbles là một dạng khác của data.frame, sự khác biệt chính là tibble in đẹp hơn trong R console (hiển thị 10 hàng đầu tiên và chỉ các cột vừa với màn hình) data frame, danh sách, hoặc ma trận có thể chuyển đổi thành tibble bằng hàm as_tibble()
Danh sách Một danh sách giống như một vector, nhưng chứa các đối tượng có kiểu khác nhau Một danh sách có thể chứa một số duy nhất, một data.frame, một vector và thậm chí một danh sách khác bên trong nó!

Bạn có thể kiểm tra kiểu của một đối tượng bằng cách cung cấp tên của nó tới hàm class(). Lưu ý: bạn có thể tham chiếu một cột cụ thể trong tập dữ liệu bằng cách sử dụng ký hiệu $ để phân tách tên của tập dữ liệu và tên của cột.

class(linelist)         # class should be a data frame or tibble
## [1] "data.frame"
class(linelist$age)     # class should be numeric
## [1] "numeric"
class(linelist$gender)  # class should be character
## [1] "character"

Đôi khi, một cột sẽ được tự động chuyển đổi thành một kiểu khác bởi R. Hãy coi chừng điều này! Ví dụ: nếu bạn có một vectơ hoặc cột kiểu số, nhưng một giá trị ký tự được chèn vào … thì toàn bộ cột sẽ thay đổi thành kiểu ký tự.

num_vector <- c(1,2,3,4,5) # define vector as all numbers
class(num_vector)          # vector is numeric class
## [1] "numeric"
num_vector[3] <- "three"   # convert the third element to a character
class(num_vector)          # vector is now character class
## [1] "character"

Một ví dụ phổ biến của điều này là khi thao tác với một data frame để in bảng - nếu bạn tạo một hàng tính tổng và cố gắng dán /gắn phần trăm với số trong cùng một ô (ví dụ: 23 (40%)), toàn bộ cột dạng số ở trên sẽ chuyển đổi thành ký tự và không còn có thể được sử dụng cho các phép tính toán học nữa.

Đôi khi, bạn sẽ cần chuyển đổi các đối tượng hoặc cột sang một loại khác.

Hàm Chức năng
as.character() Chuyển sang kiểu ký tự
as.numeric() Chuyển sang kiểu số
as.integer() Chuyển sang kiểu số nguyên
as.Date() Chuyển sang kiểu ngày tháng - Chú ý: Xem mục Ngày tháng để biết thêm chi tiết
factor() Chuyển sang kiểu factor - Chú ý: nếu muốn định nghĩa lại thứ tự của các giá trị trong biến factor thì cần thêm các đối số bổ sung

Tương tự như vậy, một số hàm base R có thể kiểm tra xem một đối tượng CÓ thuộc của một kiểu dữ liệu cụ thể nào hay không, chẳng hạn như is.numeric(), is.character(), is.double(), is.factor(), is.integer()

Bạn có thể tham khảo một tài liệu trực tuyến về các kiểu và cấu trúc dữ liệu trong R tại đây.

Cột / Biến số ($)

Một cột trong data frame về mặt kỹ thuật là một “vector” (xem bảng ở trên) - bao gồm một chuỗi các giá trị cùng loại (ký tự, số, lôgic, v.v.).

Một vectơ có thể tồn tại độc lập với một data frame, ví dụ: vectơ tên cột mà bạn muốn đưa vào làm biến giải thích trong mô hình. Để tạo một vectơ “độc lập”, hãy sử dụng hàm c() như dưới đây:

# define the stand-alone vector of character values
explanatory_vars <- c("gender", "fever", "chills", "cough", "aches", "vomit")

# print the values in this named vector
explanatory_vars
## [1] "gender" "fever"  "chills" "cough"  "aches"  "vomit"

Các cột trong data frame cũng là vectơ và có thể được gọi, tham chiếu, trích xuất hoặc tạo bằng ký hiệu $. Ký hiệu $ kết nối tên của cột với tên của data frame tương ứng. Trong cuốn sách này, chúng tôi cố gắng sử dụng từ “cột” thay vì “biến số”.

# Retrieve the length of the vector age_years
length(linelist$age) # (age is a column in the linelist data frame)

Bằng cách nhập tên của một dataframe, theo sau bởi ký tự $, bạn sẽ thấy menu gợi ý của tất cả các tên cột trong dataframe. Bạn có thể di chuyển giữa các cột bằng phím mũi tên, chọn cột bằng phím Enter để tránh lỗi chính tả!

MẸO NÂNG CAO: Một số đối tượng phức tạp hơn (ví dụ: một danh sách hoặc đối tượng epicontacts) có thể có nhiều cấp độ có thể được truy cập thông qua nhiều ký tự đô la. Ví dụ: epicontacts$linelist$date_onset

Truy cập / indexing đối tượng bằng dấu ngoặc vuông ([ ])

Khi cần xem một phần của đối tượng, còn được gọi là “indexing”, bạn có thể sử dụng dấu ngoặc vuông [ ]. Sử dụng $ trên dataframe để truy cập một cột cũng là một kiểu indexing.

my_vector <- c("a", "b", "c", "d", "e", "f")  # define the vector
my_vector[5]                                  # print the 5th element
## [1] "e"

Dấu ngoặc vuông cũng hoạt động để xem các phần cụ thể trong kết quả đầu ra, chẳng hạn như đầu ra của hàm summary():

# All of the summary
summary(linelist$age)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
##    0.00    6.00   13.00   16.07   23.00   84.00      86
# Just the second element of the summary, with name (using only single brackets)
summary(linelist$age)[2]
## 1st Qu. 
##       6
# Just the second element, without name (using double brackets)
summary(linelist$age)[[2]]
## [1] 6
# Extract an element by name, without showing the name
summary(linelist$age)[["Median"]]
## [1] 13

Dấu ngoặc vuông cũng hoạt động trên data frames để xem các hàng và cột cụ thể. Bạn có thể thực hiện việc này bằng cú pháp dataframe[rows, columns]:

# View a specific row (2) from dataset, with all columns (don't forget the comma!)
linelist[2,]

# View all rows, but just one column
linelist[, "date_onset"]

# View values from row 2 and columns 5 through 10
linelist[2, 5:10] 

# View values from row 2 and columns 5 through 10 and 18
linelist[2, c(5:10, 18)] 

# View rows 2 through 20, and specific columns
linelist[2:20, c("date_onset", "outcome", "age")]

# View rows and columns based on criteria
# *** Note the dataframe must still be named in the criteria!
linelist[linelist$age > 25 , c("date_onset", "outcome", "age")]

# Use View() to see the outputs in the RStudio Viewer pane (easier to read) 
# *** Note the capital "V" in View() function
View(linelist[2:20, "date_onset"])

# Save as a new object
new_table <- linelist[2:20, c("date_onset")] 

Lưu ý rằng bạn cũng có thể indexing hàng / cột trong một data frames và tibbles bằng cách sử dụng cú pháp của package dplyr (hàm filter() đối với hàng, và select() đối với cột). Đọc thêm về các hàm quan trọng này trong chương Làm sạch số liệu và các hàm quan trọng.

Để lọc dựa trên “số thứ tự hàng”, bạn có thể sử dụng hàm row_number()trong package dplyr với dấu ngoặc đơn mở như một phần của biểu thức lọc logic. Thường thì bạn sẽ sử dụng toán tử %in% và một khoảng giá trị số như một phần của câu lệnh logic đó, như được trình bày dưới đây. Để xem N hàng đầu tiên, bạn cũng có thể sử dụng hàm head() của package dplyr.

# View first 100 rows
linelist %>% head(100)

# Show row 5 only
linelist %>% filter(row_number() == 5)

# View rows 2 through 20, and three specific columns (note no quotes necessary on column names)
linelist %>% filter(row_number() %in% 2:20) %>% select(date_onset, outcome, age)

Khi indexing một đối tượng chứa một danh sách bằng một dấu ngoặc vuông sẽ luôn trả về kiểu danh sách, ngay cả khi chỉ một đối tượng được trả về . Tuy nhiên, hai dấu ngoặc vuông có thể được sử dụng để truy cập một phần tử đơn lẻ đối và trả về một kiểu không phải là một danh sách.
Dấu ngoặc vuông cũng có thể được viết sau nhau, như được minh họa bên dưới.

Bạn có thể xem một giải thích trực quan về việc indexing với ví dụ về hộp lắc hạt tiêu tại đây, rất hài hước và hữu ích.

# define demo list
my_list <- list(
  # First element in the list is a character vector
  hospitals = c("Central", "Empire", "Santa Anna"),
  
  # second element in the list is a data frame of addresses
  addresses   = data.frame(
    street = c("145 Medical Way", "1048 Brown Ave", "999 El Camino"),
    city   = c("Andover", "Hamilton", "El Paso")
    )
  )

Đây là cách mà một danh sách được in trong R console. Có hai phần tử được đặt tên:

  • hospitals, một vector chứa ký tự
  • addresses, một data frame chứa các địa chỉ
my_list
## $hospitals
## [1] "Central"    "Empire"     "Santa Anna"
## 
## $addresses
##            street     city
## 1 145 Medical Way  Andover
## 2  1048 Brown Ave Hamilton
## 3   999 El Camino  El Paso

Dưới đây là các phương pháp indexing mà bạn có thể sử dụng:

my_list[1] # this returns the element in class "list" - the element name is still displayed
## $hospitals
## [1] "Central"    "Empire"     "Santa Anna"
my_list[[1]] # this returns only the (unnamed) character vector
## [1] "Central"    "Empire"     "Santa Anna"
my_list[["hospitals"]] # you can also index by name of the list element
## [1] "Central"    "Empire"     "Santa Anna"
my_list[[1]][3] # this returns the third element of the "hospitals" character vector
## [1] "Santa Anna"
my_list[[2]][1] # This returns the first column ("street") of the address data frame
##            street
## 1 145 Medical Way
## 2  1048 Brown Ave
## 3   999 El Camino

Xóa đối tượng

Bạn có thể xóa từng đối tượng riêng lẻ khỏi cửa sổ R environment bằng cách để tên của đối tượng cần xóa vào trong hàm rm() (không có dấu ngoặc kép):

rm(object_name)

Bạn có thể xóa tất cả các đối tượng (xóa không gian làm việc của bạn) bằng cách chạy:

rm(list = ls(all = TRUE))

3.11 Piping (%>%)

Hai cách tiếp cận chung để làm việc với các đối tượng là:

  1. Pipes/tidyverse - pipes chuyển một đối tượng từ hàm này sang hàm khác - tập trung vào hành động chứ không phải đối tượng
  2. Xác định đối tượng trung gian - một đối tượng được xác định lại nhiều lần - tập trung vào đối tượng

Pipes

Giải thích một cách đơn giản, toán tử pipe (%>%) chuyển một đầu ra trung gian từ hàm này sang hàm tiếp theo.
Hiểu đơn giản pipe nghĩa là “sau đó”. Nhiều hàm có thể được liên kết với nhau bằng toán tử %>%.

  • Piping nhấn mạnh một chuỗi các hành động, không phải đối tượng mà các hành động đang áp dụng
  • Pipes được áp dụng tốt nhất khi một chuỗi hành động phải được thực hiện trên một đối tượng
  • Pipes đến từ package magrittr, và đã tự động được thêm vào packages dplyrtidyverse
  • Pipes làm cho code sạch hơn, dễ đọc hơn và trực quan hơn

Đọc thêm về cách tiếp cận này trong package tidyverse tại đây Hướng dẫn

Đây là một ví dụ mô phỏng dùng để so sánh, sử dụng các hàm hư cấu để “nướng bánh”. Đầu tiên, phương pháp pipe:

# A fake example of how to bake a cake using piping syntax

cake <- flour %>%       # to define cake, start with flour, and then...
  add(eggs) %>%   # add eggs
  add(oil) %>%    # add oil
  add(water) %>%  # add water
  mix_together(         # mix together
    utensil = spoon,
    minutes = 2) %>%    
  bake(degrees = 350,   # bake
       system = "fahrenheit",
       minutes = 35) %>%  
  let_cool()            # let it cool down

Đây là một link khác mô tả công dụng của pipe.

Piping không phải là một hàm trong base R. Để sử dụng piping, package magrittr phải được cài đặt và gọi ra trong phiên làm việc hiện tại (điều này thường được thực hiện bằng cách gọi package tidyverse hoặc dplyr). Bạn có thể đọc thêm về piping trong tài liệu magrittr.

Lưu ý rằng cũng giống như các lệnh R khác, các pipes có thể được sử dụng để hiển thị kết quả hoặc lưu/lưu lại một đối tượng, tùy thuộc vào toán tử <- được code như thế nào. Xem hai ví dụ dưới đây:

# Create or overwrite object, defining as aggregate counts by age category (not printed)
linelist_summary <- linelist %>% 
  count(age_cat)
# Print the table of counts in the console, but don't save it
linelist %>% 
  count(age_cat)
##   age_cat    n
## 1     0-4 1095
## 2     5-9 1095
## 3   10-14  941
## 4   15-19  743
## 5   20-29 1073
## 6   30-49  754
## 7   50-69   95
## 8     70+    6
## 9    <NA>   86

%<>%

Đây là một “assignment pipe (pipe dùng để gán)” từ package magrittr, package này sẽ pipe một đối tượng theo chiều tiến lên và cũng tái định nghĩa lại đối tượng. Đối tượng cần đứng đầu trong chuỗi pipe. Nó nhanh hơn sử dụng pipe thông thường. Hai lệnh dưới đây là tương đương với nhau:

linelist <- linelist %>%
  filter(age > 50)

linelist %<>% filter(age > 50)

Định nghĩa đối tượng trung gian

Cách tiếp cận này dùng để thay đổi đối tượng/dataframes sẽ phát huy hiệu quả nếu:

  • Bạn cần thao tác trên nhiều đối tượng
  • Các bước trung gian có ý nghĩa cụ thể và xứng đáng tạo các tên đối tượng riêng biệt

Các nguy cơ:

  • Tạo đối tượng mới cho mỗi bước có nghĩa là bạn sẽ tạo thêm rất nhiều đối tượng. Nếu bạn sử dụng không cẩn thận, bạn có thể dễ dàng bị nhầm lẫn!
  • Đặt thêm nhiều tên cho nhiều đối tượng có thể gây nhầm lẫn
  • Nếu có lỗi thì không dễ để phát hiện

Đặt tên cho từng đối tượng trung gian hoặc ghi đè lên đối tượng gốc hoặc kết hợp tất cả hàm với nhau đều đi kèm với những rủi ro.

Dưới đây vẫn là ví dụ mô phỏng quy trình làm “bánh” tương tự như trên, nhưng sử dụng phong cách này:

# a fake example of how to bake a cake using this method (defining intermediate objects)
batter_1 <- left_join(flour, eggs)
batter_2 <- left_join(batter_1, oil)
batter_3 <- left_join(batter_2, water)

batter_4 <- mix_together(object = batter_3, utensil = spoon, minutes = 2)

cake <- bake(batter_4, degrees = 350, system = "fahrenheit", minutes = 35)

cake <- let_cool(cake)

Kết hợp tất cả các hàm với nhau - câu lệnh rất khó đọc:

# an example of combining/nesting mutliple functions together - difficult to read
cake <- let_cool(bake(mix_together(batter_3, utensil = spoon, minutes = 2), degrees = 350, system = "fahrenheit", minutes = 35))

3.12 Các toán tử và hàm chính

Mục này sẽ trình bày chi tiết các toán tử trong R, chẳng hạn như :

  • Toán tử định nghĩa
  • Toán tử quan hệ (nhỏ hơn, bằng nhau..)
  • Toán tử logic (và, hoặc..)
  • Xử lý missing
  • Các toán tử và hàm toán học (+/-, >, sum(), median(), …)
  • Toán tử %in%

Toán tử gán

<-

Toán tử gán cơ bản trong R là <-. Chẳng hạn như object_name <- value.
Toán tử gán này cũng có thể được viết là =. Chúng tôi khuyên bạn nên sử dụng <-.
Bạn nên sử dụng dấu cách trong khi viết code với toán tử gán để dễ đọc hơn.

<<-

Khi Viết hàm, hoặc khi sử dụng R với scipt nguồn, thì bạn có thể cần sử dụng toán tử gán này <<- (từ base R). Toán tử này được sử dụng để định nghĩa một đối tượng trong một hàm lồng trong một hàm khác. Xem thêm tại nguồn tham khảo online này.

%<>%

Đây là một “pipe gán” từ package magrittr, package này sẽ gán một đối tượng theo chiều tiến lên và cũng định nghĩa lại đối tượng. Pipe gán phải là toán tử đầu tiên trong chuỗi pipe code. Đây là cách viết ngắn gọn, như được trình bày dưới đây là hai ví dụ tương đương với nhau:

linelist <- linelist %>% 
  mutate(age_months = age_years * 12)

Đoạn code bên trên tương đương với code dưới đây:

linelist %<>% mutate(age_months = age_years * 12)

%<+%

Toán tử này được sử dụng dể thêm dữ liệu vào Cây phả hệ với package ggtree. Xem thêm chương Cây phả hệ hoặc Sách online này.

Toán tử quan hệ và logic

Toán tử quan hệ so sánh các giá trị và thường được sử dụng khi định nghĩa các biến mới và tập con của bộ dữ liệu. Dưới đây là các toán tử quan hệ phổ biến trong R:

Ý nghĩa Toán tử Ví dụ Kết quả đầu ra của ví dụ
Bằng == "A" == "a" FALSE (vì R phân biệt chữ hoa chữ thường) Lưu ý rằng == (hai dấu bằng) khác với = (một dấu bằng), một dấu bằng hoạt động tương tự với toán tử gán <-
Không bằng != 2 != 0 TRUE
Lớn hơn > 4 > 2 TRUE
Nhỏ hơn < 4 < 2 FALSE
Lớn hơn hoặc bằng >= 6 >= 4 TRUE
Nhỏ hơn hoặc bằng <= 6 <= 4 FALSE
Giá trị bị missing is.na() is.na(7) FALSE (Xem thêm chương Dữ liệu Missing)
Giá trị không missing !is.na() !is.na(7) TRUE

Các toán tử logic, chẳng hạn như AND và OR, thường được sử dụng để kết nối các quan hệ và tạo ra các điều kiện phức tạp hơn. Các biểu thức phức tạp có thể yêu cầu dấu ngoặc đơn () để phân nhóm và thứ tự áp dụng.

Ý nghĩa Toán tử
AND &
OR | (thanh dọc)
Dấu ngoặc đơn ( ) Được sử dụng để nhóm các tiêu chí lại với nhau và làm rõ thứ tự hoạt động

Ví dụ: chúng ta có một số liệu có tên linelist với hai biến mà chúng tôi muốn sử dụng để minh họa, hep_e_rdt: kết quả xét nghiệm và other_cases_in_hh: những trường hợp khác trong gia đình. Lệnh dưới đây sử dụng hàm case_when() để tạo biến mới case_def như sau:

linelist_cleaned <- linelist %>%
  mutate(case_def = case_when(
    is.na(rdt_result) & is.na(other_case_in_home)            ~ NA_character_,
    rdt_result == "Positive"                                 ~ "Confirmed",
    rdt_result != "Positive" & other_cases_in_home == "Yes"  ~ "Probable",
    TRUE                                                     ~ "Suspected"
  ))
Điều kiện trong ví dụ ở trên Giá trị kết quả trong biến mới “case_def”
Nếu giá trị của biến rdt_resultother_cases_in_home bị missing NA (missing)
Nếu giá trị trong rdt_result là “Positive” “Confirmed”
Nếu giá trị trong rdt_result KHÔNG phải là “Positive” VÀ giá trị trong other_cases_in_home là “Yes” “Probable”
Nếu một trong các tiêu chí trên không được đáp ứng “Suspected”

Lưu ý rằng R có phân biệt chữ hoa chữ thường, vì vậy “Positive” khác với “positive”…

Giá trị Missing

Trong R, giá trị missing được biểu diễn bằng giá trị đặc biệt NA (giá trị “dành riêng cho missing”) (chữ N và A viết hoa - không nằm trong dấu ngoặc kép). Nếu dữ liệu bạn nhập vào R bị missing theo cách khác (ví dụ: 99, “Missing”, or .), bạn có thể sẽ cần phải mã hóa lại các giá trị đó thành NA. Cách thực hiện việc này được đề cập trong chương Nhập xuất dữ liệu.

Để kiểm tra xem một giá trị có phải là NA hay không, sử dụng hàm đặc biệt is.na(), kết quả sẽ trả về TRUE hoặc FALSE.

rdt_result <- c("Positive", "Suspected", "Positive", NA)   # two positive cases, one suspected, and one unknown
is.na(rdt_result)  # Tests whether the value of rdt_result is NA
## [1] FALSE FALSE FALSE  TRUE

Đọc thêm về missing, vô hạn, NULL, và các giá trị không thể trong chương Dữ liệu Missing. Tìm hiểu thêm cách chuyển đổi các giá trị bị missing khi nhập dữ liệu trong chương Nhập xuất dữ liệu.

Toán học và thống kê

Tất cả các toán tử và hàm trong chương này đều có sẵn bằng cách sử dụng base R.

Toán tử toán học

Chúng thường được sử dụng để thực hiện phép cộng, phép chia, để tạo cột mới, v.v. Dưới đây là các toán tử toán học phổ biến trong R. Việc bạn có đặt dấu cách xung quanh các toán tử hay không là không quan trọng.

Mục đích Ví dụ trong R
phép cộng 2 + 3
phép trừ 2 - 3
phép nhân 2 * 3
phép chia 30 / 5
số mũ 2^3
thứ tự hoạt động ( )

Các hàm toán học

Mục tiêu Hàm
làm tròn round(x, digits = n)
làm tròn janitor::round_half_up(x, digits = n)
làm tròn lên ceiling(x)
làm tròn xuống floor(x)
giá trị tuyệt đối abs(x)
căn bậc hai sqrt(x)
số mũ exponent(x)
logarit tự nhiên log(x)
logarit cơ số 10 log10(x)
logarit cơ số 2 log2(x)

lưu ý: sử dụng hàm round()digits = để xác định số chữ số thập phân được hiển thị. Sử dụng hàm signif() để làm tròn đến số chữ số nhất định.

Ký hiệu khoa học

Khả năng ký hiệu khoa học được sử dụng phụ thuộc vào giá trị của scipen.

Từ tài liệu hướng dẫn của ?options: scipen được áp dụng khi quyết định in các giá trị số theo ký hiệu cố định hoặc hàm mũ. Giá trị dương thuộc về ký hiệu cố định còn giá trị âm thuộc về ký hiệu khoa học: ký hiệu cố định sẽ luôn được ưu tiên trừ khi có nhiều chữ số ‘scipen’.

Nếu như có rất nhiều số bé cần hiển thị (vd: số 0), mặc định tính năng này sẽ “được bật”. Để “tắt” tính năng ký hiệu khoa học trong phiên làm việc của bạn, hãy thiết lập nó với một số rất lớn, ví dụ:

# turn off scientific notation
options(scipen=999)

Làm tròn

NGUY HIỂM: Hàm round() sử dụng “cách làm tròn của ngân hàng” nghĩa là chỉ làm tròn với số .5 nếu số được làm tròn lên là số chẵn. Sử dụng hàm round_half_up() từ package janitor để thống nhất cách làm tròn với giá trị .5. Xem thêm giải thích sau đây

# use the appropriate rounding function for your work
round(c(2.5, 3.5))
## [1] 2 4
janitor::round_half_up(c(2.5, 3.5))
## [1] 3 4

Các hàm thống kê

CẨN TRỌNG: Các hàm sau đây sẽ mặc định bao gồm cả giá trị missing khi tính toán. Giá trị missing sẽ trả về kết quả đầu ra chứa NA, trừ khi đối số na.rm = TRUE được xác định khi viết hàm. Nó cũng có thể viết ngắn gọn thành na.rm = T.

Mục đích Hàm
trung bình mean(x, na.rm=T)
trung vị median(x, na.rm=T)
độ lệch chuẩn sd(x, na.rm=T)
phân vị* quantile(x, probs)
tổng sum(x, na.rm=T)
giá trị nhỏ nhất min(x, na.rm=T)
giá trị lớn nhất max(x, na.rm=T)
khoảng giá trị số range(x, na.rm=T)
tóm tắt** summary(x)

Notes:

  • *quantile(): x là vectơ số cần khảo sát, và probs = là một vectơ số với các xác suất nằm giữa 0 và 1.0, ví dụ c(0.5, 0.8, 0.85)
  • **summary(): trả về tóm tắt một vectơ số bao gồm giá trị trung bình, trung vị, và các khoảng phân vị thường gặp

NGUY HIỂM: Nếu cung cấp một vectơ số cho một trong các hàm trên, hãy đảm bảo các số được đặt trong hàm c() .

# If supplying raw numbers to a function, wrap them in c()
mean(1, 6, 12, 10, 5, 0)    # !!! INCORRECT !!!  
## [1] 1
mean(c(1, 6, 12, 10, 5, 0)) # CORRECT
## [1] 5.666667

Một số hàm hữu ích khác

Mục đích Hàm Ví dụ
Tạo chuỗi số liên tục seq(from, to, by) seq(1, 10, 2)
lặp x, n lần rep(x, ntimes) rep(1:3, 2) or rep(c("a", "b", "c"), 3)
chia nhỏ một vectơ số cut(x, n) cut(linelist$age, 5)
lấy một mẫu ngẫu nhiên sample(x, size) sample(linelist$id, size = 5, replace = TRUE)

%in%

Một toán tử rất hữu ích để nhanh chóng đánh giá xem một giá trị có nằm trong một vectơ hoặc một dataframe hay không.

my_vector <- c("a", "b", "c", "d")
"a" %in% my_vector
## [1] TRUE
"h" %in% my_vector
## [1] FALSE

Để truy vấn một giá trị không %in% một vectơ, hãy đặt dấu chấm than (!) phía trước biểu thức logic:

# to negate, put an exclamation in front
!"a" %in% my_vector
## [1] FALSE
!"h" %in% my_vector
## [1] TRUE

%in% sẽ rất hữu dụng khi dùng hàm case_when() của package dplyr. Bạn có thể định nghĩa một vectơ trước đó, sau đó tham chiếu đến nó. ví dụ:

affirmative <- c("1", "Yes", "YES", "yes", "y", "Y", "oui", "Oui", "Si")

linelist <- linelist %>% 
  mutate(child_hospitaled = case_when(
    hospitalized %in% affirmative & age < 18 ~ "Hospitalized Child",
    TRUE                                      ~ "Not"))

Lưu ý: Nếu bạn muốn phát hiện một phần của chuỗi, có lẽ việc sử dụng hàm str_detect() từ package stringr, sẽ không chấp nhận một vectơ ký tự kiểu như c("1", "Yes", "yes", "y"). Thay vào đó, nó cần được cung cấp dưới dạng một biểu thức chính quy - một chuối cô đọng với thanh dọc cho phép so sánh OR, chẳng hạn như “1|Yes|yes|y”. Ví dụ, str_detect(hospitalized, "1|Yes|yes|y"). Xem thêm chương Ký tự và chuỗi để biết thêm chi tiết.

Bạn có thể chuyển đổi một vectơ ký tự thành một biểu thức chính quy được đặt tên bằng lệnh này:

affirmative <- c("1", "Yes", "YES", "yes", "y", "Y", "oui", "Oui", "Si")
affirmative
## [1] "1"   "Yes" "YES" "yes" "y"   "Y"   "oui" "Oui" "Si"
# condense to 
affirmative_str_search <- paste0(affirmative, collapse = "|")  # option with base R
affirmative_str_search <- str_c(affirmative, collapse = "|")   # option with stringr package

affirmative_str_search
## [1] "1|Yes|YES|yes|y|Y|oui|Oui|Si"

3.13 Lỗi và cảnh báo

Phần này giải thích:

  • Sự khác biệt giữa lỗi và cảnh báo
  • Mẹo cú pháp chung để viết code R
  • Trợ giúp viết code

Các lỗi thường gặp và cảnh báo cũng như mẹo khắc phục sự cố có thể được tìm thấy trong chương Các lỗi thường gặp.

Lỗi và Cảnh báo

Khi một lệnh được thực thi, cửa sổ R Console có thể hiển thị cho bạn cảnh báo hoặc thông báo lỗi bằng văn bản màu đỏ.

  • Một cảnh báo nghĩa là R đã hoàn thành lệnh của bạn, nhưng phải thực hiện các bước bổ sung hoặc tạo ra kết quả bất thường mà bạn cần lưu ý.

  • Một lỗi nghĩa là R không thể hoàn thành lệnh của bạn.

Tìm manh mối:

  • Thông báo lỗi/cảnh báo thường sẽ bao gồm số dòng xảy ra sự cố.

  • Nếu một đối tượng “không xác định được (is unknown)” hoặc “không tìm thấy (not found)”, có lẽ bạn đã viết sai chính tả, quên gọi một package bằng hàm library(), hoặc quên chạy lại tập lệnh của bạn sau khi thực hiện các thay đổi.

Nếu vẫn thất bại, hãy sao chép thông báo lỗi vào Google cùng với một số từ khóa chính - rất có thể ai đó cũng đã gặp lỗi này rồi!

Mẹo cú pháp chung

Một số điều cần nhớ khi viết lệnh trong R, để tránh lỗi và cảnh báo:

  • Luôn đóng dấu ngoặc đơn - mẹo: đếm số lần mở dấu ngoặc đơn “(” và đóng dấu ngoặc đơn “)” cho mỗi đoạn mã
  • Tránh để khoảng trắng trong tên cột và đối tượng. Thay vào đó, hãy sử dụng dấu gạch dưới (_) hoặc dấu chấm (.)
  • Theo dõi và nhớ tách các đối số của hàm bằng dấu phẩy
  • R phân biệt chữ hoa và chữ thường, nghĩa là Variable_A khác với variable_A

Trợ giúp viết code

Bất kỳ tập lệnh nào (RMarkdown hoặc những cái khác) sẽ cung cấp manh mối khi bạn mắc lỗi. Ví dụ: nếu bạn quên viết dấu phẩy ở vị trí cần thiết hoặc quên đóng dấu ngoặc đơn, RStudio sẽ treo cờ trên dòng đó, ở phía bên trái của script, để cảnh báo bạn.