4

I have a list which contains more lists of lists:

results <- sapply(c(paste0("cv_", seq(1:50)), "errors"), function(x) NULL)

## Locations for results to be stored
step_results <- sapply(c("myFit", "forecast", "errors"), function(x) NULL)
step_errors <- sapply(c("MAE", "MSE", "sign_accuracy"), function(x) NULL)
final_error <- sapply(c("MAE", "MSE", "sign_accuracy"), function(x) NULL)

for(i in 1:50){results[[i]] <- step_results}
for(i in 1:50){results[[i]][[3]] <- step_errors}
results$errors <- final_error

Now in this whole structure, I would like to sum up all the values in sign_accuracy and save them in results$errors$sign_accuracy

I could maybe do this with a for-loop, indexing with i:

## This is just an example - it won't actually work!
sign_acc <- matrix(nrow = 50, ncol = 2)
for (i in 1:50){
     sign_acc[i, ] <- `results[[i]][[3]][[3]]`
     results$errors$sign_accuracy <- sign_acc
}

If I remember correctly, in Matlab there is something like list(:), which means all elements. In Python I have seen something like list(0:-1), which also means all elements.

What is the elegent R equivalent? I don't really like loops.

I have seen methods using the apply family of functions. With something like apply(data, "[[", 2), but can't get it to work for deeper lists.

2 Answers 2

3

Did you try with c(..., recursive)?

Here is an option with a short example at the end:

sumList <- function(l, label) {
    lc <- c(l, recursive=T)
    filter <- grepl(paste0("\\.",label, "$"), names(lc)) | (names(lc) == label)
    nums <- lc[filter]
    return(sum(as.numeric(nums)))
}

ex <- list(a=56,b=list("5",a=34,list(c="3",a="5")))
sumList(ex,"a")
Sign up to request clarification or add additional context in comments.

1 Comment

So long as no terrible person names a list item "a.b.c" or something like that...
1

In this case, you can do what you want with

results$errors$sign_accuracy <- do.call(sum, lapply(results, function(x){x[[3]][[3]]}))

lapply loops through the first layer of results, and pulls out the third element of the third element for each. do.call(sum catches all the results and sums them.

The real problems with lists arise when the nesting is more irregular, or when you need to loop through more than one index. It can always be done in the same way, but it gets extraordinarily ugly very quickly.

1 Comment

This was the solution I actually ended up using, thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.