Menu

dplyr trong R: filter, select, mutate, summarize cơ bản

dplyr là gì, cách cài đặt, và cách sáu động từ cốt lõi cùng toán tử pipe biến code data frame rối rắm thành những pipeline dễ đọc.

Trang này có trình soạn thảo chạy trực tiếp. Sửa, chạy và xem đầu ra ngay lập tức.

dplyr là gì

dplyr là package phổ biến nhất của R để xử lý dữ liệu, một "ngữ pháp dữ liệu" được xây từ một vài động từ (verb). Mỗi động từ là một hàm nhận một data frame, làm đúng một việc (giữ lại một số hàng, thêm một cột, tính tóm tắt theo nhóm) và trả về một data frame mới. Vì mọi động từ có cùng hình dạng, data frame vào và data frame ra, chúng ghép vào nhau bằng pipe thành những pipeline đọc từ trên xuống như một công thức nấu ăn. dplyr là lõi của tidyverse, một họ package (tidyr, ggplot2, readr) có chung thiết kế này.

Mọi thứ dplyr làm, base R cũng làm được. Đây là một phân tích nhỏ bằng base R thuần: lọc bộ dữ liệu có sẵn mtcars lấy các xe 4 xi lanh, tính một cột mới và lấy trung bình theo số cấp số. Đoạn này chạy được:

Cách đó chạy được, và đó là code R tốt. Nhưng để ý xem câu chuyện bị trải ra qua chỉ số ngoặc vuông, một phép gán $ và một công thức. Phiên bản dplyr của cùng phân tích đó:

library(dplyr)

mtcars |>
    filter(cyl == 4) |>
    mutate(kml = mpg * 0.425) |>
    group_by(gear) |>
    summarize(avg_kml = round(mean(kml), 1))

Bốn động từ, theo đúng thứ tự bạn sẽ giải thích thành lời. Sự dễ đọc đó là toàn bộ lý do để dùng dplyr, và với một pipeline hai mươi bước thì nó mang tính quyết định.

Các đoạn code dplyr trên trang này là tĩnh vì trình soạn thảo này chỉ chạy base R; để chạy chúng, hãy cài dplyr trên máy của bạn như hướng dẫn tiếp theo.

Cài đặt và tải

Cài một lần, rồi tải nó trong mọi script dùng đến nó:

install.packages("dplyr")   # once, per machine
library(dplyr)              # every script

Nếu chạy install.packages("tidyverse") thay vào đó, bạn sẽ có dplyr cùng các package anh em. Khi dplyr được tải, nó cảnh báo rằng nó che (mask) stats::filter và stats::lag; đó là chuyện bình thường, không phải lỗi.

Sáu động từ cốt lõi

Mọi động từ đều nhận data frame làm đối số đầu tiên và tên cột ở dạng trần, không có dấu nháy hay tiền tố df$.

filter() giữ lại các hàng thỏa mãn một điều kiện:

mtcars |> filter(mpg > 25)
mtcars |> filter(cyl == 4, hp < 70)   # comma = AND

select() giữ lại các cột theo tên, theo dải hoặc theo hàm hỗ trợ:

mtcars |> select(mpg, cyl, hp)
mtcars |> select(mpg:hp)              # a range of adjacent columns
mtcars |> select(starts_with("d"))    # disp, drat

mutate() thêm hoặc biến đổi cột:

mtcars |> mutate(kml = mpg * 0.425, heavy = wt > 3.5)

arrange() sắp xếp các hàng; bọc một cột trong desc() để sắp giảm dần:

mtcars |> arrange(desc(mpg))

summarize() gộp các hàng thành một hàng tóm tắt, còn group_by() khiến nó gộp theo từng nhóm:

mtcars |>
    group_by(cyl) |>
    summarize(n = n(), avg_mpg = mean(mpg))

Bản thân group_by() không làm gì nhìn thấy được; nó chỉ gắn nhãn cho data frame để summarize() (hoặc mutate()) tiếp theo làm việc theo từng nhóm. Mỗi động từ có một bài đầy đủ trong chương này: lọc hàng, thêm cột, sắp xếp và tóm tắt theo nhóm.

Nối các động từ bằng pipe

Pipe |> lấy giá trị đứng trước nó và đưa vào làm đối số đầu tiên của hàm đứng sau: x |> f(y) nghĩa là f(x, y). Vì mọi động từ dplyr đều nhận và trả về data frame, chúng có thể nối nhau mãi:

mtcars |>
    filter(hp > 100) |>
    mutate(kml = mpg * 0.425) |>
    group_by(cyl) |>
    summarize(cars = n(), avg_kml = round(mean(kml), 1)) |>
    arrange(desc(avg_kml))

Đọc thành lời: lấy mtcars, giữ các xe trên 100 mã lực, thêm cột km trên lít, nhóm theo số xi lanh, đếm và tính trung bình mỗi nhóm, sắp xếp theo trung bình. Không biến trung gian, không lồng nhau. Code cũ hơn dùng %>% của package magrittr thay vì |>; với dplyr thì hai cái thay thế được cho nhau, và |> (có sẵn trong R 4.1+) được giới thiệu trong bài về pipe.

count() và n(): các hàm hỗ trợ đếm

Việc đếm phổ biến đến mức dplyr có lối tắt. n() cho số hàng trong nhóm hiện tại (chỉ dùng được bên trong summarize() hoặc mutate()), còn count() gói cả màn group_by() + summarize(n = n()) vào một lần gọi:

mtcars |> count(cyl)                    # rows per cyl value
mtcars |> count(cyl, gear, sort = TRUE) # two groupers, biggest first

Nếu thấy mình đang viết group_by(x) |> summarize(n = n()), hãy thay bằng count(x).

Đôi lời về tibble

Các động từ dplyr thường trả về một tibble, biến thể data frame của tidyverse. Nó là một data frame (mọi thứ nhận data frame đều nhận tibble), nhưng in ra thân thiện hơn: chỉ 10 hàng đầu, chỉ các cột vừa màn hình, kèm kiểu dữ liệu dưới mỗi tên cột. Hai khác biệt nên biết: tibble không bao giờ dùng tên hàng (vì vậy mtcars |> as_tibble() làm mất tên xe; tidyverse muốn định danh nằm trong một cột thật), và lấy chỉ số bằng một cặp ngoặc vuông luôn trả về tibble thay vì đôi khi rơi xuống thành vector. Cả hai điều này hằng ngày sẽ không làm bạn bất ngờ; chỉ đừng hoảng khi str() báo tbl_df.

Những điều cần nhớ

  • dplyr là một ngữ pháp: sáu động từ, mỗi động từ làm một việc trên data frame, được nối bằng pipe.
  • filter() chọn hàng, select() chọn cột, mutate() thêm cột, arrange() sắp xếp, group_by() + summarize() tổng hợp.
  • x |> f(y) là f(x, y): pipeline đọc từ trên xuống theo đúng thứ tự mọi việc diễn ra.
  • count() và n() đáp ứng hầu hết nhu cầu đếm.
  • Base R làm được tất cả; dplyr thắng về độ dễ đọc khi pipeline dài ra.

Tiếp theo: lọc và lấy tập con chuyên sâu, các cách dùng ngoặc vuông của base R và vị trí của filter() trong dplyr.

Câu hỏi thường gặp

dplyr trong R là gì?

dplyr là package R được dùng rộng rãi nhất để xử lý data frame. Nó cho bạn một nhóm nhỏ các động từ (verb) như filter(), select(), mutate(), arrange(), summarize(), group_by(), mỗi động từ làm một việc trên data frame và được nối với nhau bằng pipe thành những pipeline dễ đọc. Nó là một phần của tidyverse.

Làm sao để cài đặt dplyr?

Chạy install.packages("dplyr") một lần, rồi library(dplyr) ở đầu mọi script dùng đến nó. Nếu cài tidyverse thay vào đó, bạn có dplyr cùng các package anh em (tidyr, ggplot2, readr) trong một lần.

Có cần dplyr không, hay base R là đủ?

Base R làm được mọi thứ dplyr làm, như lấy tập con, aggregate(), order(), và đáng để biết vì nó chạy ở mọi nơi mà không cần thư viện phụ thuộc nào. dplyr xứng đáng được cài khi pipeline dài ra: năm động từ nối nhau đọc như một câu văn, trong khi bản tương đương bằng base R trông như câu đố ngoặc vuông lồng nhau.

summarize và summarise trong dplyr khác nhau thế nào?

Không khác gì cả. Đó là cùng một hàm với cách viết kiểu Mỹ và kiểu Anh; dplyr xuất cả hai. Hãy dùng cách mà nhóm của bạn dùng và giữ nhất quán.

Hình minh họa các ngôn ngữ lập trình của Coddy

Học lập trình cùng Coddy

Bắt đầu