Une boucle pour calculer un cumul sous condition ?

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

Stéphane Adrover
Messages : 8
Enregistré le : 13 Nov 2017, 10:56

Une boucle pour calculer un cumul sous condition ?

Messagepar Stéphane Adrover » 27 Juin 2019, 13:17

Bonjour,
Il y a des choses a priori très simples à faire dans Excel que je n’arrive pas à reproduire dans R.
Je vous expose mon problème. Mon fichier est une base de données météo.
[img]
DATE an moisjmois tmini tmaxitmoy preci sec
19210101 1921 0101 01 2,4 17,2 9,8 0 1
19210102 1921 0102 01 6 10,7 8,3 2,6 0
19210103 1921 0103 01 2,6 9,9 6,2 0 1
19210104 1921 0104 01 6,5 11,4 8,9 0 2
19210105 1921 0105 01 -0,8 12,9 6 0 3
19210106 1921 0106 01 1 12,1 6,5 0 4
19210107 1921 0107 01 -0,3 12,1 5,9 0 5
19210108 1921 0108 01 -0,8 11,1 5,1 0,7 0
19210109 1921 0109 01 4 9,9 7 0 1

[/img]

La variable preci est le volume de précipitation du jour. Je souhaite compter le nombre de jours consécutifs sans précipitation. Dans Excel, rien de plus simple : je crée une colonne « sec » , mets la valeur correspondante pour la 1ère observation, et pour la suivante la formule =SI(H3=0;I2+1;0), et je copie/colle la formule.

J’ai essayé pas mal de chose pour faire la même chose dans R, sans succès.
Par exemple
tab$sec<-ifelse(tab$preci==0,lag(tab$sec)+1,0)
Ca ne cumule pas

J’ai aussi essayé une boucle :
repeat {
montelim$sec <- 0
if (montelim$preci==0) {montelim$sec+1
} else {
break
}
}

La boucle tourne et ne s’arrête pas.

J'imagine que la solution est dans la création d'une boucle, mais je ne maitrise pas du tout !

Quelqu’un pourrait-il me donner une solution ? Merci d’avance !

Serge Rapenne
Messages : 1426
Enregistré le : 20 Aoû 2007, 15:17
Contact :

Re: Une boucle pour calculer un cumul sous condition ?

Messagepar Serge Rapenne » 27 Juin 2019, 13:38

Bonjour,

avec R c'est tout aussi facile sinon plus,

Code : Tout sélectionner

dta<-structure(list(DATE = 19210101:19210109, an = c(1921L, 1921L,
1921L, 1921L, 1921L, 1921L, 1921L, 1921L, 1921L), mois = 101:109,
    jmois = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), tmini = c(2.4,
    6, 2.6, 6.5, -0.8, 1, -0.3, -0.8, 4), tmaxi = c(17.2, 10.7,
    9.9, 11.4, 12.9, 12.1, 12.1, 11.1, 9.9), tmoy = c(9.8, 8.3,
    6.2, 8.9, 6, 6.5, 5.9, 5.1, 7), preci = c(0, 2.6, 0, 0, 0,
    0, 0, 0.7, 0), sec = c(1L, 0L, 1L, 2L, 3L, 4L, 5L, 0L, 1L
    )), class = "data.frame", row.names = c(NA, -9L))

#on ajoute une colonne qui contient TRUE s'il y a plu, FALSE dans le cas contraire

 dta$Pluie<-dta$preci!=0
> dta
      DATE   an mois jmois tmini tmaxi tmoy preci sec Pluie
1 19210101 1921  101     1   2.4  17.2  9.8   0.0   1 FALSE
2 19210102 1921  102     1   6.0  10.7  8.3   2.6   0  TRUE
3 19210103 1921  103     1   2.6   9.9  6.2   0.0   1 FALSE
4 19210104 1921  104     1   6.5  11.4  8.9   0.0   2 FALSE
5 19210105 1921  105     1  -0.8  12.9  6.0   0.0   3 FALSE
6 19210106 1921  106     1   1.0  12.1  6.5   0.0   4 FALSE
7 19210107 1921  107     1  -0.3  12.1  5.9   0.0   5 FALSE
8 19210108 1921  108     1  -0.8  11.1  5.1   0.7   0  TRUE
9 19210109 1921  109     1   4.0   9.9  7.0   0.0   1 FALSE

#puis la fonction rle est justement faite pour ton problème
rle(dta$Pluie)
Run Length Encoding
  lengths: int [1:5] 1 1 5 1 1
  values : logi [1:5] FALSE TRUE FALSE TRUE FALSE

La variable length donne le nombre de valeurs consecutives pour chaque values

Serge

Stéphane Adrover
Messages : 8
Enregistré le : 13 Nov 2017, 10:56

Re: Une boucle pour calculer un cumul sous condition ?

Messagepar Stéphane Adrover » 27 Juin 2019, 13:59

Merci pour cette réponse.
En fait mon but est de récupérer le nombre maximum de jours secs consécutifs de chaque année pour voir s'il y a une tendance à l'aggravation des phénomènes de sécheresse ou au contraire atténuation. Comment puis-je récupérer ces résultats ?

Serge Rapenne
Messages : 1426
Enregistré le : 20 Aoû 2007, 15:17
Contact :

Re: Une boucle pour calculer un cumul sous condition ?

Messagepar Serge Rapenne » 27 Juin 2019, 14:25

En supposant que ton jeu de donnée (que j'appelle dta dans la suite) contienne les données pour toutes les années ,

Voici une solution possible

Code : Tout sélectionner

max_consec0<-function(annee,dta){
  tmp<-subset(dta,an==annee)
  tmp$Pluie<-tmp$preci!=0
  l_pluie<-rle(tmp$Pluie)
  lemax<- max(l_pluie$length[!l_pluie$values])
  return(data.frame(an=annee,Max=lemax))
}

sapply(unique(dta$an),max_consec0,dta)


Une autre solution avec le package dplyr

Code : Tout sélectionner

library(dplyr)
dta %>%
  group_by(an) %>%
  do({tmp <- with(rle(.$preci==0), lengths[values])
  data.frame( Max=if(length(tmp)==0) 0
             else max(tmp)) }) %>%
  slice(1L)


Serge

Stéphane Adrover
Messages : 8
Enregistré le : 13 Nov 2017, 10:56

Re: Une boucle pour calculer un cumul sous condition ?

Messagepar Stéphane Adrover » 27 Juin 2019, 14:38

Je vais essayer ça, merci !


Retourner vers « Questions en cours »

Qui est en ligne

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