2012-08-02 17 views
6

Uso tryCatch para capturar posibles mensajes de error en mi código R, pero hoy me enfrenté a un problema extraño con ggplot - y realmente no tengo idea de qué está pasando (incluso después de un tiempo dedicado a Búsqueda de Google/SO).tryCatch y ggplot

ejemplo simple con un ggplot llamadas incompletas (sin capa añadida):

> tryCatch(eval(parse(text = 'ggplot(mtcars, aes(x=hp, y=wt))')), error = function(e) e) 
Error: No layers in plot 

lo tanto, el error no es capturado. Aún más: me sale un objeto R con ggplot clase:

> str(tryCatch(eval(parse(text = 'ggplot(mtcars, aes(x=hp, y=wt))')), error = function(e) e)) 
List of 8 
$ data  :'data.frame': 32 obs. of 11 variables: 
    ..$ mpg : num [1:32] 21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ... 
    ..$ cyl : num [1:32] 6 6 4 6 8 6 8 4 4 6 ... 
    ..$ disp: num [1:32] 160 160 108 258 360 ... 
    ..$ hp : num [1:32] 110 110 93 110 175 105 245 62 95 123 ... 
    ..$ drat: num [1:32] 3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 ... 
    ..$ wt : num [1:32] 2.62 2.88 2.32 3.21 3.44 ... 
    ..$ qsec: num [1:32] 16.5 17 18.6 19.4 17 ... 
    ..$ vs : num [1:32] 0 0 1 1 0 1 0 1 1 1 ... 
    ..$ am : num [1:32] 1 1 1 0 0 0 0 0 0 0 ... 
    ..$ gear: num [1:32] 4 4 4 3 3 3 3 4 4 4 ... 
    ..$ carb: num [1:32] 4 4 1 1 2 1 4 2 2 4 ... 
$ layers  : list() 
$ scales  :Reference class 'Scales' [package "ggplot2"] with 1 fields 
    ..$ scales: NULL 
    ..and 20 methods, of which 9 are possibly relevant: 
    .. add, clone, find, get_scales, has_scale, initialize, input, n, 
    .. non_position_scales 
$ mapping :List of 2 
    ..$ x: symbol hp 
    ..$ y: symbol wt 
$ options :List of 1 
    ..$ labels:List of 2 
    .. ..$ x: chr "hp" 
    .. ..$ y: chr "wt" 
$ coordinates:List of 1 
    ..$ limits:List of 2 
    .. ..$ x: NULL 
    .. ..$ y: NULL 
    ..- attr(*, "class")= chr [1:2] "cartesian" "coord" 
$ facet  :List of 1 
    ..$ shrink: logi TRUE 
    ..- attr(*, "class")= chr [1:2] "null" "facet" 
$ plot_env :<environment: R_GlobalEnv> 
- attr(*, "class")= chr "ggplot" 

¿Alguna idea para capturar este tipo de errores?


actualización: Soy consciente del hecho de que la llamada anterior podría estar bien en algunas situaciones (como la adición de una capa posterior). Pero, por favor, considere el siguiente ejemplo (tenga en cuenta que tenemos una errata existe: t se proporciona en y eje en lugar de wt):

> tryCatch(eval(parse(text = 'ggplot(mtcars, aes(x=hp, y=t)) + geom_point()')), error = function(e) e) 
Error in data.frame(x = c(110, 110, 93, 110, 175, 105, 245, 62, 95, 123, : 
    arguments imply differing number of rows: 32, 0 

que hacer llegar el mensaje de error, pero eso no es capturado por tryCatch.

Respuesta

8

Esto ocurre porque el error no se produce en la llamada al ggplot, sino en la llamada al print.ggplot.

Por lo tanto, su tryCatch funciona, pero el error se produce solo más tarde, al intentar imprimir. Esto significa que usted tiene que poner el tryCatch alrededor de la declaración print:

probar este lugar:

x <- tryCatch(eval(parse(text = 'ggplot(mtcars, aes(x=hp, y=wt))')), 
       error = function(e) e) 
tryCatch(print(x), error = function(e) e) 
<simpleError: No layers in plot> 

Y para su segundo ejemplo:

x <- eval(parse(text = 'ggplot(mtcars, aes(x=hp, y=t)) + geom_point()')) 
tryCatch(print(x), error = function(e) e) 

<simpleError in data.frame(x = c(110, 110, 93, 110, 175, 105, 245, 62, 95, 123, 123, 180, 180, 180, 205, 215, 230, 66, 52, 65, 97, 150, 150, 245, 175, 66, 91, 113, 264, 175, 335, 109), y = structure(function (x) standardGeneric("t"), generic = structure("t", package = "base"), package = "base", group = list(), valueClass = character(0), signature = "x", default = structure(function (x) UseMethod("t"), target = structure("ANY", class = structure("signature", package = "methods"), .Names = "x", package = "methods"), defined = structure("ANY", class = structure("signature", package = "methods"), .Names = "x", package = "methods"), generic = structure("t", package = "base"), class = structure("derivedDefaultMethod", package = "methods")), skeleton = structure(function (x) UseMethod("t"), target = structure("ANY", class = structure("signature", package = "methods"), .Names = "x", package = "methods"), defined = structure("ANY", class = structure("signature", package = "methods"), .Names = "x", package = "methods"), generic = structure("t", package = "base"), class = structure("derivedDefaultMethod", package = "methods"))(x), class = structure("standardGeneric", package = "methods")),  PANEL = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L,  1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L,  1L, 1L, 1L, 1L, 1L), check.names = FALSE, stringsAsFactors = TRUE): arguments imply differing number of rows: 32, 0> 
+1

impresionante, muchas gracias! ¿Cómo podría extrañar esto? :) Era bastante obvio después de echar un vistazo a su primera línea, pero esta pregunta me provocó algunas horas de dolor de cabeza antes de eso. Así que, en resumen: gracias de nuevo :) – daroczig

+0

¡Me alegro de haber podido ayudar! A veces uno puede estar demasiado cerca del código ... – Andrie