4

我一直在为我的项目学习 R,但无法通过谷歌搜索我当前问题的解决方案。

我有大约 100 个 csv 文件,需要对它们执行一组精确的操作。我已经将它们作为单独的对象读入(我认为这可能是不正确的 r 风格),但我一直无法编写一个可以循环的函数。每个 csv 都是一个包含信息的数据框,其中包括一个带有十进制年份形式的日期的列。我需要创建 2 个包含年份和年份的新列。我已经想出了如何手动完成我想找到一种方法来自动化这个过程。这是我一直在做的事情:

#setup
library(lubridate)  #Used to check for leap years
df.00 <- data.frame( site = seq(1:10), date = runif(10,1980,2000 ))


#what I need done

df.00$doy <- NA  # make an empty column which I'm going to place the day of the year
df.00$year <- floor(df.00$date) # grabs the year from the date column
df.00$dday <- df.00$date - df.00$year # get the year fraction. intermediate step.

# multiply the fraction year by 365 or 366 if it's a leap year to give me the day of the year
df.00$doy[which(leap_year(df.00$year))] <- round(df.00$dday[which(leap_year(df.00$year))] * 366)
df.00$doy[which(!leap_year(df.00$year))] <- round(df.00$dday[which(!leap_year(df.00$year))] * 365)

以上,虽然不优雅,但可以满足我的要求。但是,我需要对其他数据帧 df.01 - df.99 执行此操作。到目前为止,我一直无法将它放在函数或 for 循环中。如果我把它放到一个函数中:

funtest <- function(x) {
    x$doy <- NA
}

funtest(df.00) 什么都不做。这是我对函数在 r 中如何工作的理解所期望的,但是如果我将它包装在一个 for 循环中:

for(i in c(df.00)) { 
    i$doy <- NA }

我多次收到“In i$doy <- NA : Coercing LHS to a list”,这告诉我循环不会将数据帧视为一个单元,而是可能会查看帧中的每一列。
我真的很感激对我应该做什么的一些见解。我觉得我可以使用 bash 和 awk 轻松解决这个问题,但我希望使用 r 不那么无能

4

1 回答 1

5

最有效和最直接的方法是使用列表。

  1. 将所有 CSV 文件放入一个文件夹
  2. 获取该文件夹中的文件列表,
    例如: files <- dir('path/to/folder', full.names=TRUE)
  3. 迭代地将所有这些文件读入data.frames列表,
    例如:df.list <- lapply(files, read.csv, <additional args>)
  4. 在每个 data.frame 上迭代地应用您的函数,例如:lapply(df.list, myFunc, <additional args>)

由于您的 df 已经加载,并且它们具有方便的名称,因此您可以使用以下命令轻松获取它们:

nms     <- c(paste0("df.0", 0:9), paste0("df.", 10:99))
df.list <- lapply(nms, get)

然后将您在该#what I need done部分中的所有内容放入一个函数中,例如:

myFunc <- function(DF) {

   # what you want done to a single DF
return(DF)
}

然后lapply相应地

df.list <- lapply(df.list, myFunc)

在单独的注释中,关于功能:

funTest“什么都不做”的原因是你没有让它返回任何东西。也就是说,它正在做某事,但是当它做完之后,它就“什么都不做”。

您需要return(.)在函数中包含一条语句。或者,函数最后一行的输出(如果未分配给对象)将用作返回值——但最后一句话只是大致正确,因此需要谨慎。最干净的选择(在我看来)是使用return(.)


关于for循环data.frame

正如您所观察到的,usingfor (i in someDataFrame) {...}迭代.data.frame

您可以使用以下方法迭代行apply

apply(myDF, MARGIN=1, function(x) { x$doy <- ...; return(x) } ) # dont forget to return
于 2013-04-20T03:09:51.990 回答