Adding columns based on a specific function with (l)apply or purr on lists in a list?

Viewed 41

I want to add columns based on a function in all lists in list.

list1 <- list(A = c(1:10), B = c(rnorm(1:10)), C = c(rnorm(1:10)), D = c(rnorm(1:10)))
list2 <- list(A = c(1:10), B = c(rnorm(1:10)), C = c(rnorm(1:10)), D = c(rnorm(1:10)))
both_lists <- list(list1,list2)
both_lists <- lapply(both_lists, function(x) ... )

For one dataframe (not in a list) I normally use:

df1 <- data.frame(A = c(1:10), B = c(rnorm(1:10)), C = c(rnorm(1:10)), D = c(rnorm(1:10)))
df2 <- data.frame(A = c(1:10), B = c(rnorm(1:10)), C = c(rnorm(1:10)), D = c(rnorm(1:10)))
df1 %>% mutate(max = do.call(pmax, c(select(., c(2:4)))))

But how do I do this for the lists* in the list? So I want to do 2 things to all the lists in my list:

  • find the maximum of columns 2-4
  • add that maximum as a separate row

Oh and could anyone also tell me how I actually change the name of the list inside the list? (So changing the name of list1 to the name of a row name in the set? EG setting the name of list to df1[[1]][1] and repeat that with lapply for every list in the list?

2 Answers

With lapply you can do it as follows:

lapply(both_lists, function(x){x[['max']] <- do.call(pmax, x[2:4]); x})

The output looks like this:

[[1]]
[[1]]$A
 [1]  1  2  3  4  5  6  7  8  9 10

[[1]]$B
 [1]  1.325128799  0.341702207  0.341139152 -0.630065889  0.799934566  0.427531770
 [7] -1.492861023  2.643621022  0.008158055 -0.187956774

[[1]]$C
 [1] -0.8535937 -0.1753520  1.1008905 -0.0385363 -1.6739434  0.2179597 -0.1300490  0.4177869
 [9]  1.3066992  0.2369493

[[1]]$D
 [1]  0.98472409  0.66930725  0.52449977  0.08553770 -1.81759549 -0.07564249 -0.63611958
 [8] -1.19293507 -1.61571223  1.29777033

[[1]]$max
 [1]  1.3251288  0.6693073  1.1008905  0.0855377  0.7999346  0.4275318 -0.1300490  2.6436210
 [9]  1.3066992  1.2977703


[[2]]
...

Assuming your data.frames df1 and df2 as shown in the OP are in a list named dfl:

library(dplyr)
library(magrittr)

dfl <- lapply(dfl, function(x){
  x %<>% mutate(max = do.call(pmax, c(select(., c(2:4)))))
})

And if you want to set the names of the list elements as some value from the data.frames within, maybe something like this?

names(dfl) <- lapply(dfl, function(x){
  x[2,2]
})

I hope this is what you actually meant because your question was a bit unclear to me. (Apologies if I am wrong.)

Related