 <p>This is meant to complement Richard's, as it felt a little too substantial to simply edit into his.</p> <p>A typical code pattern for this sort of thing would be:</p> <pre><code>#Initialize an empty list of the desired length dfs &lt;- vector("list",3) #Fill the list with data frames, naming as we go for (i in seq_along(dfs)){ dfs[[i]] &lt;- data.frame(x = runif(5),y = runif(5)) names(dfs)[[i]] &lt;- paste0("df",i) } </code></pre> <p>where the use of <code>assign</code> is typically frowned upon as bad (stylistically). If the naming of the data frames is very regular, you don't even need to do it in the loop:</p> <pre><code>names(dfs) &lt;- paste0("df",seq_along(dfs)) </code></pre> <p>you can do it in a vectorized fashion as above. And as I mentioned below Richard's answer, even though having them all in a list is never worse, and usually better, than having them as separate objects, you can convert the list to separate objects via:</p> <pre><code>list2env(dfs,envir = .GlobalEnv) </code></pre>