¿Cómo atrapar entero (0)?

136

Digamos que tenemos una declaración que produce integer(0), por ejemplo

 a <- which(1:3 == 5)

¿Cuál es la forma más segura de atrapar esto?

Roman Luštrik
fuente
No me gusta la idea de tratarlo como un error; de hecho, la política de R de no colapsar ciertos objetos vacíos ayuda a evitar muchos flujos de recuperación de errores y, por lo tanto, conduce a un código mucho más limpio.
mbq
20
No uses cuál.
Hadley
1
Puedes probar con any. Devolverá FALSE para cualquiera which(1:3==5)o para 1:3==5.
IRTFM
@BondedDust que estaba tratando de encontrar integer(0), que produje usando whichcomo ejemplo.
Roman Luštrik
66
Sé que esto es viejo, pero ¿podrías, Hadley, describir por qué no usarlo which? Esto sería muy útil para mí para evitar el código incorrecto.
Cactus el

Respuestas:

162

Esa es la forma en que R imprime un vector de longitud cero (uno entero), por lo que puede probar que asea ​​de longitud 0:

R> length(a)
[1] 0

Puede valer la pena repensar la estrategia que está utilizando para identificar qué elementos desea, pero sin más detalles específicos es difícil sugerir una estrategia alternativa.

Gavin Simpson
fuente
19

Si se trata específicamente de enteros de longitud cero , entonces quieres algo como

is.integer0 <- function(x)
{
  is.integer(x) && length(x) == 0L
}

Compruébalo con:

is.integer0(integer(0)) #TRUE
is.integer0(0L)         #FALSE
is.integer0(numeric(0)) #FALSE

También puedes usar assertivepara esto.

library(assertive)
x <- integer(0)
assert_is_integer(x)
assert_is_empty(x)
x <- 0L
assert_is_integer(x)
assert_is_empty(x)
## Error: is_empty : x has length 1, not 0.
x <- numeric(0)
assert_is_integer(x)
assert_is_empty(x)
## Error: is_integer : x is not of class 'integer'; it has class 'numeric'.
Algodón Richie
fuente
3
Podrías usar en !length(x)lugar delength(x)==0
James
3
@James. Es cierto, pero no creo que haya un gran problema de rendimiento de ninguna manera, y me lo length(x) == 0Llee con más claridad.
Richie Cotton
@RichieCotton. ¿Qué pasa con 0L en lugar de 0? He intentado buscarlo en Google, pero no encuentro nada relevante. Perdón por la nigromancia.
eenblam
2
@Ben: Agregar un Lsufijo a un número hace que R lo almacene como un número entero en lugar de un valor de coma flotante. Véase, por ejemplo, cran.r-project.org/doc/manuals/R-lang.html#Constants
Richie Cotton, del
¡Gracias! Me ha ahorrado tiempo.
Andrii
12

Tal vez fuera de tema, pero R presenta dos funciones agradables, rápidas y conscientes de vacío para reducir vectores lógicos, anyy all:

if(any(x=='dolphin')) stop("Told you, no mammals!")
mbq
fuente
1
Sí, sería genial si hubiera algo como is.empty, porque algunas funciones regresan en integer(0)lugar de NAo NULL. Pero por ahora su camino es el más sencillo y funciona en forma de vector, lo cual es una gran ventaja length(a).
Ovnis
7

Inspirado por la respuesta de Andrie, puede usar identicaly evitar cualquier problema de atributo al usar el hecho de que es el conjunto vacío de esa clase de objeto y combinarlo con un elemento de esa clase:

attr(a,"foo")<-"bar"

> identical(1L,c(a,1L))
[1] TRUE

O más generalmente:

is.empty <- function(x, mode=NULL){
    if (is.null(mode)) mode <- class(x)
    identical(vector(mode,1),c(x,vector(class(x),1)))
}

b <- numeric(0)

> is.empty(a)
[1] TRUE
> is.empty(a,"numeric")
[1] FALSE
> is.empty(b)
[1] TRUE
> is.empty(b,"integer")
[1] FALSE
James
fuente
Esta no es la respuesta más simple, pero con mucho la más simple y segura para principiantes.
JASC
7
if ( length(a <- which(1:3 == 5) ) ) print(a)  else print("nothing returned for 'a'") 
#[1] "nothing returned for 'a'"

Pensándolo bien, creo que cualquiera es más hermoso que length(.):

 if ( any(a <- which(1:3 == 5) ) ) print(a)  else print("nothing returned for 'a'") 
 if ( any(a <- 1:3 == 5 ) ) print(a)  else print("nothing returned for 'a'") 
IRTFM
fuente