Adding to one of your sub-questions :
- What other information is needed to fully describe an entity?
In addition to class
, mode
, typeof
, attributes
, str
, and so on, is()
is also worth noting.
is(1)
[1] "numeric" "vector"
While useful, it is also unsatisfactory. In this example, 1
is more than just that; it is also atomic, finite, and a double. The following function should show all that an object is according to all available is.(...)
functions:
what.is <- function(x, show.all=FALSE) {
# set the warn option to -1 to temporarily ignore warnings
op <- options("warn")
options(warn = -1)
on.exit(options(op))
list.fun <- grep(methods(is), pattern = "<-", invert = TRUE, value = TRUE)
result <- data.frame(test=character(), value=character(),
warning=character(), stringsAsFactors = FALSE)
# loop over all "is.(...)" functions and store the results
for(fun in list.fun) {
res <- try(eval(call(fun,x)),silent=TRUE)
if(class(res)=="try-error") {
next() # ignore tests that yield an error
} else if (length(res)>1) {
warn <- "*Applies only to the first element of the provided object"
value <- paste(res,"*",sep="")
} else {
warn <- ""
value <- res
}
result[nrow(result)+1,] <- list(fun, value, warn)
}
# sort the results
result <- result[order(result$value,decreasing = TRUE),]
rownames(result) <- NULL
if(show.all)
return(result)
else
return(result[which(result$value=="TRUE"),])
}
So now we get a more complete picture:
> what.is(1)
test value warning
1 is.atomic TRUE
2 is.double TRUE
3 is.finite TRUE
4 is.numeric TRUE
5 is.vector TRUE
> what.is(CO2)
test value warning
1 is.data.frame TRUE
2 is.list TRUE
3 is.object TRUE
4 is.recursive TRUE
You also get more information with the argument show.all=TRUE
. I am not pasting any example here as the results are over 50 lines long.
Finally, this is meant as a complementary source of information, not as a replacement for any of the other functions mentionned earlier.
EDIT
To include even more "is" functions, as per @Erdogan's comment, you could add this bit to the function:
# right after
# list.fun <- grep(methods(is), pattern = "<-", invert = TRUE, value = TRUE)
list.fun.2 <- character()
packs <- c('base', 'utils', 'methods') # include more packages if needed
for (pkg in packs) {
library(pkg, character.only = TRUE)
objects <- grep("^is.+\\w$", ls(envir = as.environment(paste('package', pkg, sep = ':'))),
value = TRUE)
objects <- grep("<-", objects, invert = TRUE, value = TRUE)
if (length(objects) > 0)
list.fun.2 <- append(list.fun.2, objects[sapply(objects, function(x) class(eval(parse(text = x))) == "function")])
}
list.fun <- union(list.fun.1, list.fun.2)
# ...and continue with the rest
result <- data.frame(test=character(), value=character(),
warning=character(), stringsAsFactors = FALSE)
# and so on...
list(1,2)
which indeed hasmode
,class
andtypeof
of"list"
. If you want to determine if an object has more than one element, you would probably uselength
. – Olivieroserializeme(x)
in R which fully describes everything aboutx
"? Would it start off with a test, for the sake of arguments, as to whetherx
is a list or a vector or function name or whatever? What's the 'top-level' test that would be done first? – Chauvin"string"
is a length 1 vector of type character.c("stringA","stringB")
is a length 2 vector of type character. – Nevermorestr
ordput
– Oliviero"hi"
is a 1-length character vector. If you want aserializeme
function, could you use...serialize
? – Katabaticserialize()
, though it's fairly low level. Depending what you need it for,save()
might be more to your liking. – Modeserialize
to see exactly how it works, which would answer your question, right? – Katabatic