1
votes

I'm trying to use lapply to run the same function over multiple data frames, but can't get lapply to work without assigning it to something. When I do this, I then have to go back in and re-separate the resulting lists which is annoying. Does anyone know why lapply won't just store the result over the data frames themselves? Here's a simple example:

keepCols <- c(1:6, 23, 24, 27:34, 37, 41:43)

myList <- list(x, y, z)

When I do this, all it does is print the result

lapply(myList, function(x) x[, ..keepCols])

If I assign it to something, I get a large list with what I want in it

df <-  lapply(myList, function(x) x[, ..keepCols])

Why is lapply not working the way I want it to?

2
It not depends on lapply(). In R is call-by-value. en.wikipedia.org/wiki/Evaluation_strategy#Call_by_valuejogo
myList <- lapply(...)Sotos
So if I assign lapply to myList, it changes the data frames only within the list, but not the data frames (contained with in the list) outside of it. I have to make some more transformations before merging, and I don't want to have to keep relisting and unlisting, if that makes any sense?Jessica Landry
Yes, it only changes the data frames within your list If I understood your question correctly. Try l1 <- list(head(iris), tail(iris)); lapply(l1, function(i)i[3:4]) Vs l1 <- list(head(iris), tail(iris)); l1 <- lapply(l1, function(i)i[3:4]) to see what happensSotos
@Gregor I guess I would just have to work only inside of the list the entire time, and any changes to only one of the data frames can just be called upon inside of the list, correct?Jessica Landry

2 Answers

1
votes

You can use the list2env() function.

list2env(data_list, envir = .GlobalEnv)

This will return all the data frames from your list and save them to the environment. This will also keep the data frame object's name.

0
votes

You may just loop through the data frames in the globalenv() using a get-assign-approach, which is even possible in a one-liner.

Example

Consider a list of data frames like this one,

df1  # same as df2 and df3
#   X1 X2 X3 X4
# 1  1  3  5  7
# 2  2  4  6  8

where you want to keep columns 1 and 3.

kp <- c(1, 3)

Do this:

sapply(ls(pat="^df"), function(x) assign(x, get(x, envir=.GlobalEnv)[kp], envir=.GlobalEnv))

Result:

df1
#   X1 X3
# 1  1  5
# 2  2  6

Note: Instead of ls(pattern="^df") you can write alternatively c("df1", "df2", "df3). To keep the console clean you may wrap an invisible() around the sapply.

Data

df1 <- df2 <- df3 <- data.frame(matrix(1:8, 2, 4))