How to apply a function to every row of a list of tibbles in R?

Viewed 230

I have 20 different tibbles (called N1 to N20), each with 9 columns and about 2 Million rows in R.

In column number 8 (type: integer) I want to change the date. The entry in every column number 8 of each tibble is always the same, it's always number "14190"

I dont want to write :

N1[,8] <- lapply(N1[,8], function(x) format(as.Date(as.numeric(x),origin="1970-01-01"), "%Y-%m-%d"))
N2[,8] <- lapply(N2[,8], function(x) format(as.Date(as.numeric(x),origin="1970-01-01"), "%Y-%m-%d"))
N3[,8] <- lapply(N3[,8], function(x) format(as.Date(as.numeric(x),origin="1970-01-01"), "%Y-%m-%d"))
...
N20[,8] <- lapply(N20[,8], function(x) format(as.Date(as.numeric(x),origin="1970-01-01"), "%Y-%m-%d"))

My first idea was to set a list from N1-N20 but then my function got a problem because it wants integers as argument.

Is there any quick solution? Maybe without lapply?

Thank you!

2 Answers

First. You don't need to loop (= lapply) over the rows of your df to convert the column. Second. Converting all 20 df's could be achieved like so:

N1 <- N2 <- data.frame(col1 = runif(10), col2 = rep(14190, 10))
       
lapply(1:2, function(x) { d <- get(paste0("N", x)); d[[2]] <- format(as.Date(as.numeric(d[[2]]),origin="1970-01-01"), "%Y-%m-%d"); d })
#> [[1]]
#>         col1       col2
#> 1  0.6086402 2008-11-07
#> 2  0.2982811 2008-11-07
#> 3  0.7500646 2008-11-07
#> 4  0.7203713 2008-11-07
#> 5  0.4445544 2008-11-07
#> 6  0.7837107 2008-11-07
#> 7  0.2335820 2008-11-07
#> 8  0.2021103 2008-11-07
#> 9  0.1840012 2008-11-07
#> 10 0.7598002 2008-11-07
#> 
#> [[2]]
#>         col1       col2
#> 1  0.6086402 2008-11-07
#> 2  0.2982811 2008-11-07
#> 3  0.7500646 2008-11-07
#> 4  0.7203713 2008-11-07
#> 5  0.4445544 2008-11-07
#> 6  0.7837107 2008-11-07
#> 7  0.2335820 2008-11-07
#> 8  0.2021103 2008-11-07
#> 9  0.1840012 2008-11-07
#> 10 0.7598002 2008-11-07

Using lists make things a lot easier in R. Specifically, we can make a list of your N tibbles and then use lapply on that list:

N1 = iris
N2 = iris

l = mget(ls(pattern = '^N\\d$'))
l = lapply(l, transform, Sepal.Length = as.integer(Sepal.Length))

l

Another base approach may be to combine all of your tibbles into a single tibble.

l2 = do.call(rbind, c(l, make.row.names = FALSE))
l2$id = rep(seq_along(l), vapply(l, nrow, 1L))
l2[, "Sepal.Width"] = as.integer(l2[, "Sepal.Width"])


## with packages
library(dplyr)
l %>%
    bind_rows(.id = "ID")%>%
    mutate(Sepal.Width = as.integer(Sepal.Width))

library(data.table)
rbindlist(l, id = TRUE)[, Sepal.Width := as.integer(Sepal.Width)]
Related