Je veux écrire une fonction très simple. Si je mets un vecteur en sortie, je devrais obtenir «A», si la matrice «B» et si la liste «C». J'ai écrit :

check<-function(x){
  if (is.numeric(x)){'A'}
  else if (is.matrix(x)){'B'}
  else if (is.list(x)){'C'}
}

Et c'est une mauvaise fonction parce que:

Mat<-rnorm(rnorm(4),2,2)
check(Mat)
'A'

La raison est claire lorsque nous utilisons du code:

is.numeric(Mat)

Mais ma question est: comment puis-je changer ma fonction pour qu'elle fonctionne correctement? Je ne sais pas comment puis-je faire

0
John 16 oct. 2020 à 00:35

2 réponses

Meilleure réponse

Essayez avec inherits:

check<-function(x){
  if (inherits(x, 'numeric')){'A'}
  else if (inherits(x, 'matrix')){'B'}
  else if (inherits(x, 'list')){'C'}
}
check(numeric(1))            # "A"
check(matrix(1))             # "B"
check(list(1))               # "C"

# Using something else (e.g. data.frame) returns null
(check(data.frame(1)))         # NULL
1
Liman 15 oct. 2020 à 22:02

Il y a 2 problèmes. Tout d'abord, vous avez passé à votre fonction un vecteur à 1 dimension, pas une matrice:

Mat = rnorm(rnorm(4),2,2)
> is.vector(Mat)
[1] TRUE

Une matrice dans R est un vecteur à 2 dimensions:

Deuxièmement, quelque chose peut être à la fois un type numérique et un objet matrice:

Mat = as.matrix(rnorm(9), nrow=3)

> is.numeric(Mat)
[1] TRUE

> is.numeric(Mat)
[1] TRUE

Si vous voulez vérifier si vous avez une liste, un vecteur ou une matrice, vous devez changer votre fonction:

check = function(x){
  if (is.atomic(x) & !is.matrix(x)){'A'}
  else if (is.matrix(x)){'B'}
  else if (is.list(x)){'C'}
}


> a = rnorm(9)
> check(a)
[1] "A"
> a = matrix(rnorm(9), nrow=3)
> check(a)
[1] "B"
> a = list(rnorm(9))
> check(a)
[1] "C"
0
user438383 17 oct. 2020 à 00:31