R interpreter has a duck-typing memory allocation system. There is no builtin method to tell you the datatype of your pointer to memory. Duck typing is done for speed, but turned out to be a bad idea because now statements such as: print(is.integer(5))
returns FALSE and is.integer(as.integer(5))
returns TRUE. Go figure.
The R-manual on basic types: https://cran.r-project.org/doc/manuals/R-lang.html#Basic-types
The best you can hope for is to write your own function to probe your pointer to memory, then use process of elimination to decide if it is suitable for your needs.
Your object()
needs to be penetrated with get(...)
before you can see inside. Example:
a <- 10
myGlobals <- objects()
for(i in myGlobals){
typeof(i) #prints character
typeof(get(i)) #prints integer
}
The R function typeof
has a bias to give you the type at maximum depth, for example.
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
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
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
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
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
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
The R function class
has a bias to give you the type of container or structure encapsulating your types, for example.
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
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
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
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
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
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
storage.mode
of your variable:When an R variable is written to disk, the data layout changes again, and is called the data's storage.mode
. The function storage.mode(...)
reveals this low level information: see Mode, Class, and Type of R objects. You shouldn't need to worry about R's storage.mode unless you are trying to understand delays caused by round trip casts/coercions that occur when assigning and reading data to and from disk.
gettype(your_variable)
:Run this R code then adapt it for your purposes, it'll make a pretty good guess as to what type it is.
get_type <- function(variable){
sz <- as.integer(length(variable)) #length of your variable
tof <- typeof(variable) #typeof your variable
cls <- class(variable) #class of your variable
isc <- is.character(variable) #what is.character() has to say about it.
d <- dim(variable) #dimensions of your variable
isv <- is.vector(variable)
if (is.matrix(variable)){
d <- dim(t(variable)) #dimensions of your matrix
}
#observations ----> datatype
if (sz>=1 && tof == "logical" && cls == "logical" && isv == TRUE){ return("vector of logical") }
if (sz>=1 && tof == "integer" && cls == "integer" ){ return("vector of integer") }
if (sz==1 && tof == "double" && cls == "Date" ){ return("Date") }
if (sz>=1 && tof == "raw" && cls == "raw" ){ return("vector of raw") }
if (sz>=1 && tof == "double" && cls == "numeric" ){ return("vector of double") }
if (sz>=1 && tof == "double" && cls == "array" ){ return("vector of array of double") }
if (sz>=1 && tof == "character" && cls == "array" ){ return("vector of array of character") }
if (sz>=0 && tof == "list" && cls == "data.frame" ){ return("data.frame") }
if (sz>=1 && isc == TRUE && isv == TRUE){ return("vector of character") }
if (sz>=1 && tof == "complex" && cls == "complex" ){ return("vector of complex") }
if (sz==0 && tof == "NULL" && cls == "NULL" ){ return("NULL") }
if (sz>=0 && tof == "integer" && cls == "factor" ){ return("factor") }
if (sz>=1 && tof == "double" && cls == "numeric" && isv == TRUE){ return("vector of double") }
if (sz>=1 && tof == "double" && cls == "matrix"){ return("matrix of double") }
if (sz>=1 && tof == "character" && cls == "matrix"){ return("matrix of character") }
if (sz>=1 && tof == "list" && cls == "list" && isv == TRUE){ return("vector of list") }
if (sz>=1 && tof == "closure" && cls == "function" && isv == FALSE){ return("closure/function") }
return("it's pointer to memory, bruh")
}
assert <- function(a, b){
if (a == b){
cat("P")
}
else{
cat("\nFAIL!!! Sniff test:\n")
sz <- as.integer(length(variable)) #length of your variable
tof <- typeof(variable) #typeof your variable
cls <- class(variable) #class of your variable
isc <- is.character(variable) #what is.character() has to say about it.
d <- dim(variable) #dimensions of your variable
isv <- is.vector(variable)
if (is.matrix(variable)){
d <- dim(t(variable)) #dimensions of your variable
}
if (!is.function(variable)){
print(paste("value: '", variable, "'"))
}
print(paste("get_type said: '", a, "'"))
print(paste("supposed to be: '", b, "'"))
cat("\nYour pointer to memory has properties:\n")
print(paste("sz: '", sz, "'"))
print(paste("tof: '", tof, "'"))
print(paste("cls: '", cls, "'"))
print(paste("d: '", d, "'"))
print(paste("isc: '", isc, "'"))
print(paste("isv: '", isv, "'"))
quit()
}
}
#these asserts give a sample for exercising the code.
assert(get_type(TRUE), "vector of logical") #everything is a vector in R by default.
assert(get_type(c(TRUE)), "vector of logical") #c() just casts to vector
assert(get_type(c(c(TRUE))),"vector of logical") #casting vector multiple times does nothing
assert(get_type(!5), "vector of logical") #bang inflicts 'not truth-like'
assert(get_type(1L), "vector of integer") #naked integers are still vectors of 1
assert(get_type(c(1L, 2L)), "vector of integer") #Longs are not doubles
assert(get_type(c(1L, c(2L, 3L))),"vector of integer") #nested vectors of integers
assert(get_type(c(1L, c(TRUE))), "vector of integer") #logicals coerced to integer
assert(get_type(c(FALSE, c(1L))), "vector of integer") #logicals coerced to integer
assert(get_type("foobar"), "vector of character") #character here means 'string'
assert(get_type(c(1L, "foobar")), "vector of character") #integers are coerced to string
assert(get_type(5), "vector of double")
assert(get_type(5 + 5L), "vector of double")
assert(get_type(Inf), "vector of double")
assert(get_type(c(5,6,7)), "vector of double")
assert(get_type(NaN), "vector of double")
assert(get_type(list(5)), "vector of list") #your list is in a vector.
assert(get_type(list(5,6,7)), "vector of list")
assert(get_type(c(list(5,6,7))),"vector of list")
assert(get_type(list(c(5,6),T)),"vector of list") #vector of list of vector and logical
assert(get_type(list(5,6,7)), "vector of list")
assert(get_type(2i), "vector of complex")
assert(get_type(c(2i, 3i, 4i)), "vector of complex")
assert(get_type(c()), "NULL")
assert(get_type(data.frame()), "data.frame")
assert(get_type(data.frame(4,5)),"data.frame")
assert(get_type(Sys.Date()), "Date")
assert(get_type(sapply), "closure/function")
assert(get_type(charToRaw("hi")),"vector of raw")
assert(get_type(c(charToRaw("a"), charToRaw("b"))), "vector of raw")
assert(get_type(array(4)), "vector of array of double")
assert(get_type(array(4,5)), "vector of array of double")
assert(get_type(array("hi")), "vector of array of character")
assert(get_type(factor()), "factor")
assert(get_type(factor(3.14)), "factor")
assert(get_type(factor(TRUE)), "factor")
assert(get_type(matrix(3,4,5)), "matrix of double")
assert(get_type(as.matrix(5)), "matrix of double")
assert(get_type(matrix("yatta")),"matrix of character")
I put in a C++/Java/Python ideology here that gives me the scoop of what the memory most looks like. R triad typing system is like trying to nail spaghetti to the wall, <-
and <<-
will package your matrix to a list when you least suspect. As the old duck-typing saying goes: If it waddles like a duck and if it quacks like a duck and if it has feathers, then it's a duck.