Menu

Data frame trong R: tạo, xem cấu trúc và truy cập cột

Data frame là bảng tính của R: các cột có tên, dài bằng nhau, mỗi cột một kiểu. Cách tạo, xem nhanh bằng str() và head(), và truy cập cột, hàng, ô.

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.

Data frame là một danh sách các cột

Data frame là bảng của R: mỗi hàng là một quan sát, mỗi cột là một biến. Nó là bảng tính của R, và là hình dạng mà gần như mọi dữ liệu thực tế đều mang: mỗi người, mỗi lần đo, mỗi giao dịch một hàng; mỗi thuộc tính một cột.

Về cấu trúc, data frame là một list gồm các vector dài bằng nhau, được thêm hành vi hàng và cột ở bên trên. Chỉ một sự thật đó đã giải thích hầu hết quy tắc của nó: mỗi cột có một kiểu duy nhất (vì nó là vector), các cột khác nhau có thể có kiểu khác nhau (vì nó là list), và mọi cột phải dài bằng nhau (đó là phần "frame").

Bạn tạo data frame bằng cách đưa các vector có tên vào data.frame():

Văn bản, số và giá trị logic nằm cạnh nhau, một sự pha trộn mà ma trận không chứa được. Trong thực tế bạn hiếm khi gõ tay dữ liệu như thế này; bảng thường đến qua read.csv hoặc từ cơ sở dữ liệu. Nhưng mọi thứ bên dưới đều áp dụng y hệt, bất kể data frame đến từ đâu.

Xem nhanh một data frame

Đừng bao giờ tính toán trên một bộ dữ liệu mà bạn chưa nhìn qua. Bộ công cụ xem dữ liệu của R ngắn gọn và đáng để thành phản xạ:

  • str() là lệnh nên chạy đầu tiên trên mọi dữ liệu vừa tải: mỗi cột một dòng, kèm kiểu và các giá trị đầu. Đây là nơi bạn phát hiện cột "số" thực ra bị đọc thành character chỉ vì một giá trị lạc loài.
  • nrow() / ncol() cho kích thước; names() liệt kê tên các cột.
  • summary() cho thống kê theo từng cột: min/median/mean/max cho số, số đếm cho giá trị logic và factor.
  • head(df) và tail(df) in sáu hàng đầu và sáu hàng cuối, không thể thiếu khi bộ dữ liệu thật quá lớn để in toàn bộ. Bạn sẽ thấy head() hoạt động ở phần dưới trên một bộ dữ liệu có sẵn.

Ba cách lấy một cột

Truy cập cột là thao tác cơ bản nhất, và R cho bạn ba cách viết:

  • people$age: cách dùng hằng ngày, ngắn, dễ đọc, tự động gợi ý trong hầu hết trình soạn thảo.
  • people[["age"]]: kết quả giống hệt, nhưng tên cột có thể lấy từ một biến (col <- "age"; people[[col]]), điều mà $ không làm được. Nên dùng cách này bên trong hàm.
  • people[, "age"]: kiểu ma trận, hàng ở trước dấu phẩy (để trống = tất cả), cột ở sau.

Cả ba đều trả về cột dưới dạng vector thường, sẵn sàng cho mean(people$age). Cách viết thứ tư trong đoạn code là cái bẫy: people["age"] với một cặp ngoặc vuông trả về một data frame một cột, không phải vector. Đây cũng chính là sự khác biệt giữa [ và [[ ở list, vì data frame là một list. Nếu một hàm toán học phàn nàn rằng đầu vào không phải số, hãy kiểm tra lại dấu ngoặc.

Hàng và ô

Cú pháp [row, column] lấy được bất kỳ lát cắt nào của bảng:

people[2, ] là toàn bộ hàng thứ hai (dưới dạng data frame một hàng, vì hàng chứa nhiều kiểu nên vẫn giữ dạng frame). people[2, "name"] là một ô duy nhất. Một vector số thứ tự hàng sẽ lấy ra nhiều hàng.

Dòng cuối mới là dòng quan trọng: một điều kiện logic trên một cột sẽ chọn ra các hàng, ở đây là mọi người trên 28 tuổi. Cách dùng mặt nạ để chọn hàng này là nền tảng của mọi thao tác lọc dữ liệu trong R, và nó xứng đáng có một bài riêng: xem lọc và lấy tập con để biết đầy đủ, gồm cả subset() và lọc theo nhiều điều kiện.

Thêm và xóa cột

Vì data frame là một list các cột, cột được thêm hay bớt chỉ bằng phép gán thông thường:

Gán cho một tên mới sẽ thêm cột; vector phải khớp với nrow() (hoặc có độ dài 1, khi đó nó được lặp lại để điền mọi hàng). Lần thêm thứ hai cho thấy cách làm chuẩn: cột mới được tính từ các cột có sẵn, bằng phép toán vector hóa trên cả cột cùng lúc. Gán NULL sẽ xóa hẳn một cột.

Giá trị của cột cũng được ghi đè theo cùng cách: people$age <- people$age + 1 làm mọi người già thêm một tuổi.

Bộ dữ liệu có sẵn và đôi lời về tibble

R đi kèm các bộ dữ liệu để thực hành được tải sẵn, nên bạn có thể thử mọi thứ ở trên mà không cần nhập gì cả. Hai bộ bạn sẽ gặp trong mọi bài hướng dẫn là mtcars (32 xe, 11 biến số) và iris (150 bông hoa, 4 số đo cộng một factor chỉ loài):

head() phát huy tác dụng: sáu hàng cho bạn biết hình dạng của dữ liệu mà không làm ngập màn hình. Những bộ dữ liệu này là sân chơi lý tưởng: khi không chắc một hàm hoạt động thế nào, hãy thử nó trên mtcars trước khi dùng với dữ liệu của bạn.

Một thuật ngữ bạn sẽ gặp ngay khi chạm vào tidyverse: tibble, phiên bản data frame của tidyverse. Cùng khái niệm, nhưng cư xử lịch sự hơn: khi in chỉ hiện mười hàng đầu kèm kiểu của cột, và không có chuyện khớp tên cột một phần. Tạo bằng tibble() hoặc nhận về từ các hàm của readr/dplyr:

library(tibble)
tibble(name = c("Rosa", "Ken"), age = c(30, 41))
#> # A tibble: 2 x 2
#>   name    age
#>   <chr> <dbl>
#> 1 Rosa     30
#> 2 Ken      41

Mọi thứ trong bài này, gồm $, str(), thêm cột, mặt nạ logic chọn hàng, đều dùng được với tibble mà không cần thay đổi. Tibble là một data frame được trau chuốt thêm; học data frame là bạn đã học cả hai.

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

  • Data frame là một list các cột dài bằng nhau: mỗi cột một kiểu, cả bảng có thể pha trộn nhiều kiểu. Đó là bảng tính của R.
  • Xem trước khi tính: str() trước tiên, rồi head(), summary(), nrow()/ncol()/names().
  • df$col, df[["col"]] và df[, "col"] đều trả về cột dưới dạng vector; df["col"] với một cặp ngoặc vuông trả về data frame.
  • df[rows, cols] cắt lát bất cứ thứ gì; một mặt nạ logic trước dấu phẩy sẽ lọc hàng.
  • Thêm cột bằng phép gán (thường tính từ các cột khác); xóa bằng NULL; thực hành với mtcars.

Tiếp theo: giá trị thiếu, NA có nghĩa là gì, vì sao nó lan qua các phép tính và cách xử lý nó.

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

Làm sao để tạo data frame trong R?

Truyền các vector có tên và dài bằng nhau vào data.frame(): df <- data.frame(name = c("Rosa", "Ken"), age = c(30, 41)). Mỗi vector trở thành một cột. Trong thực tế, hầu hết data frame không được gõ tay mà đến từ read.csv() hoặc từ cơ sở dữ liệu, nhưng cấu trúc thì vẫn vậy.

Làm sao để truy cập một cột trong data frame của R?

Có ba cách: df$age (nhanh, dễ đọc), df[["age"]] (cùng kết quả, dùng được khi tên cột nằm trong một biến) và df[, "age"] (kiểu ma trận). Cả ba đều trả về cột dưới dạng vector thường. Còn df["age"] với một cặp ngoặc vuông thì trả về một data frame có một cột, một nguồn gây nhầm lẫn rất phổ biến.

str() hiển thị gì cho một data frame?

Mỗi cột một dòng: tên, kiểu và vài giá trị đầu tiên, kèm số hàng và số cột ở trên cùng. Đây là cách nhanh nhất để biết một cột được đọc vào dưới dạng số hay văn bản, vì vậy str() nên là lệnh đầu tiên bạn chạy trên mọi bộ dữ liệu vừa tải.

Làm sao để thêm cột vào data frame trong R?

Gán cho một tên chưa tồn tại: df$score <- c(88, 75, 93). Vector phải khớp với số hàng (hoặc có độ dài 1, khi đó nó được lặp lại cho mọi hàng). Xóa một cột bằng cách gán NULL: df$score <- NULL.

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