2017-10-18 3 views
2

Le code suivant:erreur d'appeler combiner boucle fonction foreach en R

df <- foreach(i = 1:length, .combine = cbind) %dopar% { 
... 
... 
m4 
} 

me donne une erreur:

error calling combine function: 
<simpleError in data.frame(..., check.names = FALSE): arguments imply differing number of rows: 17, 0> 

mais, si j'exécute le même code avec "pour" au lieu de « foreach "et je fais aussi cbind manuellement:

for (i in 1:lengthGeni) { 
... 
... 
mFinaleCGunificati <- cbind(mFinaleCGunificati, m4) 
} 

everthing fonctionne bien

+1

Pouvez-vous s'il vous plaît trouver un code [reproductible] approprié (https://stackoverflow.com/q/5963269/3250126)? bc si j'essaye de 'cbind (comme.data.frame (matrice (rep (1, 5), nrow = 5)), as.data.frame (matrice (rep (1, 0), nrow = 0))) '(ce qui correspond à ce qui se passe dans votre approche' for'loop ') la même erreur est retournée. – loki

Répondre

0

De ?cbind nous apprenons que

S'il y a plusieurs arguments de la matrice, ils doivent tous avoir le même nombre de colonnes (ou lignes) et ce sera le nombre de colonnes (ou lignes) du résultat. Si tous les arguments sont des vecteurs, le nombre de colonnes (lignes) dans le résultat est égal à la longueur du vecteur le plus long.

Toutefois, si de la comparaison de ces deux exemples cbind

# second df with one row 
cbind(as.data.frame(matrix(rep(1, 10), nrow = 5)), 
     as.data.frame(matrix(rep(2, 2), nrow = 1))) 
# V1 V2 V1 V2 
# 1 1 1 2 2 
# 2 1 1 2 2 
# 3 1 1 2 2 
# 4 1 1 2 2 
# 5 1 1 2 2 

# second df with zero rows 
cbind(as.data.frame(matrix(rep(1, 10), nrow = 5)), 
     as.data.frame(matrix(rep(2, 0), nrow = 0))) 
# Error in data.frame(..., check.names = FALSE) : 
# arguments imply differing number of rows: 5, 0 

nous apprenons que les objets ne sont pas autorisés à zéro de longueur.

Par conséquent, vous devez vérifier si votre résultat dans la boucle a un nombre de lignes supérieur à 0.

library(foreach) 
library(doSNOW) 
cl <- makeSOCKcluster(5) 
registerDoSNOW(cl) 

df <- foreach(i = 1:2, .combine = cbind) %dopar% { 
    if (i == 1){ 
    x <- as.data.frame(matrix(rep(1, 5), nrow = 5)) 
    } else { 
    x <- as.data.frame(matrix(rep(1, 2), nrow = 1)) 
    } 

    # check if result has at least one row 
    if (nrow(x) > 0){ 
    x 
    } 
} 
df 
# V1 V1 V2 
# 1 1 2 2 
# 2 1 2 2 
# 3 1 2 2 
# 4 1 2 2 
# 5 1 2 2 

Cependant, gardez à l'esprit que des vecteurs plus courts seront réutilisés. Cette approche pourrait donc entraîner des redondances dans le code.

Pour éviter les redondances, vous pouvez envisager de faire correspondre les longueurs des résultats avant de les renvoyer dans la boucle foreach.

+1

Merci beaucoup! – giupardeb