2017-10-16 142 views
1

好可以说我有一个文件目录,我想在每个文件上运行相同的命令。例如存在10个文件中,如下所示我的目录,虽然这里将表现为数据帧的列表:错误后循环继续处理

# Create dummy files 
    file1 <- as.data.frame(runif(100, 0,100)) 
    file2 <- as.data.frame(runif(100, 0,100)) 
    file3 <- as.data.frame(runif(100, 0,100)) 
    file4 <- as.data.frame(runif(12, 0,100)) 
    file5 <- as.data.frame(runif(100, 0,100)) 
    file6 <- as.data.frame(runif(15, 0,100)) 
    file7 <- as.data.frame(runif(100, 0,100)) 
    file8 <- as.data.frame(runif(8, 0,100)) # This is the df that its intended to fail on 
    file9 <- as.data.frame(runif(100, 0,100)) 
    file10 <- as.data.frame(runif(100, 0,100)) 
    file11 <- as.data.frame(runif(100, 0,100)) 

    # Lets pretend the files are .csv files on my HDD 
    # But here will make a list of data frames 
    file.list <- list(file1,file2,file3,file4,file5,file6,file7,file8,file9,file10) 

# Rename column names for all 10 df 
Names <- function(x) { 
    names(x) <- c("Close") 
    return(x) 
} 
# Apply name change to all 10 data frames 
file.list <- lapply(file.list, Names) 

好了,现在我们必须在这我想遍历数据,并在每个文件祝计算2至12个简单移动平均线。

首先将简单的移动平均过程包含在从file.list [[i]](或数据框1)开始的函数中。在我真正的问题中,这些是我的目录中的文件,但例如为了同样的目的!

# Create function for performing commands. 
    genSMA = function(x){ 
     nextfile <- data.frame(file.list[[i]],stringsAsFactors=FALSE) 
     new.df <- data.frame(nextfile) 
     # Load packages 
     require(TTR) 
     # Use TTR package to create rolling SMA n day moving average 
     getSMA <- function(numdays) { 
     function(new.df) { 
      SMA(new.df[,"Close"], numdays) # Calls TTR package to create SMA 
     } 
     } 
     # Create a matrix to put the SMAs in 
     sma.matrix <- matrix(nrow=nrow(new.df), ncol=0) 
     tail(sma.matrix) 
     # Loop for filling it 
     for (i in 2:12) { 
     sma.matrix <- cbind(sma.matrix, getSMA(i)(new.df)) 
     } 

     # Rename columns 
     colnames(sma.matrix) <- sapply(2:12, function(n)paste("close.sma.n", n, sep="")) 

     # Bind to existing dataframe 
     new.df <- cbind(new.df, sma.matrix) 

    } 

现在我所说的for循环来进行所有数据帧运行此函数:

for (i in 1:length(file.list)){ 
    genSMA(file.list[[i]]) 
} 

确定这是设置,以便它失败。它应该会失败的数据帧8,也显示此错误消息:

Error in runSum(x, n) : n = 9 is outside valid range: [1, 8] 

这是因为没有足够的数据来计算SMA 9,10,11,12的简单移动平均。为了计算那些我们需要的数据超过9,10,11,12个数据点。

我的问题是:

如何在这段代码中,将继续遍历文件的其余部分,忽略该错误消息添加的东西?

我也不知道如何将输出保存到一个数据框?你会注意到这只会运行,不会将输出存储到任何地方,因为我不太清楚如何编码。将最终结果存储在数据帧上也不错。

然而,上面的代码不运行和用于示出关于文件8.

回答

1

在R中可以使用tryCatch块的错误消息说明的目的:

for (i in 1:length(file.list)){ 
    tryCatch({ 
     genSMA(file.list[[i]]) 
    }, error = function(e) { print(paste("i =", i, "failed:")) }) 
} 
+0

确定这告诉我哪个迭代失败,失败时,它是否也会继续循环其余的文件? –

+0

是的,你为什么不测试它? –

+0

是的答案 - 在上面的例子中,是否有一个过程完成后将输出存储到数据框以供查看的过程? –

2

除了tryCatch,一种选择你应该考虑的是R中的foreach包。我建议这样做的原因是,我注意到你正在使用for循环来构建你的sma.matrix。以这种方式构建对象并不是一个好主意,因为它可能会非常快地变得非常缓慢,因为R必须在每个循环中重新分配内存。很多人会建议使用的apply功能之一这一点,或提前分配好自己的空矩阵,但我倾向于找foreach包更容易使用,也可以处理你的错误的问题相当不错:

library(foreach) 

sma.matrix <- foreach(
    i = 1:12,  # This is your for loop iterator 
    .combine=cbind, # Specify how to combine the results of each loop 
    .errorhandling="remove" # When error occurs, skip to next iteration 
) %do% { # You can use %dopar% for parallel loop execution 
    getSMA(i)(new.df) 
} 
+0

Scott - 感谢您的评论。这是专门为循环使SMA的速度提高吗?我为每个文件+整个其他一堆命令做SMA过程,这可以与我的其他代码集成吗? –

+0

Foreach可以用来替换任何for循环。(1)想要平行化循环,或者(2)使用循环来构建对象/矩阵/表 –

+0

太好了 - 我将检查包装! :) –