GrafZahl
GrafZahl

Reputation: 23

Using lapply on a diverse list in R

I created a list containing sub-lists, each sub-list containing information for one task I want R to do.

df <- as.data.frame(matrix(1:6 , ncol =2 , nrow = 3))
colnames(df) <- c("Col1", "Col2")
myList <- list()
myList[["Dataset1"]] <- list()
myList[["Dataset1"]]["Function"] <- "mean" 
myList[["Dataset1"]][["DataFrame"]] <- df
myList[["Dataset2"]] <- list()
myList[["Dataset2"]]["Function"] <- "lm" 
myList[["Dataset2"]][["DataFrame"]] <- df*2

Now I want R to apply the Function to the Dataframe and Store the results in a new List. How do I do that best?

So far I had two ideas: I either use lapply to run through the list, each time accessing several items from the sub-list, supplying it to a new function

myResult <- lapply(myList, FUN = myList[["Dataset1"]]["Function"](x) , x = as.matrix(myList[["Dataset1"]][["DataFrame"]]))

But I dont know how to tell R how to cycle correctly through the sub-lists.

Second, I was hoping to be able to send the whole sublist to a function, but I could not get this to run either.

myFunction <- function(x){
  TempData <- x[["DataFrame"]]
  TempFunction <- x["Function"]
  
  TempResult <- get(TempFunction)(TempData)
  
  return(TempResult)
}

myResult <- lapply(myList, myFunction(x))

If someone could give me an idea how to solve this id be very happy.

Many thanks in advance!

Upvotes: 1

Views: 57

Answers (3)

StupidWolf
StupidWolf

Reputation: 46888

Sounds more complicated than it should be.. And it's not clear how you would apply mean() or lm(). Below is an example where you store the function as an object in the list:

myList[["Dataset1"]] <- list()
myList[["Dataset1"]][["Function"]] <- function(x)mean(as.matrix(x))
myList[["Dataset1"]][["DataFrame"]] <- df
myList[["Dataset2"]] <- list()
myList[["Dataset2"]][["Function"]] <- function(x){lm(Col2~Col1,data=x)}
myList[["Dataset2"]][["DataFrame"]] <- df*2

So you iterate through elements in the list and you get the result of function(dataframe) for each element:

lapply(myList,function(i)i$Function(i$DataFrame))
$Dataset1
[1] 3.5

$Dataset2

Call:
lm(formula = Col2 ~ Col1, data = x)

Coefficients:
(Intercept)         Col1  
          6            1  

Upvotes: 1

Allan Cameron
Allan Cameron

Reputation: 173793

The function call allows you to call a function by its name given as a character string, and you can evaluate this call with eval. Note though, that neither of your function calls make sense applied to a data frame:

lapply(myList, function(sublist) call(sublist$Function, sublist[["DataFrame"]]))
#> $Dataset1
#> mean(list(Col1 = 1:3, Col2 = 4:6))

#> $Dataset2
#> lm(list(Col1 = c(2, 4, 6), Col2 = c(8, 10, 12)))

So the results are kind of useless for the examples used:

lapply(myList, function(sublist) eval(call(sublist$Function, sublist[["DataFrame"]])))
#> $Dataset1
#> [1] NA
#> 
#> $Dataset2
#> 
#> Call:
#> lm(formula = structure(list(Col1 = c(2, 4, 6), Col2 = c(8, 10, 
#> 12)), class = "data.frame", row.names = c(NA, -3L)))
#> 
#> Coefficients:
#> (Intercept)         Col2  
#>          -6            1  
#> 
#> 
#> Warning message:
#> In mean.default(list(Col1 = 1:3, Col2 = 4:6)) :
#>   argument is not numeric or logical: returning NA

Upvotes: 1

Ma&#235;l
Ma&#235;l

Reputation: 51914

A first thing you can do is use the match.fun function that allows you to recover a function from a string. Applied to a loop, it returns the following solution :

list<-list()
for (i in 1:length(myList)){
 TempFunc <- match.fun(myList[[i]][["Function"]])
 Results <- TempFunc(myList[[i]][["DataFrame"]])
 list[i]<-Results
}

> list
[[1]]
[1] NA

[[2]]
(Intercept)        Col2 
         -6           1 

Actually, the functions don't make sense because the functions are not appropriate.

Upvotes: 1

Related Questions