Phần lớn lỗi R ở người mới rơi vào khoảng mười dạng: gõ sai tên đối tượng, quên nạp gói, sai đường dẫn, sai kiểu dữ liệu, thiếu ngoặc hay dấu phẩy. Đọc thông báo lỗi từ dòng chữ cuối, tìm tên đối tượng hoặc hàm được nhắc tới, và lỗi thường tự lộ ra.
Thông báo lỗi R ngắn và khô, lại bằng tiếng Anh, nên người mới hay bỏ qua rồi chép nguyên câu đi hỏi. Thật ra mỗi câu đều nói khá rõ chuyện gì đang xảy ra. Bảng dưới đây lấy đúng nguyên văn thông báo khi chạy thử trên R 4.5, để bạn tra khi gặp.
Mười thông báo lỗi và nghĩa thật của chúng
Cột đầu là nguyên văn thông báo (phần trong ngoặc nhọn thay đổi theo mã của bạn):
| Thông báo | Nghĩa thật | Cách sửa |
|---|---|---|
object 'x' not found | Chưa có đối tượng tên x trong phiên hiện tại | Kiểm chính tả, chữ hoa thường; chạy lại dòng tạo ra nó |
could not find function “read_excel” | Hàm thuộc gói chưa nạp | Gọi library(readxl) hoặc viết readxl::read_excel() |
there is no package called ‘khongco’ | Gói chưa cài, hoặc gõ sai tên gói | Cài bằng install.packages(), kiểm chính tả |
cannot open the connection kèm No such file or directory | Đường dẫn tệp sai so với thư mục làm việc | Mở dự án RStudio, dùng here::here() |
unexpected symbol, unexpected numeric constant | Lỗi cú pháp: thiếu dấu phẩy, ngoặc, toán tử | Nhìn vị trí dấu mũ chỉ ra, xem ký tự ngay trước đó |
non-numeric argument to binary operator | Làm phép tính với cột kiểu chữ | Kiểm kiểu bằng str(), đổi bằng as.numeric() |
arguments imply differing number of rows: 3, 2 | Ghép các cột dài khác nhau thành bảng | Kiểm độ dài từng vectơ |
replacement has 2 rows, data has 3 | Gán một cột ngắn hơn số dòng của bảng | Tạo cột từ chính bảng đó, thường trong mutate() |
subscript out of bounds | Lấy phần tử thứ n trong danh sách hay ma trận ngắn hơn n | Kiểm length(), dim(), tên phần tử |
object of type 'closure' is not subsettable | Lấy phần tử của một hàm, thường do đặt tên bảng trùng tên hàm như data, df, mean | Tạo bảng trước khi dùng, đặt tên không trùng hàm |
Ngoài lỗi còn có cảnh báo, bắt đầu bằng Warning. Cảnh báo không dừng mã nhưng hay báo một kết quả sai lặng lẽ, ví dụ NAs introduced by coercion khi as.numeric() gặp giá trị như “2,5” viết bằng dấu phẩy thập phân: ô đó thành thiếu, không ai hay.
Đọc một thông báo lỗi theo thứ tự nào?
Tìm hàm gây lỗi
Thông báo thường có dạng Error in tên_hàm(...) : nội dung. Phần trước dấu hai chấm cho biết lỗi xảy ra trong hàm nào. Với các gói hệ tidyverse, thông báo được trình bày nhiều dòng, có dấu chấm đầu dòng giải thích và gợi ý; đọc hết các dòng đó.
Lần ngược đường đi
Khi lỗi xảy ra sâu bên trong một hàm gọi hàm khác, traceback() in chuỗi lời gọi ngay sau lỗi. Với lỗi từ các gói dùng rlang, rlang::last_trace() in cây lời gọi gọn hơn.
Cô lập dòng lỗi
Chạy từng bước của chuỗi lệnh |> cho tới khi lỗi xuất hiện. Thường lỗi ở bước cuối nhưng nguyên nhân ở một bước trước đó làm sai kiểu hay mất cột.
Ba lỗi không báo đỏ nhưng nguy hiểm hơn
Mấy trường hợp sau R chạy êm nhưng cho ra kết quả sai:
- Đối tượng cũ còn trong bộ nhớ: mã chạy được trên máy bạn vì một biến tạo bằng tay từ hôm trước, nhưng hỏng trên máy khác. Khởi động lại R và chạy lại từ đầu trước khi gửi.
- Cột số bị đọc thành chữ vì một ô có ký tự lạ, rồi
as.numeric()âm thầm biến các ô đó thànhNA. ĐếmNAtrước và sau khi đổi kiểu. mean(x)trảNAvì có giá trị thiếu, người dùng thêmna.rm = TRUEmà không biết đã loại bao nhiêu dòng. Ghi lại số dòng bị loại.- Factor đổi sang số bằng
as.numeric()trả về thứ tự mức chứ không phải giá trị in ra: factor có các mức “10”, “5”, “7” sẽ thành 1, 2, 3. Đổi qua chữ trước:as.numeric(as.character(x)).
Khi một lệnh in ra nhiều cảnh báo, R chỉ báo kiểu There were 12 warnings. Gõ warnings() ngay sau đó để xem từng cái; đừng bỏ qua chỉ vì mã vẫn chạy hết.
Lỗi khi cài gói và lỗi do tiếng Việt
Gói không có cho phiên bản R đang dùng
Thông báo package ‘x’ is not available for this version of R thường do gõ sai tên gói (tên gói phân biệt hoa thường), gói đã bị gỡ khỏi CRAN, hoặc gói chỉ có trên GitHub hay Bioconductor. Tra tên gói trên trang CRAN; với Bioconductor, cài qua BiocManager::install().
Cài từ mã nguồn thất bại
installation of package ‘x’ had non-zero exit status nghĩa là quá trình biên dịch hỏng. Cuộn lên trên để đọc dòng lỗi đầu tiên, thường là thiếu một thư viện hệ thống hoặc trình biên dịch. Trên Windows, gói cần biên dịch đòi cài Rtools đúng với phiên bản R. Khi R hỏi có cài từ mã nguồn bản mới hơn không, trả lời không để lấy bản nhị phân đã biên dịch sẵn là cách nhanh nhất.
Chữ tiếng Việt
invalid multibyte string xuất hiện khi R đọc chuỗi theo một bảng mã nhưng tệp lưu theo bảng mã khác, hay gặp với tệp CSV cũ hoặc kịch bản lưu không phải UTF-8. Trong RStudio, dùng File → Reopen with Encoding rồi chọn UTF-8, sau đó lưu lại bằng Save with Encoding. Trên Windows, thư mục dự án nằm dưới tên người dùng có dấu đôi khi làm hỏng việc cài gói; đặt thư viện gói và dự án ở đường dẫn không dấu sẽ tránh được.
Tra trợ giúp trước khi hỏi người khác
Gõ ?read_excel để mở trang hướng dẫn của hàm. Đọc mục Arguments để biết tham số nhận kiểu gì, và cuộn xuống Examples: chép đoạn ví dụ chạy thử là cách nhanh nhất hiểu hàm. Nhiều gói còn có tài liệu dài dạng hướng dẫn, mở bằng vignette(package = 'dplyr').
Khi tìm trên mạng, chép đúng phần thông báo lỗi không chứa tên riêng của bạn, thêm tên gói. Câu hỏi giống hệt nhiều khả năng đã có người hỏi trên Stack Overflow hoặc diễn đàn Posit Community. Đọc ngày đăng: lời khuyên cũ có thể dùng hàm đã bị thay.
Hỏi thế nào để được trả lời?
Một câu hỏi tốt có ba phần: bạn muốn làm gì, bạn đã làm gì (mã), và R trả lại gì (thông báo nguyên văn). Câu “R bị lỗi, giúp với” kèm ảnh chụp màn hình gần như không ai giúp được, vì người đọc phải đoán cả dữ liệu, cả mã, cả phiên bản.
Ghi tiêu đề câu hỏi bằng phần lõi của thông báo lỗi cộng tên hàm, ví dụ “pivot_wider báo values are not uniquely identified”. Người có cùng lỗi tìm được câu hỏi của bạn, và người trả lời biết ngay chủ đề. Khi đã được trả lời, quay lại ghi lời giải cuối cùng nếu nó khác gợi ý ban đầu.
Tạo ví dụ tối giản để hỏi
Người khác chỉ giúp được nhanh khi chạy lại được lỗi trên máy họ. Một ví dụ tối giản có dữ liệu nhỏ, mã ngắn nhất vẫn gây lỗi và thông tin phiên bản:
- Thu nhỏ dữ liệu: lấy vài dòng, vài cột liên quan.
dput(head(ks[, c('id', 'q1', 'tinh')], 8))in ra đoạn mã tạo lại đúng bảng đó, kể cả kiểu cột. - Nếu dữ liệu nhạy cảm, tự tạo một bảng giả có cùng cấu trúc bằng
data.frame(), hoặc dùng bộ có sẵn nhưmtcars,iris. - Bỏ dần từng dòng mã không liên quan, chạy lại sau mỗi lần bỏ. Nhiều khi tới bước này bạn tự thấy lỗi.
- Bôi đen đoạn mã đã gọn, gọi
reprex::reprex(). Góireprexchạy mã trong một phiên sạch và chép kết quả, kể cả thông báo lỗi, vào bộ nhớ tạm để dán vào câu hỏi. - Ghi kèm phiên bản R và gói, lấy từ
sessionInfo(), và một câu nói rõ bạn muốn kết quả ra sao.
Việc KHÔNG nên làm: gửi ảnh chụp màn hình mã, hoặc gửi cả tệp dữ liệu thật của khảo sát. Ảnh không chép chạy được, còn dữ liệu thật có thể chứa thông tin của người tham gia.
Câu hỏi thường gặp
Vì sao mã chạy được hôm qua nhưng hôm nay báo lỗi?
Thường do hôm qua có một đối tượng tạo bằng tay còn trong bộ nhớ, hoặc một gói vừa được cập nhật. Khởi động lại R, chạy từ đầu; nếu vẫn lỗi, xem trang tin thay đổi của gói.
Thông báo có chữ masked khi nạp gói là lỗi à?
Không phải lỗi. R báo rằng gói mới nạp có hàm trùng tên với hàm đã có, ví dụ filter của dplyr che filter của stats. Muốn gọi rõ hàm nào, viết tên_gói::tên_hàm.
Có nên đổi R sang giao diện tiếng Việt không?
Không nên với thông báo lỗi. Giữ thông báo tiếng Anh giúp tìm trên mạng dễ hơn nhiều, vì phần lớn câu hỏi và trả lời được viết bằng tiếng Anh.
Cảnh báo có cần xử lý hết không?
Cần đọc hết và hiểu từng cái. Có cảnh báo vô hại, có cảnh báo báo trước dữ liệu bị biến thành thiếu. Chỉ tắt cảnh báo khi đã biết rõ nguyên nhân.
dput in ra quá dài thì làm sao?
Chọn ít cột và ít dòng hơn, chỉ giữ những cột liên quan tới lỗi. Nếu cột là factor có nhiều mức, đổi tạm sang chữ trước khi dput.