Obtenir le type de toutes les variables

118

Dans R, j'aimerais récupérer une liste de variables globales à la fin de mon script et les parcourir. Voici mon code

#declare a few sample variables
a<-10
b<-"Hello world"
c<-data.frame()

#get all global variables in script and iterate over them
myGlobals<-objects()
for(i in myGlobals){
  print(typeof(i))     #prints 'character'
}

Mon problème est que typeof(i)retourne toujours charactermême si variable aet cne sont pas des variables de caractère. Comment puis-je obtenir le type d'origine de variable dans la boucle for?

Konrad Rudolph
la source
Note aux personnes lisant cette question: typeof()donne une information très générique sur la façon dont l'objet est stocké en mémoire. Pour la plupart des cas d'utilisation, si vous voulez savoir de bonnes informations sur une variable x, vous obtiendrez plus d' informations utiles à partir class(x), is(x)ou str(x)(pour plus de détails de la façon dont ils fournissent). Voir la réponse d'Eric ci-dessous pour des exemples de ce qui typeof()vous dit: les facteurs sont integer; des listes, des blocs de données, des objets de modèle, d'autres objets avancés ne sont que list...
Gregor Thomas

Réponses:

109

Vous devez utiliser getpour obtenir la valeur plutôt que le nom de caractère de l'objet tel que renvoyé par ls:

x <- 1L
typeof(ls())
[1] "character"
typeof(get(ls()))
[1] "integer"

Sinon, pour le problème tel que présenté, vous pouvez utiliser eapply:

eapply(.GlobalEnv,typeof)
$x
[1] "integer"

$a
[1] "double"

$b
[1] "character"

$c
[1] "list"
James
la source
Travaillez parfaitement. Savez-vous s'il y a une pénalité de performance si get () est utilisé pour trouver le type de plusieurs trames de données volumineuses qui peuvent être présentes dans la liste de variables renvoyée par objets ()?
1
geta ses critiques et j'imagine que ce eapplyserait plus rapide qu'une boucle interprétée. Mais il n'y a qu'une seule façon de le savoir ...
James
17

Comment obtenir le type de variable lorsqu'elle est cachée sous un objet global:

Tout ce dont vous avez besoin est dans le manuel R sur les types de base: https://cran.r-project.org/doc/manuals/R-lang.html#Basic-types

Vos object()besoins doivent être pénétrés get(...)avant de pouvoir voir à l'intérieur. Exemple:

a <- 10
myGlobals <- objects()
for(i in myGlobals){
  typeof(i)         #prints character
  typeof(get(i))    #prints integer
}

Comment obtenir le type de variable que vous avez dans R

La fonctiontypeof R a un biais pour vous donner le type à la profondeur maximale, par exemple.

library(tibble)

#expression              notes                                  type
#----------------------- -------------------------------------- ----------
typeof(TRUE)             #a single boolean:                     logical
typeof(1L)               #a single numeric with L postfixed:    integer
typeof("foobar")         #A single string in double quotes:     character
typeof(1)                #a single numeric:                     double
typeof(list(5,6,7))      #a list of numeric:                    list
typeof(2i)               #an imaginary number                   complex

#So far so good, but those who wish to keep their sanity go no further
typeof(5 + 5L)           #double + integer is coerced:          double
typeof(c())              #an empty vector has no type:          NULL
typeof(!5)               #a bang before a double:               logical
typeof(Inf)              #infinity has a type:                  double
typeof(c(5,6,7))         #a vector containing only doubles:     double
typeof(c(c(TRUE)))       #a vector of vector of logicals:       logical
typeof(matrix(1:10))     #a matrix of doubles has a type:       list

#Strangeness ahead, there be dragons: step carefully:
typeof(substr("abc",2,2))#a string at index 2 which is 'b' is:  character
typeof(c(5L,6L,7L))      #a vector containing only integers:    integer
typeof(c(NA,NA,NA))      #a vector containing only NA:          logical
typeof(data.frame())     #a data.frame with nothing in it:      list
typeof(data.frame(c(3))) #a data.frame with a double in it:     list
typeof(c("foobar"))      #a vector containing only strings:     character
typeof(pi)               #builtin expression for pi:            double

#OK, I'm starting to get irritated, however, I am also longsuffering:
typeof(1.66)             #a single numeric with mantissa:       double
typeof(1.66L)            #a double with L postfixed             double
typeof(c("foobar"))      #a vector containing only strings:     character
typeof(c(5L, 6L))        #a vector containing only integers:    integer
typeof(c(1.5, 2.5))      #a vector containing only doubles:     double
typeof(c(1.5, 2.5))      #a vector containing only doubles:     double
typeof(c(TRUE, FALSE))   #a vector containing only logicals:    logical

#R is really cramping my style, killing my high, irritation is increasing:
typeof(factor())         #an empty factor has default type:     integer
typeof(factor(3.14))     #a factor containing doubles:          integer
typeof(factor(T, F))     #a factor containing logicals:         integer
typeof(Sys.Date())       #builtin R dates:                      double
typeof(hms::hms(3600))   #hour minute second timestamp          double
typeof(c(T, F))          #T and F are builtins:                 logical
typeof(1:10)             #a builtin sequence of numerics:       integer
typeof(NA)               #The builtin value not available:      logical

#The R coolaid punchbowl has been spiked: stay frosty and keep your head low:
typeof(c(list(T)))       #a vector of lists of logical:         list
typeof(list(c(T)))       #a list of vectors of logical:         list
typeof(c(T, 3.14))       #a vector of logicals and doubles:     double
typeof(c(3.14, "foo"))   #a vector of doubles and characters:   character
typeof(c("foo",list(T))) #a vector of strings and lists:        list
typeof(list("foo",c(T))) #a list of strings and vectors:        list
typeof(TRUE + 5L)        #a logical plus an integer:            integer
typeof(c(TRUE, 5L)[1])   #The true is coerced to 1              integer
typeof(c(c(2i), TRUE)[1])#logical coerced to complex:           complex
typeof(c(NaN, 'batman')) #NaN's in a vector don't dominate:     character
typeof(5 && 4)           #doubles are coerced by order of &&    logical
typeof(8 < 'foobar')     #string and double is coerced          logical
typeof(list(4, T)[[1]])  #a list retains type at every index:   double
typeof(list(4, T)[[2]])  #a list retains type at every index:   logical
typeof(2 ** 5)           #result of exponentiation              double
typeof(0E0)              #exponential lol notation              double
typeof(0x3fade)          #hexidecimal                           double
typeof(paste(3, '3'))    #paste promotes types to string        character
typeof(3 +)           #R pukes on unicode                    error
typeof(iconv("a", "latin1", "UTF-8")) #UTF-8 characters         character
typeof(5 == 5)           #result of a comparison:               logical

Comment obtenir la classe d'une variable que vous avez dans R

La fonctionclass R a un biais pour vous donner le type de conteneur ou de structure encapsulant vos types, par exemple.

library(tibble)

#expression            notes                                    class
#--------------------- ---------------------------------------- ---------
class(matrix(1:10))     #a matrix of doubles has a class:       matrix
class(factor("hi"))     #factor of items is:                    factor
class(TRUE)             #a single boolean:                      logical
class(1L)               #a single numeric with L postfixed:     integer
class("foobar")         #A single string in double quotes:      character
class(1)                #a single numeric:                      numeric
class(list(5,6,7))      #a list of numeric:                     list
class(2i)               #an imaginary                           complex
class(data.frame())     #a data.frame with nothing in it:       data.frame
class(Sys.Date())       #builtin R dates:                       Date
class(sapply)           #a function is                          function
class(charToRaw("hi"))  #convert string to raw:                 raw
class(array("hi"))      #array of items is:                     array

#So far so good, but those who wish to keep their sanity go no further
class(5 + 5L)           #double + integer is coerced:          numeric
class(c())              #an empty vector has no class:         NULL
class(!5)               #a bang before a double:               logical
class(Inf)              #infinity has a class:                 numeric
class(c(5,6,7))         #a vector containing only doubles:     numeric
class(c(c(TRUE)))       #a vector of vector of logicals:       logical

#Strangeness ahead, there be dragons: step carefully:
class(substr("abc",2,2))#a string at index 2 which is 'b' is:  character
class(c(5L,6L,7L))      #a vector containing only integers:    integer
class(c(NA,NA,NA))      #a vector containing only NA:          logical
class(data.frame(c(3))) #a data.frame with a double in it:     data.frame
class(c("foobar"))      #a vector containing only strings:     character
class(pi)               #builtin expression for pi:            numeric

#OK, I'm starting to get irritated, however, I am also longsuffering:
class(1.66)             #a single numeric with mantissa:       numeric
class(1.66L)            #a double with L postfixed             numeric
class(c("foobar"))      #a vector containing only strings:     character
class(c(5L, 6L))        #a vector containing only integers:    integer
class(c(1.5, 2.5))      #a vector containing only doubles:     numeric
class(c(TRUE, FALSE))   #a vector containing only logicals:    logical

#R is really cramping my style, killing my high, irritation is increasing:
class(factor())       #an empty factor has default class:      factor
class(factor(3.14))   #a factor containing doubles:            factor
class(factor(T, F))   #a factor containing logicals:           factor
class(hms::hms(3600)) #hour minute second timestamp            hms difftime
class(c(T, F))        #T and F are builtins:                   logical
class(1:10)           #a builtin sequence of numerics:         integer
class(NA)             #The builtin value not available:        logical

#The R coolaid punchbowl has been spiked: stay frosty and keep your head low:
class(c(list(T)))       #a vector of lists of logical:         list
class(list(c(T)))       #a list of vectors of logical:         list
class(c(T, 3.14))       #a vector of logicals and doubles:     numeric
class(c(3.14, "foo"))   #a vector of doubles and characters:   character
class(c("foo",list(T))) #a vector of strings and lists:        list
class(list("foo",c(T))) #a list of strings and vectors:        list
class(TRUE + 5L)        #a logical plus an integer:            integer
class(c(TRUE, 5L)[1])   #The true is coerced to 1              integer
class(c(c(2i), TRUE)[1])#logical coerced to complex:           complex
class(c(NaN, 'batman')) #NaN's in a vector don't dominate:     character
class(5 && 4)           #doubles are coerced by order of &&    logical
class(8 < 'foobar')     #string and double is coerced          logical
class(list(4, T)[[1]])  #a list retains class at every index:  numeric
class(list(4, T)[[2]])  #a list retains class at every index:  logical
class(2 ** 5)           #result of exponentiation              numeric
class(0E0)              #exponential lol notation              numeric
class(0x3fade)          #hexidecimal                           numeric
class(paste(3, '3'))     #paste promotes class to string       character
class(3 +)           #R pukes on unicode                   error
class(iconv("a", "latin1", "UTF-8")) #UTF-8 characters         character
class(5 == 5)           #result of a comparison:               logical

Obtenez les données storage.modede votre variable

Lorsqu'une variable R est écrite sur le disque, la disposition des données change à nouveau et s'appelle les donnéesstorage.mode . La fonction storage.mode(...)révèle cette information de bas niveau: voir mode, classe, et le type d'objets R . Vous ne devriez pas avoir à vous soucier du mode de stockage de R à moins que vous n'essayiez de comprendre les retards causés par les transferts / coercitions aller-retour qui se produisent lors de l'attribution et de la lecture de données vers et depuis le disque.

Idéologie autour du système de typage triade de R:

Le système de typage du canard de R comporte de l'incertitude. Par analogie, considérons une tasse en céramique, elle peut être utilisée pour contenir un liquide, ou utilisée comme projectile comme une balle de baseball. Le but de la tasse dépend de ses propriétés disponibles et de la fonction qui agit sur elle. Cette fluidité de type permet aux programmeurs une plus grande marge de manœuvre pour rediriger tout type de sortie d'une fonction vers une autre fonction, et R fera de grands efforts pour essayer de lire dans vos pensées et faire quelque chose de raisonnable.

L'idée est que lorsque les programmeurs débutants écrivent des programmes R via un mouvement brownien, comme ils le feront, ils tentent de passer a googah.blimflargdans a vehicle.subspaceresponder(...). Au lieu de vomir une erreur de type, le programme R fait de la gymnastique pour transformer le type et ensuite faire quelque chose d'étonnamment utile. Le programmeur débutant publie le code sur son blog et dit "regardez cette chose formidable que j'ai faite avec 3 lignes de code R! Je ne sais pas comment il sait quoi faire, mais c'est le cas!"

Eric Leschinski
la source
comment identifier par exemple ds <- c (3,4,5,5,3) - que "ds" est exactement un vecteur avec un type numérique?
Max Usanin le
1
Créez votre propre fonction R personnalisée que vous conservez dans votre boîte à outils qui prend un paramètre x. À l'intérieur de la fonction, utilisez des instructions if pour vérifier si le typeof (x) est numérique et si la classe (x) est un vecteur. Si tel est le cas, imprimez la chaîne: "x est exactement un vecteur de type numérique". R ne va pas vous aider dans ce département car ce système de typage triade a une complexité infinie, l'analyse de type est impossible, dès que vous définissez tous les types, quelqu'un en définit un nouveau. Le système de frappe R est de loin le pire que j'ai vu de tous les langages. C'est un incendie de décharge.
Eric Leschinski
6

Vous pouvez utiliser la classe (x) pour vérifier le type de variable. Si l'exigence est de vérifier le type de toutes les variables d'une trame de données, alors sapply (x, class) peut être utilisé.

GauravS
la source
4
> mtcars %>% 
+     summarise_all(typeof) %>% 
+     gather
    key  value
1   mpg double
2   cyl double
3  disp double
4    hp double
5  drat double
6    wt double
7  qsec double
8    vs double
9    am double
10 gear double
11 carb double

J'essaye classet typeoffonctionne, mais tout échoue.

Jiaxiang
la source
1

Conçu pour faire essentiellement l'inverse de ce que vous vouliez, voici l'un de mes jouets à outils:

 lstype<-function(type='closure'){
inlist<-ls(.GlobalEnv)
if (type=='function') type <-'closure'
typelist<-sapply(sapply(inlist,get),typeof)
return(names(typelist[typelist==type]))
}
Carl Witthoft
la source
0

lapply (your_dataframe, class) vous donne quelque chose comme:

$ tikr [1] "facteur"

$ Date [1] "Date"

$ Open [1] "numérique"

$ High [1] "numérique"

... etc.

Dimitar Nentchev
la source