2

If I have a list of data frames

my_list = list(data, data2, data3)

and I would like to add a column to each that is populated with that data frame's name

column1    column2    new_column    
12         27         data
27         987        data
378        1234       data

, how would I go about this? I would like all DFs within the set to retain their original names, but have it populate a column, as well.

I have tried:

my_list = lapply(my_list, function(DF){
     DF$new_column <- DF

     DF
})

but it doesn't run through the list within the function.

What am I missing? Thanks

datahappy
  • 826
  • 2
  • 11
  • 29
  • `DF` is not a name it is a `data.frame`. Look at http://stackoverflow.com/questions/10520772/in-r-how-to-get-an-objects-name-from-the-object-itself and replace `DF` inside a function to `deparse(substitute(DF))`. Did it help? – DrDom Dec 02 '14 at 20:53
  • 2
    If you create a list with `list(data, data2, data3)` the information about the names of the data frames is lost. – Sven Hohenstein Dec 02 '14 at 21:25
  • @SvenHohenstein That makes sense- so it doesn't store them as "list element 1", list element 2", etc just as the contents of each element? – datahappy Dec 02 '14 at 21:32

3 Answers3

14

Your list is unnamed. You can either make it named manually while creating it

my_list = list(data = data, data2 = data2, data3 = data3)

Or you can use mget & ls combination if you have many data sets

my_list <- mget(ls(pattern = "^data$|^data\\d+$"))

Afterwords, just use Map

my_list <- Map(cbind, my_list, new_clumn = names(my_list))
my_list
# $data
#   column1 column2 new_clumn
# 1      12      27      data
# 2      27     987      data
# 3     378    1234      data
# 
# $data2
#   column1 column2 new_clumn
# 1      12      27     data2
# 2      27     987     data2
# 3     378    1234     data2
# 
# $data3
#   column1 column2 new_clumn
# 1      12      27     data3
# 2      27     987     data3
# 3     378    1234     data3

#If you want to put the data sets back to the global environment you can use `list2env`
#list2env(my_list, .GlobalEnv) 
#Please Note that it is usually not the preffered practice to move data frames to the global environment and back. It is preferred to store all you data sets in list from the very beginning and manipulating them within the list using functions such as `Map`, `lapply`, etc.
David Arenburg
  • 91,361
  • 17
  • 137
  • 196
  • The main difference is that list in a given initial example doesn't contain names. Otherwise it will be trivial to add these names. – DrDom Dec 02 '14 at 21:15
  • This worked like a charm within the list. It did not unpack the list to alter the original data frames in the environment, though. I'm guessing I just need to figure out how to remove data frames from a list and place them back into the global environment with another function? – datahappy Dec 02 '14 at 21:28
1
> x <- data.frame(1:2, 2:1)
> my_list <- list(a = x, b = x)
> my_list
$a
  X1.2 X2.1
1    1    2
2    2    1

$b
  X1.2 X2.1
1    1    2
2    2    1

> your_new_list <- lapply(names(my_list),
+                           function(current_name)
+                               transform(my_list[[current_name]],
+                                         new_column = current_name))
> your_new_list
[[1]]
  X1.2 X2.1 new_column
1    1    2          a
2    2    1          a

[[2]]
  X1.2 X2.1 new_column
1    1    2          b
2    2    1          b
mmuurr
  • 1,310
  • 1
  • 11
  • 21
  • And, if you're unfamiliar with transform, you can do this: `lapply(names(my_list), function(current_name) { my_list[[current_name]]$new_column = current_name; my_list })` – mmuurr Dec 02 '14 at 20:52
  • This returns a list of 0 ? – datahappy Dec 02 '14 at 20:58
  • 1
    Oh! Yeah, typo! Replace the last `my_list` with `my_list[[current_name]]`... sorry! (Or just use the `transform` version :-) – mmuurr Dec 02 '14 at 20:59
  • I replaced (and used the OP solution, and both return empty lists – datahappy Dec 02 '14 at 21:02
  • I don't think the original solution (using `transform`) returns an empty list... I've updated the solution's post to include full input/output to demonstrate. Cheers! – mmuurr Dec 02 '14 at 21:54
0

I changed, now see if this is what you wanted:

names<-names(my_list)
count <- 0
lapply(my_list, function(DF){
    count <<- count+1
    DF[,length(DF)+1] <- names[count]
    names(DF)[length(DF)] <- "new_clumn"
    DF
})