Retrieving Nested List of Lists from R to JMPHello All,
I am pulling information from an API using R and retrieving the information into JMP. I have been successful with the data retrieval until the API returns a nested list of lists.
I am thinking the error is not prompted from R side because, I am able to execute the same piece of code in R Studio without any errors . Even in JSL , the error only occurs when I am trying to retrieve the object from R to JMP using R Get(). I get the error shown below when I try :
R Get(A) ;
R Get () supports retrieval of lists - is there something I am doing wrong ?

Also, since I have nested lists of lists - wondering if looping through the contents of the list is the most efficient way to extract the data out ?
Re: Retrieving Nested List of Lists from R to JMPThat is more complex. In R, all arguments are passed by value, so even in the first call modifying 'l' actually creates a copy of it inside the function's namespace and the list you are trying to modify is untouched. In subsequent calls you are operating on smaller versions of 'l' which, again, do not reference back to your actual list. To fix the list you would need to either save a reference back to the namespace where the list resides and then use the loc argument to figure out which part to cast, or build a new copy of the list and return it. I do the latter here:
#verbose levels
# 0 nothing
# 1 Errors only
# 2 Everything
isvalid <- function(l, fix=FALSE, verbose = 2, loc = {} ) {
if(length(loc) > 10) throw("List is too deep, maybe you have raw data?")
for( i in seq_along(l) ) {
if( class(l[[i]]) == "list" ) {
#If a list, check recurse through it, fixing errors along the way if necessary
if (verbose > 1) print(paste0("Found list at: ", paste(c(loc, i), collapse = ", ")))
l[[i]] <- isvalid(l[[i]], fix=fix, verbose=verbose, loc=c(loc, i))
} else if (!(class(l[[i]]) %in% c("numeric", "character", "NULL"))) {
#If not valid data, try to cast as a list, or throw an error
if (verbose > 0) print(paste0("Invalid data (", class(l[[i]]), ") found at: ", paste(c(loc, i), collapse = ", ")))
if( fix ) {
#Cast as a list
l[[i]] <- as.list(l[[i]])
#Make sure it worked
if( class(l[[i]]) == "list" ) {
#If it is a list, recurse through it
if (verbose > 0) print(paste0("Successfully cast data as a list at: ", paste(c(loc, i), collapse = ", ")))
l[[i]] <- isvalid(l[[i]], fix=fix, verbose=verbose, loc=c(loc, i))
} else {
#Throw a message if failed, not sure what might cause this
errmsg <= paste0("Failed to cast '", class(l[[i]]), "' as a list at: ", paste(c(loc, i), collapse = ", "))
throw( errmsg )
}
}
} else {
#Found valid data
if (verbose > 1) print(paste0("Found ", class(l[[i]]), " at: ", paste(c(loc, i), collapse = ", ")))
}
}
#Return this part of the list unless not fixing anything and this is the first call
return(if((!fix) & (length(loc) == 0)) {invisible()} else {l} )
}
#A list with a problem
lst <- list(list("a", "b",data.frame(a=c(1,2))), 2)
#Look for problems
isvalid(lst, verbose = 1)
#Fix problems
lst <- isvalid(lst, fix=TRUE, verbose = 1)
#Show the new data structure
isvalid(lst, verbose = 2)
Note that I tried including raw binary data inside the list and it recursed until I got an overflow error. If you run into that you might need to do something else.
Re: Retrieving Nested List of Lists from R to JMP@ih,
That is leading us in the right track, If I am not being greedy, I would like to venture out and ask one more question .
isvalid <- function(l, loc = {} )
{
for( i in seq_along(l) )
{
if( class(l[[i]]) == "list" )
{
isvalid(l[[i]], c(loc, i))
} else if (!(class(l[[i]]) %in% c("numeric", "character")))
{
l[i] <- as.list(l[i])
#print(paste0("Invalid data found at: ", paste(c(loc, i), collapse = ", ")))
} else
{
#print(paste0("Valid data found at: ", paste(c(loc, i), collapse = ", ")))
}
}
}
isvalid(DesResult)I added one line to basically cast the invalid data found into a list - hoping that this would fix the issue. However, I don't think it worked as I expected. Any thoughts on how to fix that ?
Re: Retrieving Nested List of Lists from R to JMPI often get strange errors when trying to import invalid data types. You might try checking every element in your list to make sure it is either a list, a number, or a string. Here is one way to do that (not thoroughly tested):
isvalid <- function(l, loc = {} ) {
for( i in seq_along(l) ) {
if( class(l[[i]]) == "list" ) {
isvalid(l[[i]], c(loc, i))
} else if (!(class(l[[i]]) %in% c("numeric", "character"))) {
print(paste0("Invalid data found at: ", paste(c(loc, i), collapse = ", ")))
} else {
#print(paste0("Valid data found at: ", paste(c(loc, i), collapse = ", ")))
}
}
}
lst = list(list("a", "b",data.frame(a=c(1,2))), 2)
isvalid(lst)Which returns:
> lst = list(list("a", "b",data.frame(a=c(1,2))), 2)
> isvalid(lst)
[1] "Invalid data found at: 1, 3"Re: Retrieving Nested List of Lists from R to JMP@ih,
In my case, I am not trying to subscript into the lists. I tried your example and it works perfectly, however, when I try the exact same thing on my end , I don't understand why I am failing.
I checked if the data is stored as a list in R and it is indeed a list .

In JMP , here is what I do :
DesResult = R Get("DesResult"); It still gives the same error , but that makes no sense because your example clearly demonstrates that it should be retrievable
Re: Retrieving Nested List of Lists from R to JMPR Get will retrieve nested lists from R. You need to get the whole list (I do not believe you can subscript in the R Get command) and it struggles with data frames containing lists, or anything other than numbers and characters.
Names default to here( 1 );
R Init();
R Submit( "\[
a <- list( 1, 2, list("a", list( "b", "c" ) ) )
]\");
a = R Get( "a" );
Show( a[3][2][1] );
R Term();