我一直在为我的项目学习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
来减少它的无能答案 0 :(得分:4)
最有效和直接的方法是使用列表。
files <- dir('path/to/folder', full.names=TRUE)
data.frame
的列表中
例如:df.list <- lapply(files, read.csv, <additional args>)
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
循环
正如您所观察到的,使用for (i in someDataFrame) {...}
遍历data.frame
的列。
您可以使用apply
迭代行:
apply(myDF, MARGIN=1, function(x) { x$doy <- ...; return(x) } ) # dont forget to return