Sebastian Hesse
Sebastian Hesse

Reputation: 545

Applying a function over multiple df that are NOT combined in a list

I am aware of apply/map to run functions over a list of data frames but my problem is that the function uses the name of the data frame to create col names and this doesn't work using it on a list of dfs. Is there a way how I could automate running the function on several DFs without combining them in a list?

Alternatively I could probably also change the function so it gets the names from list objects but so far I failed with this as well.

Maybe someone has a solution? Thanks a lot!

Example data

p.vals <- seq(from=0, to=1, by=.0001)
logFCs <- seq(from=0, to=4, by=.1)
diffEx_proteins <- data.frame(protein=LETTERS[1:1000],
                      adj.P.Val=sample(p.vals, size=1000, replace=TRUE),
                      logFC=sample(logFCs, size=1000, replace=TRUE))

diffEx_proteins_2 <- data.frame(protein=LETTERS[1:1000],
                      adj.P.Val=sample(p.vals, size=1000, replace=TRUE),
                      logFC=sample(logFCs, size=1000, replace=TRUE))

list <- list(group1 = diffEx_proteins, group2 = diffEx_proteins_2)

Function

mark_significants_p.05and.001_fc1 <- function(comparison){
dat <- comparison
name <- deparse(substitute(comparison))
dat[,paste(name,"up_0.05", sep = "_")] <- dat$adj.P.Val <= 0.05 & dat$logFC >= 1
dat[,paste(name,"down_0.05", sep = "_")] <- dat$adj.P.Val <= 0.05 & dat$logFC <= -1
dat[,paste(name,"up_0.001", sep = "_")] <- dat$adj.P.Val <= 0.001 & dat$logFC >= 1
dat[,paste(name,"down_0.001", sep = "_")] <- dat$adj.P.Val <= 0.001 & dat$logFC <= -1
dat[,paste(name,"reg_0.05", sep = "_")] <- dat$adj.P.Val <= 0.05 & abs(dat$logFC) >= 1
dat[,paste(name,"reg_0.001", sep = "_")] <- dat$adj.P.Val <= 0.001 & abs(dat$logFC) >= 1
return(dat)
}

map(list, mark_significants_p.05and.001_fc1) results in cols with names starting with [[1]] but instead I would like to have the df name in it.

Thank you! Sebastian

Upvotes: 0

Views: 29

Answers (1)

Ronak Shah
Ronak Shah

Reputation: 389235

You could use imap which passes the list as well as names of it

mark_significants_p.05and.001_fc1 <- function(comparison, name){
    dat <- comparison
    dat[,paste(name,"up_0.05", sep = "_")] <- dat$adj.P.Val <= 0.05 & dat$logFC >= 1
    dat[,paste(name,"down_0.05", sep = "_")] <- dat$adj.P.Val <= 0.05 & dat$logFC <= -1
    dat[,paste(name,"up_0.001", sep = "_")] <- dat$adj.P.Val <= 0.001 & dat$logFC >= 1
    dat[,paste(name,"down_0.001", sep = "_")] <- dat$adj.P.Val <= 0.001 & dat$logFC <= -1
    dat[,paste(name,"reg_0.05", sep = "_")] <- dat$adj.P.Val <= 0.05 & abs(dat$logFC) >= 1
    dat[,paste(name,"reg_0.001", sep = "_")] <- dat$adj.P.Val <= 0.001 & abs(dat$logFC) >= 1
   return(dat)
}


purrr::imap(list, mark_significants_p.05and.001_fc1)

imap is same as map2 passed with names of list

purrr::map2(list, names(list), mark_significants_p.05and.001_fc1)

Upvotes: 1

Related Questions