Pobierz typ wszystkich zmiennych

118

W R chciałbym pobrać listę zmiennych globalnych na końcu mojego skryptu i iterować po nich. Oto mój kod

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

Mój problem polega na tym, że typeof(i)zawsze zwraca, characternawet jeśli jest zmienna ai cnie jest zmienną znakową. Jak mogę uzyskać oryginalny typ zmiennej wewnątrz pętli for?

Konrad Rudolph
źródło
Uwaga dla osób czytających to pytanie: typeof()podaje bardzo ogólną informację o tym, jak obiekt jest przechowywany w pamięci. W większości przypadków użycia, jeśli chcesz wiedzieć, dobre informacje o zmiennej x, dostaniesz więcej przydatnych informacji z class(x), is(x)lub str(x)(w kolejności ile zapewniają one szczegółowo). Zobacz odpowiedź Erica poniżej, aby zobaczyć przykłady tego, co typeof()mówi: czynniki są integer; listy, ramki danych, obiekty modeli, inne zaawansowane obiekty to po prostu list...
Gregor Thomas

Odpowiedzi:

109

Aby getuzyskać wartość, a nie nazwę znaku obiektu, należy użyć ls:

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

Alternatywnie, dla przedstawionego problemu możesz użyć eapply:

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

$a
[1] "double"

$b
[1] "character"

$c
[1] "list"
James
źródło
Pracuj doskonale. Czy wiesz, czy istnieje jakikolwiek spadek wydajności, jeśli metoda get () jest używana do znalezienia typu kilku dużych ramek danych, które mogą znajdować się na liście zmiennych zwracanych przez obiekty ()?
1
getma swoich krytyków i wyobrażam sobie, eapplyże byłby szybszy niż interpretowana pętla. Ale jest tylko jeden sposób, aby się tego dowiedzieć ...
James
17

Jak uzyskać typ zmiennej ukrytej pod obiektem globalnym:

Wszystko, czego potrzebujesz, znajduje się w podręczniku R dotyczącym podstawowych typów: https://cran.r-project.org/doc/manuals/R-lang.html#Basic-types

Twoje object()potrzeby muszą zostać spenetrowane, get(...)zanim będziesz mógł zajrzeć do środka. Przykład:

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

Jak uzyskać typ zmiennej, którą masz w R

R funkcjatypeof ma nastawienie, aby dać Ci typ na maksymalnej głębokości, na przykład.

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

Jak uzyskać klasę zmiennej, którą masz w R

R funkcjaclass ma nastawienie, aby dać Ci typ pojemnika lub struktura enkapsulacji swoich typów, na przykład.

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

Pobierz dane storage.modeswojej zmiennej

Kiedy zmienna R jest zapisywana na dysku, układ danych zmienia się ponownie i nazywany jest danymistorage.mode . Funkcja storage.mode(...)ujawnia te informacje niskiego poziomu: patrz Tryb, klasa i typ obiektów R . Nie powinieneś martwić się o tryb przechowywania w R., chyba że próbujesz zrozumieć opóźnienia spowodowane rzutami / wymuszeniami w obie strony, które występują podczas przypisywania i odczytu danych do iz dysku.

Ideologia wokół systemu typowania triady R:

System pisania kaczego w R ma w sobie niepewność. Jako analogię rozważmy ceramiczną filiżankę, która może być używana do przechowywania płynu lub jako pocisk, jak piłka do baseballu. Przeznaczenie kubka zależy od jego dostępnych właściwości i oddziałującej na nie funkcji. Ta płynność typu pozwala programistom na większą swobodę w przekierowywaniu dowolnego rodzaju danych wyjściowych z jednej funkcji do innej, a R dołoży wszelkich starań, aby spróbować czytać w twoich myślach i zrobić coś rozsądnego.

Chodzi o to, że gdy początkujący programiści piszą programy w języku R za pomocą ruchów Browna, tak jak to robią, próbują przekazać a googah.blimflargdo a vehicle.subspaceresponder(...). Zamiast zwymiotować błąd typu, program R wykonuje gimnastykę, aby przekształcić typ, a następnie zrobić coś zaskakująco użytecznego. Początkujący programista umieszcza kod na swoim blogu i mówi: „Spójrz na tę niesamowitą rzecz, którą zrobiłem z 3 liniami kodu R! Nie mam pojęcia, skąd wie, co robić, ale tak jest!”

Eric Leschinski
źródło
jak rozpoznać np. ds <- c (3,4,5,5,3) - że „ds” jest dokładnie wektorem zawierającym typ liczbowy?
Max Usanin
1
Utwórz własną niestandardową funkcję R, którą będziesz przechowywać w skrzynce narzędziowej, która przyjmuje parametr x. Wewnątrz funkcji użyj instrukcji if, aby sprawdzić, czy typeof (x) jest liczbowy i czy klasa (x) jest wektorem. Jeśli tak, wypisz ciąg: "x jest dokładnie wektorem typu numerycznego". R nie pomoże ci w tym dziale, ponieważ ten system pisania triady ma nieskończoną złożoność, analiza typów jest niemożliwa, gdy tylko zdefiniujesz wszystkie typy, ktoś definiuje nowy. System pisania w R jest zdecydowanie najgorszym ze wszystkich języków, jakie widziałem. To pożar składowiska.
Eric Leschinski
6

Możesz użyć class (x), aby sprawdzić typ zmiennej. Jeśli wymaganiem jest sprawdzenie wszystkich zmiennych typu ramki danych, można użyć sapply (x, class).

GauravS
źródło
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

Próbuję classi typeofdziała, ale wszystko zawodzi.

Jiaxiang
źródło
1

Zaprojektowany, aby zasadniczo robić to, co chciałeś, oto jedna z moich zabawek z zestawu narzędzi:

 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
źródło
0

lapply (your_dataframe, class) daje coś takiego:

$ tikr [1] "współczynnik"

$ Date [1] "Data"

$ Open [1] "numeryczne"

$ High [1] „numeryczne”

... itd.

Dimitar Nentchev
źródło