我在下面有一个示例函数,它将日期作为字符串读入并将其作为日期对象返回.如果它读取的字符串无法转换为日期,则会返回错误.
testFunction <- function (date_in) {
return(as.Date(date_in))
}
testFunction("2010-04-06") # this works fine
testFunction("foo") # this returns an error
Run Code Online (Sandbox Code Playgroud)
现在,我想使用lapply并在日期列表中应用此函数:
dates1 = c("2010-04-06", "2010-04-07", "2010-04-08")
lapply(dates1, testFunction) # this works fine
Run Code Online (Sandbox Code Playgroud)
但是,如果我想在两个好日期中间的一个字符串返回错误时将该函数应用于列表,那么处理此问题的最佳方法是什么?
dates2 = c("2010-04-06", "foo", "2010-04-08")
lapply(dates2, testFunction)
Run Code Online (Sandbox Code Playgroud)
我认为我想在那里试一试,但是有没有办法捕获"foo"字符串的错误,同时要求lapply继续阅读第三个日期?
我试图测试对象是否是错误的结果.用例主要是通过一个foreach()产生错误的循环产生的(虽然,对于测试来说,似乎只能将simpleError()一个变量分配给一个变量),我很困惑如何确定何时发生这种情况:我怎么能测试一个实际上,给定对象是一个错误?一旦我确定这是一个错误,除了消息之外我还能提取什么?也许我错过了关于R的错误处理设施的一些东西,因为似乎有必要从头编写错误对象测试功能.
以下是两个示例,一个使用foreach,.errorhandling参数设置为pass.如果数据切片出现异常,我已经开始将其用作大规模或无人值守处理的默认设置.这样的异常是罕见的,并且不值得崩溃整个for循环(特别是如果异常发生在最后,这似乎是我的默认行为murphysListSortingAlgorithm();-)).相反,期望事后检测.
library(foreach)
library(doMC)
registerDoMC(2)
results = foreach(ix = 1:10, .errorhandling = "pass") %dopar%{
if(ix == 6){
stop("Perfect")
}
if(ix == 7){
stop("LuckyPrime")
} else {
return(ix)
}
}
Run Code Online (Sandbox Code Playgroud)
为简单起见,这是一个非常简单的错误(根据定义):
a = simpleError("SNAFU")
Run Code Online (Sandbox Code Playgroud)
虽然似乎没有被这样的命令is.error(),像命令typeof()和mode()似乎是毫无意义的,我已经找到了最好的方法是使用class()或attributes(),这给那些指示错误的属性.如何以确保我有错误并完全处理该错误的方式使用这些?例如a$message返回SNAFU,但是a$call是NULL.我应该期望从中提取任何有用的东西res[[6]]$call吗?
注1:如果一个人没有多核功能来重现第一个例子,我应该指出它results[[6]]不同于simpleError("Perfect"):
> b = simpleError("Perfect")
> …Run Code Online (Sandbox Code Playgroud) 我在下面有一个简单的应用程序,它显示了一个ggplot.ggplot在控制台中生成警告(参见底部图片).我想捕获警告,并在应用程序中,在情节下显示它.
这是我的代码:
library(shiny)
library(ggplot2)
ui <- fluidPage(
titlePanel("How do i output ggplot warnings? :("),
mainPanel(
plotOutput("my_plot_that_generates_warnings"),
tags$br(),
verbatimTextOutput(outputId='ggplot_warnings')
)
)
server <- function(input, output) {
messages <- reactiveValues(ggplot_warning = 'How to capture warning and display it?')
output$my_plot_that_generates_warnings <- renderPlot({
tryCatch({
ggplot(iris, aes(x=Sepal.Length, y=Sepal.Width)) +
geom_point() +
geom_smooth()
}, message = function(e) {
messages$ggplot_warning <- e$message
}, warning = function(e) {
messages$ggplot_warning <- e$message
}, error = function(e) {
messages$ggplot_warning <- e$message
})
})
output$ggplot_warnings <- renderPrint({
cat(messages$ggplot_warning)
})
}
shinyApp(ui …Run Code Online (Sandbox Code Playgroud) 这个问题可能会或可能不会受到我失去整个3小时地理编码运行的启发,因为其中一个值返回了错误.提示怜悯(下)投票.
基本上在被调用的函数内返回了一个错误sapply.我曾经options(error=recover),但尽管浏览了我可以使用的每个级别,我找不到任何将(数千次成功)调用FUN的结果存储在内存中的地方.
我在浏览周围时发现的一些对象在我尝试检查它们时会出错,声称引用不再有效.不幸的是我丢失了特定的错误消息.
这是一个快速的例子,虽然它没有复制引用错误(我怀疑它与消失的环境有关并且可能并不重要),但它确实证明我看不到保存已处理数据的方法.
有这样的技术吗?
请注意,我已经意识到我的错误并插入了比之前存在的更强大的错误处理try,但我正在寻找一种方法来事后恢复内容而不是事前.
测试功能
sapply( seq(10), function(x) {
if(x==5) stop("Error!")
return( "important data" )
} )
Run Code Online (Sandbox Code Playgroud)
互动探索
> sapply( seq(10), function(x) {
+ if(x==5) stop("Error!")
+ return( "important data" )
+ } )
Error in FUN(1:10[[5L]], ...) : Error!
Enter a frame number, or 0 to exit
1: sapply(seq(10), function(x) {
if (x == 5)
stop("Error!")
return("important data")
})
2: lapply(X = X, FUN = FUN, ...)
3: FUN(1:10[[5]], …Run Code Online (Sandbox Code Playgroud) op <- options(warn=0) #although doesn't work for any value of warn
assign("last.warning", NULL, envir = baseenv())
thisDoesntWork<- function() {
warning("HEY, this is definitely a warning!")
cat(paste("number of warnings:",length(warnings())))
}
>thisDoesntWork()
Warning in thisDoesntWork() : HEY, this is definitely a warning!
number of warnings: 0
Run Code Online (Sandbox Code Playgroud)
警告的数量应该是1而不是0 - warnings()如果在函数内调用,它似乎不返回任何内容.为什么?如果警告发生,如何解决这个问题并将其打印出来?
我不想使用tryCatch,因为那时我失去了函数返回的值(它可能仍然返回一个有效值,即使它生成了一个警告).
我是一个狂热的粉丝tryCatch().然而,直到今天,我从未真正关注简单和常规警告/错误之间的区别,因此我真的不知道如何处理它们.
我想知道的是如何告诉tryCatch(参见帮助文件)简单的警告是正常的,它应该返回结果expr而不是跳转到该warning部分.
您将在下面找到一个可重复的示例
tryCatch>>没有警告require("forecast")
y <- ts(c(6178, 7084, 8162, 8462, 9644, 10466, 10748, 9963, 8194, 6848, 7027, 7269, 6775, 7819, 8371, 9069, 10248, 11030, 10882, 10333, 9109, 7685, 7602, 8350, 7829, 8829, 9948, 10638, 11253, 11424, 11391, 10665, 9396, 7775, 7933, 8186, 7444, 8484, 9864, 10252, 12282, 11637, 11577, 12417, 9637, 8094, 9280, 8334, 7899, 9994, 10078, 10801, 12950, 12222, 12246, 13281, 10366, 8730, 9614, 8639, …Run Code Online (Sandbox Code Playgroud) 编写一个tryCatch将处理错误值但将忽略警告的代码。举个例子
foo <- function(x) {
if (x == 1) {
warning('Warning')
} else if (x == 0) {
stop('Error')
}
return(1)
}
bar <- function(x){
tryCatch(
expr = foo(x),
error = identity,
warning = function(w) invokeRestart("muffleWarning")
)
}
Run Code Online (Sandbox Code Playgroud)
因此foo,如果您传递 0 会警告您,如果您传递 1 则会出现错误。目的bar是如果您传递 0 则会收到错误,但它会抑制bar传递 1 时生成的警告。该invokeRestart("muffleWarning")命令来自的定义suppressWarnings。它在我这里的建筑中不起作用,我不知道为什么。(具有讽刺意味的是,它会生成一个错误,因此尝试成功将我不想要的警告升级为我无法解释的错误。)
这个定义bar将起作用
bar <- function(x){
tryCatch(
expr = foo(x),
error = SomeFunctionThatDoesNotMatter,
warning = function(w){suppressWarnings(foo(x))}
) …Run Code Online (Sandbox Code Playgroud) 我在服务器上运行的R中有许多无人看管的批处理作业,运行后我必须分析作业失败。
我试图捕获错误以将其记录下来并从错误中恢复,但是我无法获得堆栈跟踪(traceback)来记录导致错误的R命令的代码文件名和行号。(愚蠢的)可复制示例:
f <- function() {
1 + variable.not.found # stupid error
}
tryCatch( f(), error=function(e) {
# Here I would log the error message and stack trace (traceback)
print(e) # error message is no problem
traceback() # stack trace does NOT work
# Here I would handle the error and recover...
})
Run Code Online (Sandbox Code Playgroud)
运行上面的代码将产生以下输出:
f()中的simpleError:找不到对象“ variable.not.found”
没有可用的回溯
回溯不可用,其原因已记录在R帮助(?traceback)中:
通过try或tryCatch捕获的错误不会生成回溯,因此输出的是最后一个未捕获的错误(不一定是最后一个错误)的调用顺序。
换句话说:捕获错误tryCatch确实会杀死堆栈跟踪!
我怎么能够
多谢!
为了回应有用的评论,我编辑了原始问题(我假设for循环和apply循环给出了不同的结果).
我使用R来运行大量的2组t检验,使用分隔表中的输入.根据这里和其他地方的建议,我尝试了'for-loops'和'apply'来实现这一目标.对于'正常't.test,两者都很好地工作并给出相同的结果.但是,对于配对t检验,for-look似乎有效,而apply-loop则不然.后来,我发现两个循环都遇到了同样的问题(见下文),但for循环更适合处理情况(循环的一个循环返回无效结果),而apply-loop完全失败.
我的输入文件如下所示:(第一行是标题行,数据行有名称,第1组有4个数据点,第2组有4个数据点):
header g1.1 g1.2 g1.3 g1.4 g2.1 g2.2 g2.3 g2.4
name1 0 0.5 -0.2 -0.2 -0.1 0.4 -0.3 -0.3
name2 23.2 24.4 24.5 27.2 15.5 16.5 17.7 20.0
name3 .....
Run Code Online (Sandbox Code Playgroud)
等等(整体~50000行).第一条数据线(从名字19开始证明是罪魁祸首.
这是for循环版本,效果更好(在有问题的行上失败,但正确处理所有其他行):
table <- read.table('ttest_in.txt',head=1,sep='\t')
for(i in 1:nrow(table)) {
g1<-as.numeric((table)[i,2:5])
g2<-as.numeric((table)[i,6:9])
pv <- t.test(g1,g2,paired=TRUE)$p.value
}
Run Code Online (Sandbox Code Playgroud)
这是导致问题的"应用"版本
table <- read.table('ttest_in.txt',head=1,sep='\t')
pv.list <- apply(table[,2:9],1,function(x){t.test(x[1:4],x[5:8],paired=TRUE)$p.value})
Run Code Online (Sandbox Code Playgroud)
~50000条数据线中的一条是有问题的,因为所有成对比较的差异是相同的,这在配对t检验中导致未定义的p值(基本上为零).应用循环崩溃,错误"数据基本上是常量".对我来说(作为一个R新手),因为t.test不喜欢一个数据而崩溃整个脚本似乎不是一个好主意.在for循环中,此数据行也会导致错误消息,但循环继续,所有其他t测试都会给出正确的结果.
我做了一些根本错误的事吗?这种行为基本上禁止使用apply-loops进行这种批处理分析.或者有一种规避这个问题的标准方法.为什么t检验不会返回对该特定p值无效的东西而不是拯救?