简体   繁体   English

如何跳过循环中的错误

[英]How to skip an error in a loop

I want to skip an error (if there is any) in a loop and continue the next iteration. 我想在循环中跳过错误(如果有的话)并继续下一次迭代。 I want to compute 100 inverse matrices of a 2 by 2 matrix with elements randomly sampled from {0, 1, 2}. 我想计算具有从{0,1,2}随机采样的元素的2乘2矩阵的100个逆矩阵。 It is possible to have a singular matrix (for example, 可以有一个奇异矩阵(例如,

1 0
2 0

Here is my code 这是我的代码

set.seed(1)
count <- 1
inverses <- vector(mode = "list", 100)
repeat {
    x <- matrix(sample(0:2, 4, replace = T), 2, 2)
    inverses[[count]] <- solve(x)
    count <- count + 1
    if (count > 100) break
}

At the third iteration, the matrix is singular and the code stops running with an error message. 在第三次迭代中,矩阵是单数的,代码停止运行并显示错误消息。 In practice, I would like to bypass this error and continue to the next loop. 在实践中,我想绕过这个错误并继续下一个循环。 I know I need to use a try or tryCatch function but I don't know how to use them. 我知道我需要使用trytryCatch函数,但我不知道如何使用它们。 Similar questions have been asked here, but they are all really complicated and the answers are far beyond my understanding. 这里也提出了类似的问题,但它们都非常复杂,答案远远超出我的理解范围。 If someone can give me a complete code specifically for this question, I really appreciate it. 如果有人可以专门为这个问题给我一个完整的代码,我真的很感激。

This would put NULL s into inverses for the singular matrices: 这会将NULL s置于奇异矩阵的inverses中:

inverses[[count]] <- tryCatch(solve(x), error=function(e) NULL)

If the first expression in a call to tryCatch raises an error, it executes and returns the value of the function supplied to its error argument. 如果对tryCatch的调用中的第一个表达式引发错误,它将执行并返回提供给其error参数的函数的值。 The function supplied to the error arg has to take the error itself as an argument (here I call it e ), but you don't have to do anything with it. 提供给error arg的函数必须将错误本身作为参数(这里我称之为e ),但你不必对它做任何事情。

You could then drop the NULL entries with inverses[! is.null(inverses)] 然后你可以使用inverses[! is.null(inverses)]删除NULL条目inverses[! is.null(inverses)] inverses[! is.null(inverses)] . inverses[! is.null(inverses)]

Alternatively, you could use the lower level try . 或者,您可以使用较低级别的try The choice is really a matter of taste. 选择真的是品味问题。

count <- 0
repeat {
    if (count == 100) break
    count <- count + 1
    x <- matrix(sample(0:2, 4, replace = T), 2, 2)
    x.inv <- try(solve(x), silent=TRUE)
    if ('try-error' %in% class(x.inv)) next
    else inverses[[count]] <- x.inv
}

If your expression generates an error, try returns an object with class try-error . 如果表达式生成错误,请try返回类try-error的对象。 It will print the message to screen if silent=FALSE . 如果silent=FALSE它会将消息打印到屏幕。 In this case, if x.inv has class try-error , we call next to stop the execution of the current iteration and move to the next one, otherwise we add x.inv to inverses . 在这种情况下,如果x.inv拥有一流的try-error ,我们称之为next停止当前迭代的执行,并移动到下一个,否则我们添加x.invinverses

Edit: 编辑:

You could avoid using the repeat loop with replicate and lapply . 您可以避免使用带有replicatelapplyrepeat循环。

matrices <- replicate(100, matrix(sample(0:2, 4, replace=T), 2, 2), simplify=FALSE)
inverses <- lapply(matrices, function(mat) if (det(mat) != 0) solve(mat))

It's interesting to note that the second argument to replicate is treated as an expression , meaning it gets executed afresh for each replicate. 有趣的是,要replicate的第二个参数被视为expression ,这意味着它会为每个复制重新执行。 This means you can use replicate to make a list of any number of random objects that are generated from the same expression. 这意味着您可以使用replicate来生成从同一表达式生成的任意数量的随机对象的list

Instead of using tryCatch you could simply calculate the determinant of the matrix with the function det . 您可以使用函数det简单地计算矩阵的行列式,而不是使用tryCatch A matrix is singular if and only if the determinant is zero. 当且仅当行列式为零时,矩阵才是奇异的。

Hence, you could test whether the determinant is different from zero and calculate the inverse only if the test is positive: 因此,您可以测试行列式是否与零不同,并仅在测试为正时计算逆:

set.seed(1)
count <- 1
inverses <- vector(mode = "list", 100)
repeat {
  x <- matrix(sample(0:2, 4, replace = T), 2, 2)
  # if (det(x)) inverses[[count]] <- solve(x)
  # a more robust replacement for the above line (see comment):
  if (is.finite(determinant(x)$modulus)) inverses[[count]] <- solve(x)
  count <- count + 1
  if (count > 100) break
}

Update : 更新

It is, however, possible to avoid generating singular matrices. 但是,可以避免生成奇异矩阵。 The determinant of a 2-by-2 matrix mat is definded as mat[1] * mat[4] - mat[3] * mat[2] . 2乘2矩阵mat的行列式定义为mat[1] * mat[4] - mat[3] * mat[2] You could use this knowledge for sampling random numbers. 您可以使用此知识对随机数进行采样。 Just do not sample numbers which will produce a singular matrix. 只是不要采样会产生奇异矩阵的数字。 This, of course, depends on the numbers sampled before. 当然,这取决于之前采样的数字。

set.seed(1)
count <- 1
inverses <- vector(mode = "list", 100)

set <- 0:2 # the set of numbers to sample from

repeat {

  # sample the first value
  x <- sample(set, 1)
  # if the first value is zero, the second and third one are not allowed to be zero.
  new_set <- ifelse(x == 0, setdiff(set, 0), set)
  # sample the second and third value
  x <- c(x, sample(new_set, 2, replace = T))
  # calculate which 4th number would result in a singular matrix
  not_allowed <- abs(-x[3] * x[2] / x[1])
  # remove this number from the set
  new_set <- setdiff(0:2, not_allowed)
  # sample the fourth value and build the matrix
  x <- matrix(c(x, sample(new_set, 1)), 2, 2)

  inverses[[count]] <- solve(x)
  count <- count + 1
  if (count > 100) break
}

This procedure is a guarantee that all generated matrices will have an inverse. 此过程可保证所有生成的矩阵都具有反转。

try is just a way of telling R : "If you commit an error inside the following parentheses, then skip it and move on." try只是告诉R一种方式:“如果你在下面的括号中提交错误,那么跳过它然后继续。”

So if you're worried that x <- matrix(sample(0:2, 4, replace = T), 2, 2) might give you an error, then all you have to do is: 因此,如果您担心x <- matrix(sample(0:2, 4, replace = T), 2, 2)可能会给您一个错误,那么您所要做的就是:

try(x <- matrix(sample(0:2, 4, replace = T), 2, 2))

However , keep in mind then that x will be undefined if you do this and it ends up not being able to compute the answer. 但是 ,请记住,如果执行此操作, x将不确定,并且最终无法计算答案。 That could cause a problem when you get to solve(x) - so you can either define x before try or just "try" the whole thing: 这可能会导致问题,当你得到solve(x) - 所以你可以在try之前定义x或只是“尝试”整个事情:

try(
      {
      x <- matrix(sample(0:2, 4, replace = T), 2, 2)
      inverses[[count]] <- solve(x)
      }
    )

The documentation for try explains your problem pretty well. 试用文档很好地解释了你的问题。 I suggest you go through it completely. 我建议你彻底完成它。

Edit: The documentation example looked pretty straightforward and very similar to the op's question. Edit:文档示例看起来非常简单,与op的问题非常相似。 Thanks for the suggestion though. (还是)感谢你的建议。 Here goes the answer following the example in the documentation page: 以下是文档页面中示例的答案:

# `idx` is used as a dummy variable here just to illustrate that
# all 100 entries are indeed calculated. You can remove it.
set.seed(1)
mat_inv <- function(idx) {
    print(idx)
    x <- matrix(sample(0:2, 4, replace = T), nrow = 2)
    solve(x)
}
inverses <- lapply(1:100, function(idx) try(mat_inv(idx), TRUE))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM