-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
  • 141,215
  • 6
  • 77
  • 149