-1

I have to work on several data frames to perform the same set of operations. Because of this, I inserted them into a list, and by using lapply I perform some kind of operations. Then, I want to save each dataframes separately as .txt files, by employing a for loop. Here's the code I wrote:

all <- lapply(names(sampleList),function(mysample){
  aux <- read.table(sampleList[[mysample]], col.names=c("Chromosome","Position","Ref_allele","Alt_allele","Fraction","Fw_ref","Rv_ref","Fw_alt","Rv_alt"))
  aux <- mutate(aux, ID=paste0(Chromosome, ":", Position)) %>% distinct(ID, .keep_all=T)
})

for( i in 1:length(all))
  write.table(all[i], paste0(all[i],"_filtered.txt"))

I would expect to have n new dataframes, named as the original ones + _filtered at the end. But this is what actually happens:

Error in file(file, ifelse(append, "a", "w")) : 
  cannot open the connection
In addition: Warning message:
In file(file, ifelse(append, "a", "w")) :
  cannot open file 'list(Chromosome = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 [... truncated]

But that's not what my data frames contains. By View(as.data.frame(all[n])) I see my data frames looks normal.

Many thanks for any help.

  • 2
    Take a look at [how to create a good reproducible example](https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example). – heds1 Aug 05 '19 at 23:37
  • Your second argument to `write.table` should be a file name, but is instead `paste0(all[i],...)` which is a `data.frame` (embedded in a length-1 `list`), not the name of it. Perhaps you can replace your `for` loop completely with `Map(write.table, all, paste0(names(all), "_filtered.txt"))`. – r2evans Aug 05 '19 at 23:41
  • 2
    (And it pains me to write it like that ... I suggest that you don't name your variables the same as base R functions: `all` and `any` are common enough that it can be a little difficult for others to read your code, harder yet to troubleshoot problems (esp if you don't understand the error `object of type 'closure' is not subsettable`).) – r2evans Aug 05 '19 at 23:43

1 Answers1

0

There are a couple things that can be done here:

for( i in 1:length(all))
  write.table(all[i], paste0(all[i],"_filtered.txt"))

First, the second argument is supposed to be a string, but your paste0(all[i],...) is working on the frame itself (all[i] is a data.frame embedded in a list of length 1), not the name of it. You might get away with:

for( i in 1:length(all))
  write.table(all[i], paste0(names(all)[i], "_filtered.txt"))

But you can continue the theme of "operate on a list of frames" (which is great, btw), by extending your lexicon from just lapply (which executes a function on one vector/list of data) to include Map and mapply, which zips together one or more vectors/lists into individual arguments of a function. Up front:

Map(write.table, all, paste0(names(all), "_filtered.txt"))

should save everything as you intend (and return a list of return values from write.table, which might not be useful).

Explanation: Map(myfun, 1:3, c('a','b','c'), c('X','Y','Z')) is unrolled internally to be

myfun(1, 'a', 'X')
myfun(2, 'b', 'Y')
myfun(3, 'c', 'Z')

So these two are nearly equivalent:

lapply(1:3, myfun)
Map(myfun, 1:3)

(There are some ever-so-minor performance differences between them. If you know you always have one vector, use lapply.)

So to continue a theme of "vectorize as much as you can" (which is a common mantra in R-circles), we generate the filenames early with paste0(names(all), "_filtered.txt"), and then pass two list/vector objects to Map: the list of data, and the file names.

r2evans
  • 108,754
  • 5
  • 72
  • 122
  • Alan, if the answer addresses your issue, please [accept it](https://stackoverflow.com/help/someone-answers); doing so not only provides a little perk to the answerer with some points, but also provides some closure for readers with similar questions. Though you can only accept one answer, you have the option to up-vote as many as you think are helpful. (If there are still issues, you will likely need to edit your question with further details.) – r2evans Aug 10 '19 at 16:22