使用lapply将函数应用于读入文件列表并将输出保存为新的文件列表

时间:2017-07-19 16:22:26

标签: r loops for-loop lapply write.table

我对R很陌生,而且我觉得这可能是一项常见的操作。我需要执行基本功能的文件有多个(57个,累计行数为6亿~15亿行)。我能够读取这些文件并执行计算我没有问题,但我在最终输出中绊倒了。我设想一次处理1个文件的函数,输出工作文件并移动到下一个文件。

在计算之后,我想输出57个新的.txt文件,这些文件以输入数据首先来自的文件命名。到目前为止,我能够在较小的测试数据集上执行计算并吐出1个附加的.txt文件,但这不是我想要的最终输出。

#list filenames 
files <- list.files(path=, pattern="*.txt", full.names=TRUE, recursive=FALSE)

#begin looping process
loop_output = lapply(files, 
function(x) {

#Load 'x' file in
DF<- read.table(x, header = FALSE, sep= "\t")

#Call calculated height average a name
R_ref= 1647.038203

#Add column names to .las data
colnames(DF) <- c("X","Y","Z","I","A","FC")

#Calculate return
DF$R_calc <- (R_ref - DF$Z)/cos(DF$A*pi/180)

#Calculate intensity
DF$Ir_calc <- DF$I * (DF$R_calc^2/R_ref^2)

#Output new .txt with calcuated columns
write.table(DF, file=, row.names = FALSE, col.names = FALSE, append = TRUE,fileEncoding = "UTF-8")

})

我最近的代码努力一直在处理初始的lapply / sapply函数:

#begin looping process
loop_output = sapply(names(files), 
function(x) {

以及输出行:

#Output new .csv with calcuated columns 
write.table(DF, file=paste0(names(DF), "txt", sep="."),
row.names = FALSE, col.names = FALSE, append = TRUE,fileEncoding = "UTF-8")

从我在read.table输出期间读取文件命名功能开始,可能是我还没有与脚本的其余部分完全对齐的键之一。我一直在查看我认为适用的许多其他问题:

Using lapply to apply a function over list of data frames and saving output to files with different names

Write list of data.frames to separate CSV files with lapply

没有运气。我非常感谢任何关于输入x个文件的正确方向的见解或路径,在每个文件上执行相同的功能,然后输出相同的x个文件。谢谢。

2 个答案:

答案 0 :(得分:1)

输出定向到同一文件的原因可能是file = paste0(names(DF), "txt", sep=".")为每次迭代返回相同的值。也就是说,DF在每次迭代中必须具有相同的列名,因此names(DF)将是相同的,paste0(names(DF), "txt", sep=".")将是相同的。与append = TRUE选项一起,结果是所有输出都写入同一文件。

在匿名函数中,x是输入文件的名称。您可以对此字符串进行一些转换,而不是使用names(DF)作为输出文件名的基础。

例如

鉴于

x <- "/foo/raw_data.csv"

在函数内部你可以做这样的事情

infile <- x
outfile <- file.path(dirname(infile), gsub('raw', 'clean', basename(infile)))

outfile
[1] "/foo/clean_data.csv"

然后使用新名称输出append = FALSE(除非你需要它是真的)

write.table(DF, file = outfile, row.names = FALSE, col.names = FALSE, append = FALSE, fileEncoding = "UTF-8")

答案 1 :(得分:0)

使用您的代码,这是一般的想法:

require(purrr)

#list filenames 
files <- list.files(path=, pattern="*.txt", full.names=TRUE, recursive=FALSE)


#Call calculated height average a name
R_ref= 1647.038203

dfTransform <- function(file){
  colnames(file) <- c("X","Y","Z","I","A","FC")

  #Calculate return
  file$R_calc <- (R_ref - file$Z)/cos(file$A*pi/180)

  #Calculate intensity
  file$Ir_calc <- file$I * (file$R_calc^2/R_ref^2)
  return(file)
}

output <- files %>% map(read.table,header = FALSE, sep= "\t") %>%
  map(dfTransform) %>%
  map(write.table, file=paste0(names(DF), "txt", sep="."),
  row.names = FALSE, col.names = FALSE, append = TRUE,fileEncoding = "UTF-8")