Rate this post

Trong hướng dẫn này, chúng ta sẽ khám phá một chủ đề rất thú vị, đó là R debug. Ở đây chúng ta sẽ thảo luận về các nguyên tắc cơ bản của debug R và các chức năng khác nhau của nó trong lập trình R với sự trợ giúp của các ví dụ. Chúng tôi cũng sẽ trình bày chi tiết về các gói debug đã cài đặt và xử lý và khôi phục lỗi.

Vì vậy, chúng ta hãy bắt đầu hướng dẫn.

R Debug là gì?

Một chương trình đúng ngữ pháp có thể cho chúng ta kết quả không chính xác do lỗi lôgic. Trong trường hợp, nếu những lỗi như vậy (tức là lỗi) xảy ra, chúng tôi cần tìm hiểu lý do tại sao và nơi chúng xảy ra để bạn có thể sửa chữa chúng. Quy trình xác định và sửa lỗi được gọi là ” debug “.

Có một số hàm debug R, chẳng hạn như:

  • traceback()
  • debug()
  • browser()
  • trace()
  • recover()

Chúng ta sẽ thảo luận lần lượt về các chức năng được đề cập ở trên trong phần sau của bài viết này. Trước đó, chúng ta hãy xem xét các nguyên tắc cốt lõi của debug trong R.

Các nguyên tắc cơ bản của R Debugging

Các lập trình viên thường thấy rằng họ dành nhiều thời gian để debug một chương trình hơn là thực sự viết nó. Do đó, kỹ năng debug tốt là vô giá.

Nguyên tắc xác nhận:

Sửa một chương trình là một quá trình xác nhận từng điều một, rằng nhiều điều bạn tin là đúng về mã thực sự là đúng. Khi chúng tôi nhận thấy một trong những giả định của mình là không đúng, chúng tôi đã tìm ra manh mối về vị trí của một lỗi.

Ví dụ:

x <- y^2 + 3*g(z, 2)
w <- 28
if (w+q > 0) u <- 1 else v <- -10

Bắt đầu nhỏ

Bám sát vào các trường hợp thử nghiệm đơn giản nhỏ, ít nhất là khi bắt đầu quá trình debug R. Làm việc với các đối tượng dữ liệu lớn có thể khiến bạn khó suy nghĩ về vấn đề hơn. Tất nhiên, cuối cùng chúng ta nên kiểm tra mã của mình trong các trường hợp lớn, phức tạp, nhưng hãy bắt đầu từ quy mô nhỏ.

debug trong Mô-đun

Cách thức từ trên xuống:

Hầu hết các nhà phát triển phần mềm chuyên nghiệp đều đồng ý rằng mã nên được viết theo kiểu mô-đun. Mã cấp độ đầu tiên của chúng tôi không nên đủ dài với phần lớn nó bao gồm các lệnh gọi hàm. Và các hàm đó không nên dài dòng quá và nên gọi hàm khác nếu cần. Điều này làm cho mã dễ dàng hơn ở giai đoạn viết và cũng để những người khác hiểu khi đến thời điểm mã được mở rộng.

Chúng ta nên debug theo cách từ trên xuống. Giả sử chúng ta có một thiết lập trạng thái debug của hàm f () và nó chứa dòng này.

Ví dụ:

Y <- g (x, 8)

Hiện tại, không gọi debug (g). Thực thi dòng và xem liệu g () có trả về giá trị mà chúng ta mong đợi hay không. Nếu đúng như vậy, thì chúng ta chỉ cần tránh quá trình tốn thời gian khi thực hiện từng bước đơn qua g (). Nếu g () trả về giá trị sai, thì bây giờ là lúc để gọi debug (g).

Antibugging

Nếu chúng ta có một phần mã trong đó biến x phải là số dương, thì chúng ta có thể chèn dòng này:

Stopifnot (x> 0)

Nếu có lỗi trong mã trước đó hiển thị x bằng, chẳng hạn -3, lệnh gọi tới stopifnot () sẽ đưa mọi thứ đến đó, với thông báo lỗi như sau:

Lỗi: x> 0 không phải là TRUE

R Chức năng debug

Bây giờ chúng ta sẽ thảo luận về các hàm được đề cập ở trên để debug trong R:

traceback ()

Nếu mã của chúng tôi đã bị lỗi và chúng tôi muốn biết dòng vi phạm ở đâu, thì hãy thử truy xuất lại (). Điều này (đôi khi) sẽ hiển thị vị trí trong mã của sự cố đã xảy ra.

Khi một chức năng R không thành công, một lỗi sẽ được in ra màn hình. Ngay sau khi xảy ra lỗi, bạn có thể gọi traceback () để xem lỗi xảy ra ở hàm nào. Hàm traceback () in danh sách các hàm đã được gọi trước khi xảy ra lỗi. Các chức năng được in theo thứ tự ngược lại.

Ví dụ:

f<-function(x) {
  r<-x-g(x)
  r
}
g<-function(y) {
  r<-y*h(y)
  r
}
h<-function(z) {
  r<-log(z)
  if(r<10)
    r^2
  else
    r^3
}

Hiển thị mã:

Đầu ra:

debug ()

Hàm  debug ()  trong R cho phép người dùng từng bước thực hiện một hàm. Tại bất kỳ thời điểm nào, chúng ta có thể in ra giá trị của các biến hoặc tạo ra biểu đồ kết quả trong hàm. Trong khi debug, chúng ta có thể chỉ cần gõ “c” để tiếp tục đến cuối phần mã hiện tại. traceback () không cho chúng tôi biết lỗi đã xảy ra ở đâu trong hàm. Để biết dòng nào gây ra lỗi, chúng ta sẽ phải xem qua hàm debug ().

Ví dụ:

fun <- function(mu,val){
  sub <- val - mu
  sqr <- sub^2
  get <- sum(sqr)
  get
}
set.seed(100)
val <- rnorm(100)
fun(1,val)

Đầu ra:

> debug(fun)
> fun(1,val)

Đầu ra:

Sau khi bạn nhìn thấy lời nhắc “Duyệt qua [1]>”, bạn có thể làm những việc khác nhau:

  • Gõ n thực hiện dòng hiện tại và in dòng tiếp theo;
  • Bằng cách gõ Q, chúng ta có thể thoát khỏi việc debug;
  • Gõ ‘where’ cho biết bạn đang ở đâu trong ngăn xếp lệnh gọi hàm;
  • Bằng cách gõ ls () , chúng ta có thể liệt kê tất cả các đối tượng trong môi trường cục bộ.

Nhập tên đối tượng hoặc in (<tên đối tượng>) cho chúng ta biết giá trị hiện tại của đối tượng. Nếu đối tượng của bạn có tên n, c hoặc Q, chúng ta phải sử dụng print () để xem giá trị của chúng.

browser ()

browser chức năng debug R ()  dừng việc thực thi một chức năng cho đến khi người dùng cho phép nó tiếp tục. Điều này rất hữu ích nếu chúng ta không muốn xem từng đoạn mã hoàn chỉnh, nhưng chúng ta muốn nó dừng lại ở một thời điểm nhất định để chúng ta có thể kiểm tra những gì đang diễn ra. Chèn một lệnh gọi đến browser () trong một hàm sẽ tạm dừng việc thực thi một hàm tại điểm mà browser () được gọi. Tương tự như việc sử dụng debug () ngoại trừ chúng ta có thể kiểm soát nơi thực thi bị tạm dừng.

Ví dụ:

h<-function(z) {
  browser() ## a break point inserted here
  r<-log(z)
  if(r<10)
    r^2
  else
    r^3
}

Hiển thị mã:

Đầu ra:

trace ()

Việc gọi trace () trên một hàm cho phép người dùng chèn các bit mã vào một hàm. Cú pháp cho R debug function trace () hơi lạ đối với người dùng lần đầu. Có thể tốt hơn là sử dụng debug ().

Ví dụ:

#Author websitehcm.com
f<-function(x) {
  r<-x-g(x)
  r
}
g<-function(y) {
  r<-y*h(y)
  r
}
h<-function(z) {
  r<-log(z)
  if(r<10)
    r^2
  else
    r^3
}

Hiển thị mã:

Trong bảng điều khiển, chúng tôi gõ các lệnh sau:

> as.list(body(h))
> trace("h",quote(if(is.nan(r)) {browser()}), at=3, print=FALSE)
> f(1)
> f(-1)
Browse[1]> n
Browse[2]> ls()
Warning message:
In log(z) : NaNs produced
Browse[2]> r
Browse[2]> z
Browse[2]> trace("h",quote(if(z<0) {z<-1}), at=2, print=FALSE)
Browse[2]> f(-1)

Đầu ra:

recovery ()

Khi chúng ta đang debug một hàm, recovery () cho phép chúng ta kiểm tra các biến trong các hàm cấp trên.

Bằng cách nhập một số trong vùng lựa chọn, chúng tôi được điều hướng đến chức năng trên ngăn xếp cuộc gọi và được định vị trong môi trường browser.

  • Chúng ta có thể sử dụng recovery () như một trình xử lý lỗi, thiết lập bằng cách sử dụng các tùy chọn () (ví dụ: lỗi (error = recovery)).
  • Khi một hàm tạo ra lỗi, việc thực thi sẽ bị tạm dừng tại điểm bị lỗi. Chúng ta có thể duyệt qua các lệnh gọi hàm và kiểm tra môi trường để tìm ra nguồn gốc của vấn đề.

Trong recovery, chúng tôi sử dụng các hàm f (), g () và h () trước đó để debug.

> trace("h",quote(if(is.nan(r)) {recover()}), at=3, print=FALSE)
> f(-1)

Selection: 1
Browse[1]> n

Selection: n
Selection: 2
Browse[3]> n

Selection: n
Selection: 3
Browse[5]> n

Selection: n
Selection: 0
Browse[4]>

Đầu ra:

Bằng cách nhập một số trong vùng lựa chọn, chúng tôi được điều hướng đến hàm trên ngăn xếp cuộc gọi và chúng tôi được định vị trong môi trường browser.

Debug các gói đã cài đặt trong R

Có khả năng xảy ra lỗi do gói R đã cài đặt. Một số cách khác nhau để giải quyết vấn đề này là:

  • Cài đặt tùy chọn (lỗi = khôi phục) và sau đó đi từng dòng qua mã bằng cách sử dụng n. 
  • Khi đối mặt với các vấn đề phức tạp, bạn có thể mang theo một bản sao mã chức năng bên mình. Nhập tên chức năng trong bảng điều khiển R sẽ in ra mã chức năng có thể được sao chép vào trình soạn thảo văn bản. Sau đó, bạn có thể chỉnh sửa điều này, tải nó vào không gian làm việc chung và sau đó thực hiện debug. 
  • Nếu sự cố vẫn không được giải quyết, hãy tải xuống mã nguồn. Bạn cũng có thể sử dụng gói devtools và các hàm install (), load_all ()  để làm cho quá trình nhanh hơn. 

Xử lý và khôi phục lỗi trong R

Xử lý ngoại lệ hoặc lỗi là một quá trình phản hồi với các sự cố bất thường trong mã làm gián đoạn dòng chảy của mã. Nói chung, phạm vi cho các trình xử lý ngoại lệ bắt đầu bằng thử và kết thúc bằng bắt. R cung cấp hàm try ()trycatch () cho cùng một hàm.

Hàm try () là một hàm bao bọc cho trycatch () in lỗi và sau đó tiếp tục. Mặt khác, trycatch () cung cấp cho bạn quyền kiểm soát hàm lỗi và cũng có thể tùy chọn, tiếp tục quá trình của hàm.

f <- function(value) {
  if(value == 0) {
    stop("The value cannot be 0")
  } else {
    print(value)
  
}

Hiển thị mã:

> inp <- sapply(0:3, function(i) f(i))
> inp <- sapply(0:3, function(i) try(f(i)))
> inp <- sapply(0:3, function(i) tryCatch(f(i), error = function(e) NA))

Đầu ra:

Bản tóm tắt

Trong hướng dẫn này về các hàm debug R, chúng ta đã hiểu khái niệm debug trong R cùng với các chức năng và ví dụ của chúng. Chúng tôi cũng đã khám phá các gói debug đã cài đặt và xử lý & khôi phục lỗi trong lập trình R.

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *

Contact Me on Zalo
Call now