Thêm một cột: df$new <- value
Để thêm cột trong base R, hãy gán giá trị cho một tên chưa tồn tại. Giá trị thường được tính từ những cột đã có:
Có hai việc vừa xảy ra. orders$total nhận một vector đầy đủ: price * qty được tính cho mọi hàng cùng lúc, vì phép tính số học trong R được vector hóa. orders$currency nhận một giá trị đơn, và R tái sử dụng (recycle) nó cho cả bốn hàng. Bất kỳ độ dài nào khác đều gây lỗi (replacement has 3 rows, data has 4), đó là cách R bảo vệ bạn khỏi một cột bị lệch hàng.
Điều này hoạt động được vì data frame là một list gồm các cột có cùng độ dài: gán một phần tử có tên mới sẽ làm list dài thêm. Tài liệu về data frame giải thích kỹ mô hình này.
Cột có điều kiện: ifelse()
Một cột có giá trị phụ thuộc vào điều kiện thì cần ifelse(), người anh em vector hóa của if. Hàm này nhận cả một vector điều kiện và trả về một giá trị cho mỗi hàng:
Sao không dùng if thường? Vì if chỉ đánh giá đúng một TRUE/FALSE; đưa cho nó cả một cột thì sẽ báo lỗi (the condition has length > 1). ifelse(test, yes, no) kiểm tra từng phần tử và chọn kết quả theo từng hàng. Với ba kết quả trở lên, bạn có thể lồng nhau:
Lồng hai tầng thì không sao; từ ba tầng trở lên sẽ thành một kim tự tháp, và đó chính là việc mà case_when() của dplyr (bên dưới) được tạo ra để giải quyết. Câu lệnh if/else cho một giá trị đơn được trình bày trong tài liệu về if-else.
Nhiều cột cùng lúc: transform()
transform() của base R thêm nhiều cột trong một lần gọi, với tên cột viết trực tiếp:
Lưu ý rằng transform() trả về một data frame mới: bạn phải gán kết quả ngược lại, trong khi df$new <- ... sửa ngay tại chỗ. Một hạn chế: các biểu thức trong cùng một lệnh transform() không thấy được nhau, nên discount = ifelse(total > 50, ...) sẽ thất bại ở đó (total chưa tồn tại). Hãy làm hai bước, hoặc dùng mutate(), hàm cho phép việc này.
Sửa cột và tạo cột
Cùng một cú pháp gán sẽ ghi đè lên cột đã có; khác biệt duy nhất là cột đó đã tồn tại hay chưa:
Điểm này đáng dừng lại một chút: R không cảnh báo gì khi bạn ghi đè một cột. Một lỗi gõ như df$prise <- round(df$price, 2) sẽ âm thầm tạo một cột mới thay vì sửa cột cũ. Sau khi biến đổi, hãy print() hoặc str() data frame và xác nhận bạn đã thay đổi đúng thứ mình muốn.
Xóa một cột
Gán NULL để xóa:
Cột biến mất, không cần thủ tục gì. Để xóa nhiều cột, df[, c("a", "b")] (giữ những cột bạn liệt kê) thường rõ ràng hơn so với gán NULL nhiều lần.
Cách của dplyr: mutate()
Động từ của dplyr cho tất cả những việc trên là mutate(). Các đoạn code dưới đây là khối tĩnh (sandbox chỉ chạy base R), nhưng đây là cách các thao tác tương tự được viết:
library(dplyr)
orders |>
mutate(
total = price * qty,
big = total > 50 # can use total, defined one line up
)
Có hai lợi thế so với base R. Thứ nhất, các cột được định nghĩa trong cùng một mutate() có thể tham chiếu lẫn nhau, theo thứ tự, điều mà transform() không cho phép. Thứ hai, các hàm hỗ trợ điều kiện tốt hơn ifelse() lồng nhau:
students |>
mutate(
grade = if_else(score >= 60, "pass", "fail"),
band = case_when(
score >= 85 ~ "high",
score >= 60 ~ "mid",
.default = "low"
)
)
if_else() là một ifelse() chặt chẽ hơn (hai nhánh phải cùng kiểu dữ liệu, nhờ vậy bắt được bug thật). case_when() đọc như một danh sách phẳng các cặp condition ~ value được kiểm tra từ trên xuống dưới, với .default làm giá trị dự phòng: đây là cách thay thế dễ đọc cho kim tự tháp ifelse(). Như mọi động từ của dplyr, mutate() trả về một data frame mới; xem phần giới thiệu dplyr để biết cách nó nối chuỗi với các hàm còn lại.
Những điều cần nhớ
df$new <- expressionthêm một cột; biểu thức chạy cho mọi hàng cùng lúc.ifelse(test, yes, no)tạo cột có điều kiện;ifthường thì không làm được.transform()thêm nhiều cột mỗi lần gọi nhưng chúng không thấy được nhau;mutate()thì có.- Cùng phép gán đó sẽ ghi đè mà không báo gì: kiểm tra chính tả sau khi biến đổi.
df$col <- NULLxóa một cột;case_when()thay thế kim tự thápifelse()lồng nhau.
Tiếp theo: đổi tên cột với names(), cách viết chắc chắn của base R, và rename() của dplyr.
Câu hỏi thường gặp
Làm sao để thêm một cột mới vào data frame trong R?
Gán giá trị cho một tên cột chưa tồn tại: df$total <- df$price * df$qty. R tạo cột ngay lập tức. Giá trị có thể là một giá trị đơn (được tái sử dụng cho mọi hàng) hoặc một vector tính từ các cột khác, miễn là độ dài khớp với số hàng.
Làm sao để tạo cột có điều kiện trong R?
Dùng hàm vector hóa ifelse(): df$grade <- ifelse(df$score >= 60, "pass", "fail") kiểm tra mọi hàng cùng lúc. Đừng dùng if thường, vì nó chỉ xử lý một điều kiện, không phải cả một cột. Với hơn hai kết quả, hãy lồng các lệnh ifelse() hoặc dùng case_when() của dplyr.
mutate() trong R dùng để làm gì?
mutate() là động từ của dplyr để thêm hoặc biến đổi cột: df |> mutate(total = price * qty) trả về một bản sao của data frame kèm cột mới. Hàm này có thể định nghĩa nhiều cột trong một lần gọi, và cột định nghĩa sau có thể dùng cột định nghĩa trước trong cùng lệnh mutate.
Làm sao để xóa một cột khỏi data frame trong R?
Gán NULL cho cột đó: df$notes <- NULL xóa cột ngay tại chỗ. Trong dplyr, select(-notes) trả về một bản sao không có cột đó.