【问题标题】:Applying a function on all csv files from a certain folder对某个文件夹中的所有 csv 文件应用函数
【发布时间】:2015-01-28 17:15:51
【问题描述】:

我正在从某个文件夹中读取 csv 文件,这些文件都具有相同的结构。此外,我还创建了一个函数,可以将某个值添加到 dataFrame。

我已经创建了“文件夹阅读”部分,还创建了函数。但是,我现在需要将这两者相互连接。这就是我遇到问题的地方:

这是我的代码:

addValue <- function(valueToAdd, df.file, writterPath) {
    df.file$result <- df.file$Value + valueToAdd
    x <- x + 1 
    df.file <- as.data.frame(do.call(cbind, df.file))
    fullFilePath <- paste(writterPath, x , "myFile.csv", sep="")
    write.csv(as.data.frame(df.file), fullFilePath)
}

#1.reading R files
path <- "C:/Users/RFiles/files/"
files <- list.files(path=path, pattern="*.csv")
for(file in files)
{
  perpos <- which(strsplit(file, "")[[1]]==".")
  assign(
    gsub(" ","",substr(file, 1, perpos-1)), 
    read.csv(paste(path,file,sep="")))
}

#2.appyling function  
writterPath <- "C:/Users/RFiles/files/results/"
addValue(2, sys, writterPath)

如何在我的#1.reading R files 构造中应用addValue() 函数?有什么建议吗?

感谢您的回答!

更新

在试用示例代码时,我得到:

+   }
+   ## If you really need to change filenames with numbers,
+   newfname <- file.path(npath, paste0(x, basename(fname)))
+   ## otherwise just use `file.path(npath, basename(fname))`.
+   
+   ## (4) Write back to a different file location:
+   write.csv(newdat, file = newfname, row.names = FALSE)
+ }
Error in `$<-.data.frame`(`*tmp*`, "results", value = numeric(0)) : 
  replacement has 0 rows, data has 11

有什么建议吗?

【问题讨论】:

  • 你有什么问题? (您在致电list.files() 时需要full.names=TRUE 吗?)
  • @r2evans 感谢您的回复!我的问题是我不知道如何将我的函数 addValue() 应用于我的 1.reading R files 构造? atm 这两个是完全分开的......

标签: r statistics


【解决方案1】:

您的代码有几个问题(例如,您的函数中的 x 从未定义,并且在对 addValue 的调用之间未保留),所以我猜这是真实的缩减版本代码,你仍然有剩余。我不会冗长地把它分开,而是提供我自己的建议代码和一些指针。

addValue 函数看起来很适合更改 data.frame,但我不会猜到(至少从名称上看)它还会将文件写入磁盘(并可能覆盖现有文件)。

我猜您正在尝试 (1) 读取文件,(2) 为其“添加值”,(3) 将其分配给全局变量,以及 (4) 将其写入磁盘。第三个可能是有问题的(并且会引起一些程序员的争议),但我将暂时搁置它。

除非写入磁盘是您为 data.frame “增加价值”的想法所固有的,否则我建议您将 #2 与 #4 分开。以下是您的代码的建议替代方案:

addValue <- function(valueToAdd, df) {
    df$results <- df$Value + valueToAdd
    ## more stuff here?
    return(df)
}

opath <- 'c:/Users/RFiles/files/raw'     # notice the difference
npath <- 'c:/Users/RFiles/files/adjusted'
files <- list.files(path = opath, pattern = '*.csv', full.names = TRUE)

x <- 0
for (fname in files) {
    x <- x + 1
    ## (1) read in and (2) "add value" to it
    dat <- read.csv(fname)
    newdat <- addValue(2, dat)

    ## (3) Conditionally assign to a global variable:
    varname <- gsub('\\.[^.]*$', '', basename(fname))
    if (! exists(varname)) {
        assign(x = varname, value = newdat)
    } else {
        warning('variable exists, did not overwrite: ', varname)
    }
    ## If you really need to change filenames with numbers,
    newfname <- file.path(npath, paste0(x, basename(fname)))
    ## otherwise just use `file.path(npath, basename(fname))`.

    ## (4) Write back to a different file location:
    write.csv(newdat, file = newfname, row.names = FALSE)
}

注意它不会覆盖全局变量。这可能是一个烦人的检查,但如果您不小心运行了这部分代码,可以防止您丢失数据。

将大量变量分配给全局地址空间的另一种方法是将它们全部保存到一个列表中。假设它们是相同的格式,您可能会使用相同(或非常相似)的分析方法来处理它们,因此将它们全部放在一个列表中将有助于实现这一点。跟踪不同的变量名称的替代方法可能很烦人。

## addValue as defined previously
opath <- 'c:/Users/RFiles/files/raw'
npath <- 'c:/Users/RFiles/files/adjusted'
ofiles <- list.files(path = opath, pattern = '*.csv', full.names = TRUE)
nfiles <- file.path(npath, basename(ofiles))

dats <- mapply(function(ofname, nfname) {
    dat <- read.csv(ofname)
    newdat <- addValue(2, dat)
    write.csv(newdat, file = nfname, row.names = FALSE)
    newdat
}, ofiles, nfiles, SIMPLIFY = FALSE)
length(dats)                            # number of files
names(dats)                             # one for each file

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多