Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a fast way to modify consistent components of a nested list in R?

Tags:

r

nested-lists

I have a vector of values that I wish to use to modify a consistent component of a nested list. Currently I'm using a for loop to do this which is proving quite slow and I'm wondering if there's a faster way to do it.

By way of reproducible example:

#Create Data and List
set.seed(100)
Students <- c("Amy", "Ben", "Caz")
Subject <- c("Maths", "English", "Science")

ExamResults <- lapply(Students, function (r) {
  Scores <- lapply(Subject, function(x) round(runif(4, 0, 100)))
  names(Scores) <- Subject
  Scores
})
names(ExamResults) <- Students

Which creates a list that looks like this:

$Amy
$Amy$Maths
[1] 31 26 55  6

$Amy$English
[1] 47 48 81 37

$Amy$Science
[1] 55 17 62 88

$Ben
$Ben$Maths
[1] 28 40 76 67

$Ben$English
[1] 20 36 36 69

$Ben$Science
[1] 54 71 54 75

$Caz
$Caz$Maths
[1] 42 17 77 88

$Caz$English
[1] 55 28 49 93

$Caz$Science
[1] 35 95 70 89

Now let's say the second maths paper for all students is remarked:

#New Data
MathsRemark <- c(24, 50, 45) #assume in correct (alphabetical) order

And we wish to modify their existing second maths score for these new values. My current solution for doing this is:

#Current Slow Solution
for (i in 1:length(Students)) {
  ExamResults[[i]][["Maths"]][[2]] <- MathsRemark[i]
}

On larger datasets this is proving very slow. Is anyone aware of a faster way to do this? I've been taught to avoid using for loops where vectorising is possible but I can't figure out how to vectorise this problem. Any ideas would be much appreciated.

like image 216
Will T-E Avatar asked Sep 17 '25 04:09

Will T-E


1 Answers

One option is Map().

Map(function(x, y) { x$Maths[2] <- y; x }, ExamResults, MathsRemark)

A second option is to unlist, replace, and relist.

u <- unlist(ExamResults)
relist(replace(u, endsWith(names(u), "Maths2"), MathsRemark), ExamResults)
like image 144
Rich Scriven Avatar answered Sep 18 '25 16:09

Rich Scriven