2017-10-16 3 views
1

Ok, disons que j'ai un répertoire de fichiers et que je veux exécuter les mêmes commandes sur chaque fichier. Il est par exemple 10 fichiers dans mon répertoire comme ci-dessous, même si ici exprimera une liste des trames de données:Boucle pour continuer à traiter après erreur

# 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) 

Ok donc maintenant nous avons les données auxquelles je veux itérer et sur chaque fichier que je souhaite pour calculer 2 à 12 moyenne mobile simple.

D'abord, enchaînera la procédure de moyenne mobile simple dans une fonction à partir de file.list [[i]] (ou de la trame de données 1). Dans mon vrai problème ce sont des fichiers sur mon répertoire mais par exemple c'est la même chose!

# 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) 

    } 

Maintenant, j'appelle la boucle pour exécuter cette fonction sur toutes les trames de données:

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

Ok c'est configuré pour qu'il échoue. Il tombe en panne sur les données image 8 et également imprimer ce message d'erreur:

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

Ceci est parce qu'il n'y a pas assez de données pour calculer les moyennes mobiles simples de SMA 9,10,11,12. Pour calculer ceux-ci, nous avons besoin de données plus longues que 9,10,11,12 points de données.

Ma question est:

Comment puis-je ajouter quelque chose dans ce code qui continuera à boucle à travers le reste des fichiers et ignorer le message d'erreur?

Je ne sais pas non plus comment enregistrer la sortie dans une trame de données? Vous remarquerez que cela va juste courir et ne pas stocker la sortie n'importe où car je ne sais pas trop comment coder cela non plus. Il serait bon de stocker le résultat final sur la trame de données aussi.

Cependant, le code ci-dessus fonctionne et à des fins d'illustration de montrer le message d'erreur sur le fichier 8.

Répondre

1

Vous pouvez utiliser tryCatch blocs R:

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

Ok que me dit quelle itération a échoué, en cas d'échec, continuera-t-elle également à parcourir le reste des fichiers? –

+0

Oui pourquoi ne pas le tester? –

+0

Oui est la réponse - Dans l'exemple ci-dessus, existe-t-il une procédure pour stocker la sortie dans une trame de données pour la visualisation après la fin du processus? –

2

En plus de TryCatch, une option vous devriez considérer est le paquet foreach dans R. La raison que je suggère ceci, est parce que je remarque que vous utilisez votre for pour construire votre sma.matrix. Ce n'est pas une bonne idée de construire un objet de cette façon car il peut devenir très lent très rapidement car R doit continuer à réallouer de la mémoire à chaque boucle. Beaucoup de gens suggère d'utiliser l'une des apply fonctions pour cela, ou l'attribution de votre matrice vide à l'avance, mais je tendance à trouver le paquet foreach plus facile à utiliser et gère également votre problème d'erreurs assez bien:

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 - merci pour les commentaires. C'est spécifiquement pour la boucle de faire les SMA pour l'accélérer? Je fais la procédure SMA pour CHAQUE fichier + tout un tas de commandes, cela peut être intégré avec le reste de mon code? –

+0

Foreach peut être utilisé pour remplacer n'importe quelle boucle for.Je trouve cela très utile lorsque vous (1) voulez paralléliser la boucle, ou (2) utiliser une boucle pour construire un objet/matrice/table –

+0

Super - je vais vérifier le paquet! :) –