2011-06-10 6 views
11

Je veux retourner un data.frame d'une fonction si le retour TRUE, sinon NA en utilisant return(ifelse(condition, mydf, NA))Pourquoi ifelse convertit un data.frame en une liste: ifelse (TRUE, data.frame (1), 0))! = Data.frame (1)?

Cependant, ifelse les bandes les noms de colonnes du data.frame.

Pourquoi ces résultats sont-ils différents?

> data.frame(1) 
    X1 
1 1 
> ifelse(TRUE, data.frame(1), NA) 
[[1]] 
[1] 1 

certains éléments d'information supplémentaires de dput():

> dput(ifelse(TRUE, data.frame(1), 0)) 
list(1) 
> dput(data.frame(1)) 
structure(list(X1 = 1), .Names = "X1", row.names = c(NA, -1L), 
      class = "data.frame") 

Répondre

14

ifelse est généralement destiné aux comparaisons vectorisés, et a des effets secondaires tels que ceux-ci: comme il est dit dans ?ifelse,

‘ifelse’ returns a value with the same shape as ‘test’ ... 

donc dans ce cas (test est un vecteur de longueur 1) il tente de convertir la trame de données à un «vecteur» (liste dans ce cas) de longueur 1 ...

return(if (condition) mydf else NA) 

En tant que point de conception générale, j'essaie de retourner des objets de la même structure, peu importe quoi, donc je pourrais préférer

if (!condition) mydf[] <- NA 
return(mydf) 

En règle générale, je trouve que les utilisateurs R (en particulier en provenance de d'autres langages de programmation) commencez par utiliser if exclusivement, prenez un moment pour découvrir ifelse, puis abusez-vous pendant un moment, découvrant plus tard que vous voulez vraiment utiliser if dans des contextes logiques. Une chose similaire se produit avec & et &&.

Voir aussi:

+0

@Ben Merci pour le conseil. Je n'ai pas réalisé 'mydf [] <- NA' était une option. –

+0

@Ben puis-je changer l'utilisation de 'if (is.na (myfn()))' en if (sum (is.na (myfn())> 0) 'dans une fonction suivante? Je pourrais poster un question séparée si vous avez besoin de clarification –

+1

probablement juste 'if (tous (is.na (mydf)))'? –