Lapply to Add Columns to Each Dataframe in a List

Lapply to Add Columns to Each Dataframe in a List

Use Map. It is short for mapply(..., SIMPLIFY = FALSE) as suggested by Ari.

df1 <- data.frame(x = runif(3), y = runif(3))
df2 <- data.frame(x = runif(3), y = runif(3))
dfs <- list(df1, df2)
years <- list(2013, 2014)

Map(cbind, dfs, year = years)
# [[1]]
# x y year
# 1 0.8843945 0.6285246 2013
# 2 0.8400041 0.1369520 2013
# 3 0.4398870 0.4660476 2013
#
# [[2]]
# x y year
# 1 0.4153315 0.5831114 2014
# 2 0.9685105 0.2398060 2014
# 3 0.9507591 0.7585670 2014

Adding a column to a list of dataframe with lapply

Try assigning the result of the lapply call to an object; in this case, you can assign back to the originating list of dataframes

dat.s<-lapply(...)

Using lapply over a list and adding a column with data frame name

We can loop through names of sample_list instead of looping through the list

lapply(names(sample_list), function(x) {
sample_list[[x]] %>%
filter_at(vars(1),~. >= 20) %>%
mutate(groupName = x)
})

Update Sep-2021

cleaner way using purrr::map

purrr::map(names(sample_list), ~sample_list[[.x]] %>% 
filter_at(vars(1),~. >= 20) %>%
mutate(groupName = .x)
)

Create new column in each dataframe of list and fill with string from character vector based on position (R)

You can also try creating directly mycol with mapply():

#Data
dfs<-list(mtcars[,1:4], iris[,1:4])
z <- c("red", "blue")
#Code
L <- mapply(function(x,y) {x$mycol<-y;return(x)},x=dfs,y=z,SIMPLIFY = F)

Add new column name to a list of data frames from a part of the file name using lapply

Name the list of filenames using setNames(), then use the .id argument in bind_rows(), which adds a column containing list names.

library(tidyverse)
library(readxl)

files <- list.files(path ="Users/Desktop/week", pattern = "*.xlsx", full.names= T) %>%
setNames(nm = .) %>%
lapply(read_excel, sheet =4, skip =39) %>%
bind_rows(.id = "Week") %>%
mutate(Week = str_extract(Week, "wk\\d+"))

You could also combine the iteration and row-binding steps using purrr::map_dfr():

files <- list.files(path ="Users/Desktop/week", pattern = "*.xlsx", full.names= T) %>%
setNames(nm = .) %>%
map_dfr(read_excel, sheet = 4, skip = 39, .id = "Week") %>%
mutate(Week = str_extract(Week, "wk\\d+"))

R: add new column to a list of data frames with lapply

It's because my_list[[1]]["SubCat"] <- as.character("") doesn't return anything, so, after the expression is evaluated you have NULL as data and the cbind process cannot execute it accordingly. Also, lapply will execute your function for each and every data frame in your list, so your command should like as follows:

vec.1 <- c(1, 2)
vec.2 <- c(2, 3)
df.1 <- data.frame(vec.1, vec.2)
df.2 <- data.frame(vec.2, vec.1)
my_list <- list(df.1, df.2)
## This is the correct use of lapply for your list
my_list <- lapply(my_list, cbind, SubCat = c(""))
my_list
[[1]]
vec.1 vec.2 SubCat
1 1 2
2 2 3

[[2]]
vec.2 vec.1 SubCat
1 2 1
2 3 2

EDIT:
lapply takes a list as argument and a function to apply in each and every one of the list's elements. However, cbind requires two arguments. The additional arguments are passed with lapply. Now, you may notice that the SubCat vector consists of one null string; that is OK, because R repeats that vector as many times as needed.

EDIT #2:
Hmm, this error is probably coming from the empty data.frames, which I didn't take into account. You could do this to solve your problem (I didn't take into account that a vector cannot repeat itself zero times):

my_list <- lapply(my_list, function(df){
if (nrow(df) > 0)
cbind(df, SubCat = c(""))
else
cbind(df, SubCat = character())
})

Added by the author of the question:

It is OK, to complete a column with blanks("") according to the
other columns SubCat = c(""). But, if you have an empty data frame,
you need to start a new column with: SubCat = character(), which is a zero length column.

Adding columns to multiple dataframes in a list in R

Based on the comments, 'Y' is created as a list from splitting the 'Z' by the 'site' column

Y <- split(Z, Z$site)
Y.nmds <- lapply(Y, function(x) metaMDS(x[-(1:4)]))

Now, we can use Map to loop over the corresponding list elements of 'Y.nmds' with 'Y' to create the columns

lst1 <- Map(function(nmd, dat, site) {

dat1 <- as.data.frame(scores(nmd))
transform(dat1, site = site,
reserve_status = dat$reserve_status,
year = dat$year)

}, Y.nmds, Y, names(Y))

-output

lst1
#$AYUNGON
# NMDS1 NMDS2 site reserve_status year
#1 -0.5405524 -0.208839893 AYUNGON Inside 2012
#2 -0.4679394 -0.127144729 AYUNGON Inside 2012
#3 -0.4470720 -0.035047840 AYUNGON Inside 2012
#4 -0.3723951 -0.004604424 AYUNGON Inside 2012
#5 -0.3527766 0.062692135 AYUNGON Inside 2012
#6 -0.3214464 0.117212445 AYUNGON Inside 2014
#7 -0.2585269 0.118163340 AYUNGON Inside 2014
#8 -0.2434562 0.173341542 AYUNGON Inside 2014
#9 0.8334110 -0.008478317 AYUNGON Inside 2014
#10 0.6918728 -0.048824777 AYUNGON Inside 2014
#11 0.5889373 0.008377321 AYUNGON Inside 2015
#12 0.4882185 -0.028821935 AYUNGON Inside 2015
#13 0.4017254 -0.018024867 AYUNGON Inside 2015

#$BINDOY
# NMDS1 NMDS2 site reserve_status year
#14 -0.4973781 0.0312765162 BINDOY Inside 2015
#15 -0.4901276 -0.0008288276 BINDOY Inside 2015
#16 -0.4816021 -0.0282379296 BINDOY Inside 2016
#17 0.1943789 0.0619863596 BINDOY Inside 2016
#18 0.1924750 0.0348895563 BINDOY Inside 2016
#19 0.1876516 0.0165441678 BINDOY Inside 2016
#20 0.1853833 0.0016281922 BINDOY Inside 2016
#21 0.1832898 -0.0126894179 BINDOY Inside 2017
#22 0.1774036 -0.0243657601 BINDOY Inside 2017
#23 0.1750507 -0.0370687919 BINDOY Inside 2017
#24 0.1734749 -0.0431340651 BINDOY Inside 2017

R use of lapply() to populate and name one column in list of dataframes

A full R base approach without using loops

> l<-list(a=c(1,2,3),b=c(4,5,6,7))
> data.frame(grp=rep(names(l), lengths(l)), num=unlist(l), row.names = NULL)
grp num
1 a 1
2 a 2
3 a 3
4 b 4
5 b 5
6 b 6

Add a new column to each df in a list of dfs using apply function

The function week_no is not vectorised so you would need some kind of loop to iterate over each value after strsplit. In the for loop you use sapply, so we can use the same here.

lapply(mapp_dfs, function(x) cbind(x, 
week_nums = sapply(as.Date(unlist(strsplit(x$Timestamp, "T"))[c(TRUE,FALSE)]), week_no)))

#$l1
# Timestamp Value Q.code week_nums
#1 1993-08-30T00 13.53 1 36
#2 2002-01-16T00 1.55 2 3
#3 2010-01-13T00 5.63 3 3
#4 2016-11-08T00 7.32 4 46
#5 2019-05-13T00 7.89 5 20

#$l2
# Timestamp Value Q.code week_nums
#1 1994-07-10T00 13.53 1 28
#2 2003-01-26T00 1.55 1 4
#3 2011-01-13T00 5.63 3 3
#4 2016-11-08T00 9.31 4 46
#5 2019-05-23T00 5.63 1 21

#$l3
# Timestamp Value Q.code week_nums
#1 1995-08-30T00 1.36 2 36
#2 2004-01-16T00 5.63 2 3
#3 2012-01-13T00 5.63 5 3
#4 2013-11-08T00 7.32 4 45
#5 2019-06-03T00 5.22 4 23


Related Topics



Leave a reply



Submit