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

Using lapply to apply a function over read-in list of files and saving output as new list of files

我是 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")

根据我在 write.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 个文件时朝着正确方向前进的任何见解或路径。谢谢你。

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

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")

输出被定向到同一个文件的原因可能是 file = paste0(names(DF), "txt", sep=".") returns 每次迭代的值相同。也就是说,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")