Saving output of a recursive function as a list - r

I'd like to save the output of my recursive function as a list.
> (getNames(74, foo))
[1] "Excavata"
[1] "Excavata"
[1] "Excavata"
[1] "Excavata"
[1] "Stramenopiles"
[1] "Stramenopiles"
[1] "Stramenopiles"
[1] "Excavata"
[1] "Excavata"
[1] "Metazoa"
How do I go about doing this? Maybe this is simpler than I think but I've been stuck for a couple of days!
I don't think the code here matters: the general idea of my question regards saving the output of a recursive function (such as towers of hanoi) as a data type such as a list or a data.frame.

If you really think the exact code doesn't matter:
recursive_add <- function(x, res_list=NULL) {
if (is.null(res_list)) {
res_list <- list()
}
if (x == 26) {
return(res_list)
}
res_list[[x]] <- letters[x]
res_list <- recursive_add(x + 1, res_list)
return(res_list)
}
recursive_add(1)
The default NULL argument allows you to create a new list the first time, but then pass the existing list down to the recursive calls.

Without code to see I'm not sure as to whether it would be useful, but have you considered using rapply? rapply help page its a recursive version of lapply and lapply returns lists as output.

Related

R - Return an object name from a for loop

Using a basic function such as this:
myname<-function(z){
nm <-deparse(substitute(z))
print(nm)
}
I'd like the name of the item to be printed (or returned) when iterating through a list e.g.
for (csv in list(acsv, bcsv, ccsv)){
myname(csv)
}
should print:
acsv
bcsv
ccsv
(and not csv).
It should be noted that acsv, bcsv, and ccsvs are all dataframes read in from csvs i.e.
acsv = read.csv("a.csv")
bcsv = read.csv("b.csv")
ccsv = read.csv("c.csv")
Edit:
I ended up using a bit of a compromise. The primary goal of this was not to simply print the frame name - that was the question, because it is a prerequisite for doing other things.
I needed to run the same functions on four identically formatted files. I then used this syntax:
for(i in 1:length(csvs)){
cat(names(csvs[i]), "\n")
print(nrow(csvs[[i]]))
print(nrow(csvs[[i]][1]))
}
Then the indexing of nested lists was utilized e.g.
print(nrow(csvs[[i]]))
which shows the row count for each of the dataframes.
print(nrow(csvs[[i]][1]))
Then provides a table for the first column of each dataframe.
I include this because it was the motivator for the question. I needed to be able to label the data for each dataframe being examined.
The list you have constructed doesn't "remember" the expressions it was constructed of anymore. But you can use a custom constructor:
named.list <- function(...) {
l <- list(...)
exprs <- lapply(substitute(list(...))[-1], deparse)
names(l) <- exprs
l
}
And so:
> named.list(1+2,sin(5),sqrt(3))
$`1 + 2`
[1] 3
$`sin(5)`
[1] -0.9589243
$`sqrt(3)`
[1] 1.732051
Use this list as parameter to names, as Thomas suggested:
> names(mylist(1+2,sin(5),sqrt(3)))
[1] "1 + 2" "sin(5)" "sqrt(3)"
To understand what's happening here, let's analyze the following:
> as.list(substitute(list(1+2,sqrt(5))))
[[1]]
list
[[2]]
1 + 2
[[3]]
sqrt(5)
The [-1] indexing leaves out the first element, and all remaining elements are passed to deparse, which works because of...
> lapply(as.list(substitute(list(1+2,sqrt(5))))[-1], class)
[[1]]
[1] "call"
[[2]]
[1] "call"
Note that you cannot "refactor" the call list(...) inside substitute() to use simply l. Do you see why?
I am also wondering if such a function is already available in one of the countless R packages around. I have found this post by William Dunlap effectively suggesting the same approach.
I don't know what your data look like, so here's something made up:
csvs <- list(acsv=data.frame(x=1), bcsv=data.frame(x=2), ccsv=data.frame(x=3))
for(i in 1:length(csvs))
cat(names(csvs[i]), "\n")

binding a function to a list

Where am I missing something?
FUN<-list()
make.FUN<-function(i) function(n) i+n
for (i in 1:3) FUN[[i]]<-make.FUN(i)
FUN[[1]](1)
If I check FUN assignment I get a reference to a nested function (as expected):
> FUN
[[1]]
function (n)
i + n
<environment: 0x03adfad0>
[[2]]
function (n)
i + n
<environment: 0x03ae0834>
[[3]]
function (n)
i + n
<environment: 0x03ae0604>
>
Problem is that if I check:
> FUN[[1]](1)
[1] 4
>
when I expect 2! (clearly it is overwriting the last value)
On the other hand, if I manually assign for each element of the list:
FUN[[1]]<-make.FUN(1)
FUN[[2]]<-make.FUN(2)
FUN[[3]]<-make.FUN(3)
I get the correct answer:
> FUN[[1]](1)
[1] 2
> FUN[[2]](3)
[1] 5
>
I could workaround using do.call, but I can't realize what the interpreter is assuming in the first loop, or why is do.call mandatory in this case.
When I try:
FUN<-list()
make.FUN<-function(i) function(n) i+n
for (i in 1:3) FUN[[i]]<-do.call('make.FUN',list(i))
I get (as expected):
> FUN[[1]](2)
[1] 3
Any clue? (it only happens when using lists)
Your question is almost a copy-paste of the force example from the doc. You need to do:
FUN <- list()
make.FUN <- function(i) { force(i); function(n) i+n }
for (i in 1:3) FUN[[i]] <- make.FUN(i)
FUN[[1]](1)
# [1] 2
Relevant details from ?force:
force forces the evaluation of a formal argument. This can be useful if the argument will be captured in a closure by the lexical scoping rules and will later be altered by an explicit assignment or an implicit assignment in a loop or an apply function.

Is there an S4 equivalent to unlist()?

I have some experience working with S4 objects and their slots, so I know how to access specific slots and sub-slots. What I'd like to learn is how to "de-slotify" an object in the way that unlist takes apart an S3 list.
My immediate goal is to have an S4 counterpart to one of my toys which returns the number of elements of an object:
lssize<-function(items){
if (any(sapply(sapply(items,get),typeof)=='closure')){
warning('Closures in list, will ignore.')
items<-items[(sapply(sapply(bar,get),typeof)=='closure')!=TRUE]
}
sizes<-sapply(sapply(sapply(sapply(items,get,simplify=F), unlist,simplify=F), as.vector,simplify=F), length)
return(sizes)
}
(no fair laughing at my code :-) ). I am hoping not to have to write some recursion routine which extracts slots one at a time to convert them.
Edit: I know object.size will return the bytecount; not what I'm after here.
(This is revised to be closer to a previous, deleted answer, using slotName and slot rather than relying on attributes). We could write a function that tests whether an instance is an S4 object, and if so extracts all the slots as a list and recurses
f = function(x) {
if (isS4(x)) {
nms <- slotNames(x)
names(nms) <- nms
lapply(lapply(nms, slot, object=x), f)
} else x
}
and then
A = setClass("A", representation(x="numeric"))
B = setClass("B", representation(a="A", b="numeric"))
f(B())
to arrive at a plain old list that we could use for whatever purposes we want.
$a
$a$x
numeric(0)
$a$class
[1] "A"
attr(,"package")
[1] ".GlobalEnv"
$b
numeric(0)
$class
[1] "B"
attr(,"package")
[1] ".GlobalEnv"
f might need to be enhanced, e.g., to handle NULL values or S4 classes made from S3 classes via setOldClass. The code to validObject would be my choice of places to look for a more comprehensive traversal.
A generalization might make a visitor, along the lines of
visitLeavesWith <-
function(object, FUN, ...)
{
f = function(x) {
if (isS4(x)) {
slots <- setNames(slotNames(x), slotNames(x))
lapply(lapply(slots, slot, object=x), f)
} else FUN(x, ...)
}
f(object)
}
e.g.,
visitLeavesWith(B(), length)

force-evaluate an object being passed as an argument to a function

I would like to pass the value of an object as an argument to a function.
# This is my object
anObject <- "an_unkown_string"
# I would like to do the equivalent of:
someFunc("an_unkown_string")
# .. by somehow calling on the object containing the string
someFunc( ??? (anObject) )
For example, with the sample function below (based on save()):
someFunc <- function(...) {
names <- as.character(substitute(list(...)))[-1L]
return(names)
}
# Ideally, the output would be:
someFunc( ??? (anObject) )
[1] "an_unkown_string"
I do not have access to modify someFunc
I have tried the following, but with no success.
someFunc(Name_of_Object)
someFunc(eval(Name_of_Object))
someFunc(evalq(Name_of_Object))
someFunc(force(Name_of_Object))
someFunc(eval(parse(text=Name_of_Object)))
Any help is appreciated.
How about
> do.call(someFunc, list(anObject))
[1] "an_unkown_string"
Or you could make a wrapper
myWrap <- function(...) {
do.call(someFunc, as.list(...))
}
> myWrap(anObject)
[1] "an_unkown_string"
Another way to construct a call and evaluate it:
> call("someFunc", anObject)
someFunc("an_unkown_string")
> eval(call("someFunc", anObject))
[1] "an_unkown_string"
I suppose I should mention that ?do.call says
The behavior of some functions, such as substitute, will not be the same for functions evaluated using do.call as if they were evaluated from the interpreter. The precise semantics are currently undefined and subject to change.
Nevertheless, for now at least, anObject is evaluated when the call is constructed (in the call to call or do.call), so substitute finds "an_unknown_string" instead of "anObject".
I'm puzzled. Why are you trying to make this more complex than it realy is?
someFunc <- function(obj) {
return(obj)
}
> someFunc(anObject)
[1] "an_unkown_string"

Can the print() command in R be quieted?

In R some functions can print information and return values, can the print be silenced?
For example:
print.and.return <- function() {
print("foo")
return("bar")
}
returns
> print.and.return()
[1] "foo"
[1] "bar"
>
I can store the return like:
> z <- print.and.return()
[1] "foo"
> z
[1] "bar"
>
Can I suppress the print of "foo"?
You may use hidden functional nature of R, for instance by defining function
deprintize<-function(f){
return(function(...) {capture.output(w<-f(...));return(w);});
}
that will convert 'printing' functions to 'silent' ones:
noisyf<-function(x){
print("BOO!");
sin(x);
}
noisyf(7)
deprintize(noisyf)(7)
deprintize(noisyf)->silentf;silentf(7)
?capture.output
If you absolutely need the side effect of printing in your own functions, why not make it an option?
print.and.return <- function(..., verbose=TRUE) {
if (verbose)
print("foo")
return("bar")
}
> print.and.return()
[1] "foo"
[1] "bar"
> print.and.return(verbose=FALSE)
[1] "bar"
>
I agree with hadley and mbq's suggestion of capture.output as the most general solution. For the special case of functions that you write (i.e., ones where you control the content), use message rather than print. That way you can suppress the output with suppressMessages.
print.and.return2 <- function() {
message("foo")
return("bar")
}
# Compare:
print.and.return2()
suppressMessages(print.and.return2())
I know that I might be resurrecting this post but someone else might find it as I did. I was interested in the same behaviour in one of my functions and I just came across "invisibility":
It has the same use of return() but it just don't print the value returned:
invisible(variable)
Thus, for the example given by #ayman:
print.and.return2 <- function() {
message("foo")
invisible("bar")
}

Resources