Obtener el tipo de todas las variables

118

En R, me gustaría recuperar una lista de variables globales al final de mi script e iterar sobre ellas. Aqui esta mi codigo

#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'
}

Mi problema es que typeof(i)siempre regresa characteraunque sea variable ay cno sean variables de carácter. ¿Cómo puedo obtener el tipo original de variable dentro del bucle for?

Konrad Rudolph
fuente
Nota para las personas que lean esta pregunta: typeof()proporciona una información muy genérica sobre cómo se almacena el objeto en la memoria. Para la mayoría de los casos de uso, si usted quiere saber una buena información sobre una variable x, obtendrá una información más útil a partir de class(x), is(x)o str(x)(en orden de la cantidad de detalles que proveen). Vea la respuesta de Eric a continuación para ver ejemplos de lo que typeof()le dice: los factores son integer; listas, marcos de datos, objetos modelo, otros objetos avanzados son solo list...
Gregor Thomas

Respuestas:

109

Debe usar getpara obtener el valor en lugar del nombre del carácter del objeto como lo devuelve ls:

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

Alternativamente, para el problema tal como se presenta, es posible que desee utilizar eapply:

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

$a
[1] "double"

$b
[1] "character"

$c
[1] "list"
James
fuente
Trabaja perfectamente. ¿Sabe si hay alguna penalización en el rendimiento si se usa get () para encontrar el tipo de varios marcos de datos grandes que pueden estar presentes en la lista de variables devuelta por objetos ()?
1
gettiene sus críticos y me imagino eapplyque sería más rápido que un bucle interpretado. Pero solo hay una forma de averiguarlo ...
James
17

Cómo obtener el tipo de variable cuando se oculta debajo de un objeto global:

Todo lo que necesita está en el manual de R sobre tipos básicos: https://cran.r-project.org/doc/manuals/R-lang.html#Basic-types

Sus object()necesidades a ser penetrados con get(...)antes de poder ver el interior. Ejemplo:

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

Cómo obtener el tipo de variable que tienes en R

La funcióntypeof R tiene un sesgo para darle el tipo a la profundidad máxima, por ejemplo.

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

Cómo obtener la clase de una variable que tienes en R

La funciónclass R tiene un sesgo para darle el tipo de contenedor o estructura que encapsula sus tipos, por ejemplo.

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

Obtén los datos storage.modede tu variable

Cuando se escribe una variable R en el disco, el diseño de los datos cambia una vez más y se denomina datosstorage.mode . La función storage.mode(...)revela esta información bajo nivel: véase modo, clase y tipo de objetos R . No debería tener que preocuparse por el modo de almacenamiento de R a menos que esté tratando de comprender los retrasos causados ​​por las transmisiones / coerciones de ida y vuelta que se producen al asignar y leer datos hacia y desde el disco.

Ideología en torno al sistema de tipificación de la tríada de R:

El sistema de tipificación de pato de R tiene incertidumbre. Como analogía, considere una taza de cerámica, puede usarse para contener un líquido o usarse como un proyectil como una pelota de béisbol. El propósito de la taza depende de sus propiedades disponibles y de la función que actúa sobre ella. Esta fluidez de tipo permite a los programadores un mayor margen de maniobra para redirigir cualquier tipo de salida de una función a otra, y R hará todo lo posible para intentar leer tu mente y hacer algo razonable.

La idea es que cuando los programadores novatos escriben programas en R a través del movimiento browniano, como lo harán, intenten pasar un googah.blimflargarchivo a vehicle.subspaceresponder(...). En lugar de vomitar un error de tipo, el programa R hace gimnasia para transformar el tipo y luego hacer algo sorprendentemente útil. El programador novato publica el código en su blog y dice: "¡Mira esta cosa tremenda que hice con 3 líneas de código R! ¡No tengo idea de cómo sabe qué hacer, pero lo hace!"

Eric Leschinski
fuente
¿Cómo identificar, por ejemplo, ds <- c (3,4,5,5,3) - que "ds" es exactamente un vector que contiene un tipo numérico?
Max Usanin
1
Crea tu propia función R personalizada que guardas en tu caja de herramientas que toma un parámetro x. Dentro de la función use instrucciones if para verificar si el tipo de (x) es numérico y si la clase (x) es un vector. Si es así, imprima la cadena: "x es exactamente un vector con un tipo numérico". R no te va a ayudar en este departamento porque este sistema de tipificación de tríadas tiene una complejidad infinita, el análisis de tipos es imposible, tan pronto como defines todos los tipos, alguien define uno nuevo. El sistema de escritura R es, con mucho, el peor que he visto de cualquier idioma. Es un incendio en un vertedero.
Eric Leschinski
6

Puede usar class (x) para verificar el tipo de variable. Si el requisito es verificar el tipo de todas las variables de un marco de datos, se puede usar sapply (x, class).

GauravS
fuente
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

Intento classy typeoffunciona, pero todo falla.

Jiaxiang
fuente
1

Diseñado para hacer esencialmente lo contrario de lo que querías, aquí tienes uno de los juguetes de mi kit de herramientas:

 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
fuente
0

lapply (your_dataframe, class) te da algo como:

$ tikr [1] "factor"

$ Fecha [1] "Fecha"

$ Abrir [1] "numérico"

$ Alto [1] "numérico"

... etc.

Dimitar Nentchev
fuente