在r中的几个数据帧中应用一组操作

时间:2013-04-20 01:59:34

标签: r

我一直在为我的项目学习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。到目前为止,我一直无法将它放在函数或循环中。如果我将它放入函数中:

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

funtest(df.00)什么都不做。我理解函数如何在r中起作用,但是如果我将它包装在for循环中,那么我会期望:

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

我得到“在i $ doy&lt; - NA:将LHS强制转换为列表”几次,这告诉我循环不是将数据帧视为一个单元,而是查看帧中的每一列。登记/> 我真的很感激我应该做些什么。我觉得我可以用bash和awk轻松解决这个问题但是我想用r

来减少它的无能

1 个答案:

答案 0 :(得分:4)

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

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

  5. 由于您的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循环

    正如您所观察到的,使用for (i in someDataFrame) {...}遍历data.frame

    您可以使用apply迭代行:

    apply(myDF, MARGIN=1, function(x) { x$doy <- ...; return(x) } ) # dont forget to return