2017-10-16 139 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

太好了 - 我將檢查包裝! :) –