problème de syntaxe dans un programme

Postez ici vos questions, réponses, commentaires ou suggestions - Les sujets seront ultérieurement répartis dans les archives par les modérateurs

Modérateur : Groupe des modérateurs

Céline MIR
Messages : 15
Enregistré le : 15 Déc 2006, 17:46

problème de syntaxe dans un programme

Messagepar Céline MIR » 18 Déc 2006, 10:12

Bonjour à tous !
Je suis en train d'essayer de construire un programme sous R, et de découvrir du même coup la syntaxe de R. Je bute sur un problème de syntaxe que je ne parviens pas à débloquer (ça doit probablement être tout bête, mais bon, je débute !!).
J’ai besoin de fixer plusieurs paramètres, et je voulais donc utiliser « for » pour cela. Par exemple, si on prend une expression toute simple :
for (n in 1:nrow(srt3)) {Q=sum(srt3[1:n,1]*srt3[1:n,2])}
ça marche très bien.
J’ai vu qu’il était possible de combiner à la suite plusieurs « for », du genre :
for (n in 1:nrow(srt3)) {for (k in 1:ncol(srt3)) Q=sum(srt3[1:n,1:k]*srt3[1:n,1:k])}

Mais lorsque je veux utiliser cette syntaxe pour préciser une valeur (par exemple, si je veux dire « pour les valeurs de la 2eme colonne de srt3 > 3), ça ne marche plus… J’ai essayé plusieurs formulations, mais rien n’y fait… Par exemple,
for (n in 1:nrow(srt3)) {for (srt3[1 :n,2] >3) Q=sum(srt3[1:n,1:k]*srt3[1:n,1:k])}
ne fonctionne pas…
Pourriez vous m’aider s’il vous plaît ? Je n’ai trouvé sur internet aucune explication sur les syntaxes imbriquées, et je suis complètement bloquée…
Heeeeeeeeeelp !
Merci beaucoup par avance
Céline

Romain François
Messages : 42
Enregistré le : 08 Déc 2005, 19:23
Contact :

Messagepar Romain François » 18 Déc 2006, 12:34

J’ai besoin de fixer plusieurs paramètres, et je voulais donc utiliser « for » pour cela. Par exemple, si on prend une expression toute simple :
for (n in 1:nrow(srt3)) {Q=sum(srt3[1:n,1]*srt3[1:n,2])}
ça marche très bien.


Beaucoup de calculs sont faits inutilement dans cette boucle. A chaque fois que n change, Q change de valeur, a quoi bon ? Pourquoi pas essayer quelque chose de plus simple :

Code : Tout sélectionner

sum( srt3[,1] * srt3[,2] )


ça marche très bien.
J’ai vu qu’il était possible de combiner à la suite plusieurs « for », du genre :
for (n in 1:nrow(srt3)) {for (k in 1:ncol(srt3)) Q=sum(srt3[1:n,1:k]*srt3[1:n,1:k])}

Mais lorsque je veux utiliser cette syntaxe pour préciser une valeur (par exemple, si je veux dire « pour les valeurs de la 2eme colonne de srt3 > 3), ça ne marche plus… J’ai essayé plusieurs formulations, mais rien n’y fait… Par exemple,
for (n in 1:nrow(srt3)) {for (srt3[1 :n,2] >3) Q=sum(srt3[1:n,1:k]*srt3[1:n,1:k])}
ne fonctionne pas…
Pourriez vous m’aider s’il vous plaît ? Je n’ai trouvé sur internet aucune explication sur les syntaxes imbriquées, et je suis complètement bloquée…
Heeeeeeeeeelp !
Merci beaucoup par avance
Céline


J'ai du mal a comprendre ce que vous souhaitez vraiment faire, mais le plus important c'est que ces boucles ont l'air d'etre tout sauf necessaires. R est vectorise, par exemple :

Code : Tout sélectionner

srt3[,2] < 3
srt3[ srt3[,2] < 3  , ]


...
--
Romain François
Consultant R Indépendant
http://romainfrancois.blog.free.fr

Céline MIR
Messages : 15
Enregistré le : 15 Déc 2006, 17:46

Messagepar Céline MIR » 18 Déc 2006, 12:55

Bonjour !
Merci de votre réponse !
En fait, je suis bien consciente que la boucle que je citais comme exemple n'est pas construite de la meilleure façon qui soit: je me suis juste fait un exemple bidon pour comprendre la syntaxe, et la manière d'imbriquer plusieurs boucles "for" (même si on peut avoir ici le même résultat en formulant différemment).
Donc si on reprend votre réponse, la façon correcte de formuler serait :
for (n in 1:nrow(srt3)) {for (srt3[,2] >3) Q=sum(srt3[1:n,1:k]*srt3[1:n,1:k])}
...ca ne marche pas.

Je ne sais pas si je suis claire dans ma question. L'exemple que je cite n'a aucune réalité, je voudrais juste avoir un exemple de syntaxe icluant plusieurs for...
Merci
Céline

Renaud Lancelot
Messages : 2484
Enregistré le : 16 Déc 2004, 08:01
Contact :

Messagepar Renaud Lancelot » 18 Déc 2006, 13:30

La première chose à faire d'urgence est de passer qques heures à lire de la documentation de base. Il y en a énormément, y compris en français. Voir sur le CRAN dans la section Documentation --> Contributed http://cran.r-project.org/other-docs.html.

Ensuite, il faut s'habituer à écrire clairement le code. Votre exemple est illisible. En respectant le principe d'indentation, il devient:

Code : Tout sélectionner

for(n in 1:nrow(srt3))
  for(srt3[1:n, 2] > 3)
    Q <- sum(srt3[1:n, 1:k] * srt3[1:n, 1:k])


Cela fait immédiatement apparaître que le résultat est un scalaire (nombre) qui est écrasé à chaque itération. Ce n'est probablement pas ce que vous recherchez.

L'expression

Code : Tout sélectionner

srt3[1:n, 2] > 3
a pour valeur un vecteur logique qui n'est pas approprié comme argument à for(). L'erreur vient probablement de là.

Je suspecte que ce que vous recherchez pourrait être qque chose comme:

Code : Tout sélectionner

Q <- vector(mode = "numeric", length = nrow(srt3))
for(n in 1:nrow(srt3))
    Q[n] <- sum(srt3[srt3[1:n, 2] > 3 , ]^2)


Ce qui devrait pouvoir se simplifier en une ligne:

Code : Tout sélectionner

Q <- cumsum(srt3[srt3[ , 2] > 3 , ]^2)


Renaud

Logez Maxime
Messages : 3138
Enregistré le : 26 Sep 2006, 11:35

Messagepar Logez Maxime » 19 Déc 2006, 13:44

Bonjour,


Je ne sais pas si je vais répondre correctement à ta question mais je vais essayé. Si je comprends bien tu veux effectuer ton calcul uniquement sur pour les lignes de la deuxième colonne supérieure à 3 alors il faut que ta boucle sur les lignes qui est ton premier for se fasse uniquement sur ces lignes la tu as plusieurs façon pour récupérer l'information :

Code : Tout sélectionner

srt3 <- matrix(rnorm(20,3,1),10,2)
srt3
          [,1]     [,2]
 [1,] 3.967942 3.754213
 [2,] 1.946929 3.399120
 [3,] 2.141729 2.371613
 [4,] 1.830191 2.142292
 [5,] 2.045582 1.842223
 [6,] 2.709870 2.713192
 [7,] 1.464278 1.668538
 [8,] 2.874854 1.671262
 [9,] 1.756746 3.054997
[10,] 3.147519 3.509496

# tu peux récupérer l'info comme ça :
which(srt3[,2]>3)
[1]  1  2  9 10
# et la tu as les numéros des lignes pour lesquelles ta condition est vérifiée
#et faire ta boucle la dessus :
for (n in which(srt3[,2]>3)){


Mais à ce moment la ton sum de srt3[1:n, 1:k] n'a plus de sens je pense car ici les numéros de lignes ne sont plus continus et que du coup tu vas faire dans un cas 1:1 puis à la deuxième boucle 1:2, à la troisième 1:9... Le problème ici n'est pas de synthaxe imbriquée mais de bien relier le for avec l'indexation de la matrice est-ce que n fait référence aux lignes ou aux colonnes ?!

Par contre si tu veux maintenir ton calcul tel qu'il est mais ne le faire que sur "la sous matrice" avec les valeurs de la colonne 2 >3 alors tu peux refaire ton calcul sur la matrice réduite :

Code : Tout sélectionner

srt3red <- srt3[which(srt3[,2]>3),]
# ou encore
srt3red <- srt3[srt3[,2]>3,]
for (n in 1:nrow(srt3red)){
 for (k in 1:ncol(srt3red))
  Q=sum(srt3red[1:n,1:k]*srt3red[1:n,1:k])
}


ou lors il te faut procéder de cette façon mais je ne trouve pas ça très "propre"

Code : Tout sélectionner

for (n in 1:length(which(srt3[,2]>3))){
  for (k in 1:ncol(srt3))
    Q=sum(srt3[srt3[,2]>3,][1:n,1:k]*srt3[srt3[,2]>3,][1:n,1:k])
    }

ici aussi tu vas travailler sur la matrice réduite qui t'intéresse mais bon je touve pas ça très "propre" comme code. Bon faut bien faire gaffe à chaque fois dans ta boucle pour savoir ou intervient la lettre que tu as mis dans le for.

En espérant t'avoir aider un peu.

Maxime

Céline MIR
Messages : 15
Enregistré le : 15 Déc 2006, 17:46

Messagepar Céline MIR » 20 Déc 2006, 14:19

Bonjour !
Merci beaucoup pour vos réponses, cela m'aide à mieux saisir la logique et le langage de R.
En me basant également sur la documentation et certains exemples que j'ai pu trouver, j'ai essayé de transcrire le calcul que je veux réellement effectuer (il ne s'agit plus d'un exemple sur lequel je m'entraine).

cela donne :

Code : Tout sélectionner

for (I in 1:max(IDP))
+ + + + + for (n in min(niv1): max(niv1))
+ + + + + for (k in 1:nrow(srt))
+ + + + + {f5$Hcor[f5$IDP==I & f5$niv==n]=f5$Hobs[f5$IDP==I & f5$niv==n]-sum(srt[k,"sr"]*f5$Hobs[f5$IDP==I & f5$niv==n+(srt[k,"Nums"])])}


En "français", j'ai deux tableaux:
1) f5 a comme colonne IDP (dont la valeur I va de 1 à max(IDP), niv (pour chaque I, la valeur n de niv va de min(niv1) à max(niv1), Hobs et Hcor (les 2 changeant pour chaque valeur de n pour chaque I).
2) srt a pour colonne sr et Nums).

Dans f5, je veux que la valeur de Hcor correspondant à I et n soit égale à :
la valeur Hobs pour ces mêmes I et n
de laquelle on soustrait
la somme (réalisée pour chaque ligne k de srt) de [la valeur sr de srt multiplié par la valeur de Hobs du même I mais pour une valeur de niv = n+la valeur Nums de srt ].

J'espère être claire...
En tout cas, ma formulation fonctionne partiellement : cela ne prend pas en compte toutes les lignes k de srt (j'ai 2 lignes dans srt, cela ne prend en compte que les valeurs de la dernière ligne). J'ai fait de nombreux essais de formulations différentes, en vain.
Je suis loin de maitriser l'écriture sous R, je continue à me documenter et à chercher la solution à mon problème, mais si quelqu'un a une suggestion, je suis preneuse !!!
Merci beaucoup par avance
Céline

Logez Maxime
Messages : 3138
Enregistré le : 26 Sep 2006, 11:35

Messagepar Logez Maxime » 20 Déc 2006, 15:15

Bonjour,


je dois avouer que pour moi ce que tu veux faire n'est pas très claire surtout concernant la partie : la somme (réalisée pour chaque ligne k de srt) de [la valeur sr de srt multiplié par la valeur de Hobs du même I mais pour une valeur de niv = n+la valeur Nums de srt ].

Alors est-ce que ceci est correcte :
Pour chaque ligne de f5 (à une ligne correspond un couple I,n) Hcor = Hobs-somme(sr*Hobs) pour le Hobs qui coresspond à niv+num ?
La je vois déjà un problème y a t'il autant de ligne dans f5 que dans srt ? Veux tu que tous les sr soient multipliés par une seule valeur Hobs qui correspond a niv+num? Mais num prend il plusieurs valeurs ? enfin j'avoue ne pas avoir très bien saisi ce que tu voulais vraiment faire mais ave ce que j'ai compris ça ressemblait à ça :

Code : Tout sélectionner

for (i in 1:nrow(f5)){
f5$cor[i] <- f5$obs[i]-sum(srt$sr*f5$obs[f5$niv==(f5$niv[i]+srt$num)])
}


Mais je crois qu'il faudrait vraiment que tu donnes quelques lignes de chaque tableaux et que tu expliques encore plus clairement ce que tu souhaites faire.

Maxime

Céline MIR
Messages : 15
Enregistré le : 15 Déc 2006, 17:46

Messagepar Céline MIR » 20 Déc 2006, 16:46

Re bonjour !

Merci de ta réponse. Je vais essayer d'être plus claire.

Donc j'ai un tableau f5, avec comme colonne
- "IDP", qui correspond à un numéro de population I
- "niv", qui correspond à un niveau chiffré n (en paires de bases) (n va de 159 à 169)
- "Hobs" dont la valeur change pour chaque couple (I,n)
- "Hcor" qui est ce que je veux avoir (pour l'instant ls valeurs sont nulles)

Ce qui est important, c'est que les valeurs de Hobs et Hcor varient en fonction de I et de n, pas seulement de l'un des deux, car pour chaque population I on a les mêmes valeurs de n.

Un petit bout de tableau f5 donne :

Code : Tout sélectionner

  IDP niv     Hobs         Hcor

46   5 160 0.0476486  0.000000000
45   5 159 0.0000000  0.000000000
66   6 169 0.0000000  0.000000000
65   6 168 0.0000000  0.000000000
64   6 167 0.0000000  0.000000000
63   6 166 0.0000000  0.000000000
62   6 165 0.0000000  0.000000000
61   6 164 0.0000000  0.000000000
60   6 163 0.0000000  0.000000000
59   6 162 0.0000000  0.000000000
58   6 161 0.0000000  0.000000000
57   6 160 0.9170650  0.000000000
56   6 159 0.1104400  0.000000000
77   7 169 0.6584370  0.000000000
76   7 168 0.0000000  0.000000000
75   7 167 0.0000000  0.000000000
74   7 166 0.0384363  0.000000000
73   7 165 0.0000000  0.000000000
72   7 164 0.0000000  0.000000000
71   7 163 0.3239430  0.000000000
70   7 162 0.0000000  0.000000000
69   7 161 0.0000000  0.000000000
68   7 160 0.3511630  0.000000000
67   7 159 0.0000000  0.000000000


Mon tableau srt comprend:
- une colonne "sr", qui correspond à un coefficient
- une colonne "Nums" qui donne pour chaque valeur de sr un nombre
Dans mon cas, srt est assez simple, mais il pourra y avoir beaucoup plus de lignes :

Code : Tout sélectionner

         sr Nums
[1,] 0.1444    1
[2,] 0.0619    3


Donc, pour en revenir à mon calcul de Hcor :
pour une valeur de I et de n données, Hcor =
la valeur de Hobs pour ces mêmes I et n
de laquelle on soustrait
la somme de (sr x Hobs de la même I mais pour le niveau n+(Nums de sr)), (sr x Hobs est calculé pour chaque sr, puis le tout est additionné).

Le mieux est encore de prendre un exemple:
pour I = 7 (valeur de IDP) et n = 160 (valeur de niv), en bas de f5 :
Hcorr de I=7 et n=160 est = à
0.3511630 (qui est Hobs pour I = 7 et n = 160) - [0.1444 (qui est un 1er sr) * 0 (qui est Hobs à n+Nums de ce 1er sr =160+1=161) + 0.0619 (qui est le 2eme sr) * 0.3239430 (qui est Hobs pour n+Nums de ce 2eme sr = 160+3 = 163)].
Il s'agit de répéter ce calcul pour chaque couple n/I de f5.

J'espère que c'est un peu plus clair...

Je ne vois pas vraiment comment travailler avec les lignes i de f5, je pensais plutôt qu'il fallait bien préciser I et n pour éviter des chevauchements entre les différentes I....
Je vais continuer à chercher, en tout cas merci pour ton aide... si tu as d'autres suggestions...je prends !
Céline

Renaud Lancelot
Messages : 2484
Enregistré le : 16 Déc 2004, 08:01
Contact :

Messagepar Renaud Lancelot » 20 Déc 2006, 23:14

Si j'ai bien compris...

Données, réordonnées pour ce qui concerne f5:

Code : Tout sélectionner

> f5 <- f5[order(f5$IDP, f5$niv), ]
> f5
   IDP niv      Hobs Hcor
2    5 159 0.0000000    0
1    5 160 0.0476486    0
13   6 159 0.1104400    0
12   6 160 0.9170650    0
11   6 161 0.0000000    0
10   6 162 0.0000000    0
9    6 163 0.0000000    0
8    6 164 0.0000000    0
7    6 165 0.0000000    0
6    6 166 0.0000000    0
5    6 167 0.0000000    0
4    6 168 0.0000000    0
3    6 169 0.0000000    0
24   7 159 0.0000000    0
23   7 160 0.3511630    0
22   7 161 0.0000000    0
21   7 162 0.0000000    0
20   7 163 0.3239430    0
19   7 164 0.0000000    0
18   7 165 0.0000000    0
17   7 166 0.0384363    0
16   7 167 0.0000000    0
15   7 168 0.0000000    0
14   7 169 0.6584370    0
>
> srt
         sr Nums
[1,] 0.1444    1
[2,] 0.0619    3
>

Algorithme:

1. on partitionne le tableau f5 en sous-tableaux définis par les différentes valeurs de IDP

2. Pour chaque sous tableau, et pour chaque ligne du tableau (boucle for)
* On vérifie si il existe une valeur de Hobs correspondant au calcul souhaité (condition if)
* Si oui, on effectue le calcul,
* Si non, on retourne une valeur manquante pour Hcor
NB: on teste qu'il existe une et une seule valeur pour chaque "composante" de Hcor en faisant la somme du vecteur logique retournée par le test de comparaison (FALSE = 0 et TRUE = 1).

Code : Tout sélectionner

> Liste <- by(f5, list(IDP = f5$IDP), function(x){
+   for(i in seq(nrow(x))){
+     if(sum(x$niv == (x$niv[i] + srt[,"Nums"][1])) == 1 & sum(x$niv == (x$niv[i] + srt[,"Nums"][2])) == 1)
+       x$Hcor[i] <- x$Hobs[i] - (srt[,"sr"][1] * x$Hobs[x$niv == x$niv[i] + srt[,"Nums"][1]] +
                                  srt[,"sr"][2] * x$Hobs[x$niv == x$niv[i] + srt[,"Nums"][2]])
+     else
+       x$Hcor[i] <- NA
+     }
+   x
+   })
>

f5 étant un data.frame, le résultat du calcul est une liste de data.frame's.

Code : Tout sélectionner

> Liste
IDP: 5
  IDP niv      Hobs Hcor
2   5 159 0.0000000   NA
1   5 160 0.0476486   NA
---------------------------------------------------------------------------------------------------------------------
IDP: 6
   IDP niv     Hobs        Hcor
13   6 159 0.110440 -0.02198419
12   6 160 0.917065  0.91706500
11   6 161 0.000000  0.00000000
10   6 162 0.000000  0.00000000
9    6 163 0.000000  0.00000000
8    6 164 0.000000  0.00000000
7    6 165 0.000000  0.00000000
6    6 166 0.000000  0.00000000
5    6 167 0.000000          NA
4    6 168 0.000000          NA
3    6 169 0.000000          NA
---------------------------------------------------------------------------------------------------------------------
IDP: 7
   IDP niv      Hobs         Hcor
24   7 159 0.0000000 -0.050707937
23   7 160 0.3511630  0.331110928
22   7 161 0.0000000  0.000000000
21   7 162 0.0000000 -0.046777369
20   7 163 0.3239430  0.321563793
19   7 164 0.0000000  0.000000000
18   7 165 0.0000000 -0.005550202
17   7 166 0.0384363 -0.002320950
16   7 167 0.0000000           NA
15   7 168 0.0000000           NA
14   7 169 0.6584370           NA
>

Il ne reste plus qu'à les empiler avec la fct do.call:

Code : Tout sélectionner

> do.call("rbind", Liste)
     IDP niv      Hobs         Hcor
5.2    5 159 0.0000000           NA
5.1    5 160 0.0476486           NA
6.13   6 159 0.1104400 -0.021984186
6.12   6 160 0.9170650  0.917065000
6.11   6 161 0.0000000  0.000000000
6.10   6 162 0.0000000  0.000000000
6.9    6 163 0.0000000  0.000000000
6.8    6 164 0.0000000  0.000000000
6.7    6 165 0.0000000  0.000000000
6.6    6 166 0.0000000  0.000000000
6.5    6 167 0.0000000           NA
6.4    6 168 0.0000000           NA
6.3    6 169 0.0000000           NA
7.24   7 159 0.0000000 -0.050707937
7.23   7 160 0.3511630  0.331110928
7.22   7 161 0.0000000  0.000000000
7.21   7 162 0.0000000 -0.046777369
7.20   7 163 0.3239430  0.321563793
7.19   7 164 0.0000000  0.000000000
7.18   7 165 0.0000000 -0.005550202
7.17   7 166 0.0384363 -0.002320950
7.16   7 167 0.0000000           NA
7.15   7 168 0.0000000           NA
7.14   7 169 0.6584370           NA


Bon, je pars en vacances ;-)

Renaud


Retourner vers « Questions en cours »

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 1 invité