Comment attraper un entier (0)?

136

Disons que nous avons une déclaration qui produit integer(0), par exemple

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

Quelle est la manière la plus sûre d'attraper cela?

Roman Luštrik
la source
Je n'aime pas l'idée de le traiter comme une erreur - en fait, la politique de R de ne pas réduire certains objets vides aide à éviter de nombreux flux de récupération d'erreurs, et conduit ainsi à un code beaucoup plus propre.
mbq le
20
N'utilisez pas lequel.
hadley
1
Vous pouvez tester avec any. Il renverra FALSE pour l'un which(1:3==5)ou l' autre pour 1:3==5.
IRTFM
@BondedDust que j'essayais de trouver integer(0), que j'ai produit en utilisant whichcomme exemple.
Roman Luštrik
6
Je sais que c'est vieux, mais pourriez-vous, Hadley, expliquer pourquoi ne pas l'utiliser which? Ce serait très utile pour moi d'éviter un mauvais code.
Cactus

Réponses:

162

C'est la manière de R d'imprimer un vecteur de longueur nulle (un entier), vous pouvez donc tester asa longueur 0:

R> length(a)
[1] 0

Il pourrait être utile de repenser la stratégie que vous utilisez pour identifier qui des éléments que vous voulez, mais sans plus de détails de spécifiques , il est difficile de proposer une stratégie alternative.

Gavin Simpson
la source
19

Si c'est spécifiquement des entiers de longueur nulle , alors vous voulez quelque chose comme

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

Vérifiez-le avec:

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

Vous pouvez également utiliser assertivepour cela.

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'.
Coton Richie
la source
3
Vous pouvez simplement utiliser !length(x)plutôt quelength(x)==0
James
3
@James. C'est vrai, mais je ne pense pas qu'il y ait beaucoup de problème de performance dans les deux cas, et length(x) == 0Lme lit plus clairement.
Richie Cotton
@RichieCotton. Que se passe-t-il avec 0L par rapport à 0? J'ai essayé de le rechercher sur Google, mais je ne trouve rien de pertinent. Désolé pour la nécromancie.
eenblam
2
@Ben: L'ajout d'un Lsuffixe à un nombre fait que R le stocke sous forme d'entier plutôt que de valeur à virgule flottante. Voir, par exemple, cran.r-project.org/doc/manuals/R-lang.html#Constants
Richie Cotton
Merci! Cela m'a fait gagner du temps.
Andrii
12

Peut-être hors sujet, mais R propose deux fonctions intéressantes, rapides et vides pour réduire les vecteurs logiques - anyet all:

if(any(x=='dolphin')) stop("Told you, no mammals!")
mbq
la source
1
Ouais, ce serait super s'il y avait quelque chose comme is.empty, parce que certaines fonctions retournent integer(0)au lieu de NAou NULL. Mais pour l'instant, votre chemin est le plus simple et fonctionne en mode vectoriel, ce qui est un gros avantage length(a).
Ufos le
7

Inspiré par la réponse d'Andrie, vous pouvez utiliser identicalet éviter tout problème d'attribut en utilisant le fait qu'il s'agit de l'ensemble vide de cette classe d'objet et en le combinant avec un élément de cette classe:

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

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

Ou plus généralement:

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
la source
Ce n'est pas la réponse la plus simple, mais de loin la plus simple et la plus sûre pour les débutants.
JASC
7
if ( length(a <- which(1:3 == 5) ) ) print(a)  else print("nothing returned for 'a'") 
#[1] "nothing returned for 'a'"

À la réflexion, je pense que tout est plus beau 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
la source