1

I have n number of dataframes named "s.dfx" where x=1:n. All the dataframes have 7 columns with different names. Now I want to cbind all the dataframes.

I know the comand

t<-cbind.data.frame(s.df1,s,df2,...,s.dfn)

But I want to optimize and cbind them in a loop, since n is a large number.

I have tried

for(t2 in 1:n){ t<-cbind.data.drame(s.df[t2]) }

But I get this error "Error in [.data.frame(s.df, t2) : undefined columns selected"

Can anyone help?

2 Answers2

3

I don't think that a for-loop would be any faster than do.call(cbind, dfs), but it wasn't clear to me that you actually had such a list yet. I thought you might need to build such list from a character object. This answer assumes you don't have a list yet but that you do have all your dataframes numbered in an ascending sequence that ends in n where the decimal representation might have multiple digits.

 t <- do.call( cbind, mget( paste0("s.dfs", 1:n) ) )

Pasqui uses ls inside mget and a pattern to capture all the numbered dataframes. I would have used a slightly different one, since you suggested that the number was higher than 9 which is all that his pattern would capture:

  ls(pattern = "^s\\.df[0-9]+")  # any number of digits
                # ^ need double escapes to make '.' a literal period or fixed=TRUE
IRTFM
  • 258,963
  • 21
  • 364
  • 487
1
library(purrr) #to be redundant

#generating dummy data frames
df1 <- data.frame(x = c(1,2),      y = letters[1:2])
df2 <- data.frame(x = c(10,20),    y = letters[c(10, 20)])
df3 <- data.frame(x = c(100, 200), y = letters[c(11, 22)])

#' DEMO [to be adapted]: capturing the EXAMPLE data frames in a list
dfs <- mget(ls(pattern = "^df[1-3]"))

#A Tidyverse (purrr) Solution
t <- purrr::reduce(.x = dfs, .f = bind_cols)

#Base R
do.call(cbind,dfs)  
# or
Reduce(cbind,dfs)
Pasqui
  • 591
  • 4
  • 12
  • 5
    `do.call(cbind,dfs)` or `Reduce(cbind,dfs)` in base R – Onyambu Mar 26 '18 at 22:46
  • I made explicit that the capturing bit is an example and it needs to be adapted. – Pasqui Mar 26 '18 at 22:51
  • 2
    If you're using `tidyverse` you should use `dplyr::bind_cols` which is more efficient. Else use @Onyambu's solution. – moodymudskipper Mar 26 '18 at 23:05
  • 1
    I edited my answer. However, my reason for the `tidyverse` is that its functions are "pipe `%>%`" friendly (see data arg as first arg). Nothing to do with efficiency. – Pasqui Mar 26 '18 at 23:11
  • @Pasqui: Wouldn't simply `paste0("df", 1:3)` or at least `ls(pattern = "^df[1-3]$")` be a bit safer? @Onyambu: Isn't `do.call(cbind,dfs)` simpler and faster than `Reduce(cbind,dfs)`? – s_baldur Jun 22 '18 at 08:40
  • @snoram: the spirit of my "[to be adapted]". I wanted to communicate to option of pattern matching (thus I do not like any `paste` solution :) ). In general, I want to express problem solving strategies. The end user will finalise the implementation details. – Pasqui Jun 22 '18 at 17:06