Boucles for

Bonjour,

J’essaie de mettre en application ce que j’ai appris en cours.

Voici le format de mon fichier:

Je veux retirer le minimum de l’année pour chaque nationalité.
J’ai écrit ceci. Malheureusement, il y a un problème dans mon code, il n’affiche pas le résultat.
Il rentre bien dans les boucles mais les parties en gras ne s’exécutent pas correctement.

annees=[2019,2020,2021,2022]

df_Etr_corrige=pd.DataFrame()

for n in annees:
Nuitees_Etr=0
Nuitees_Etr_corrige=0

calcul du nombre de nuitées initial

for c in df.columns[1:-1]:
    **Nuitees_Etr= df[df["Annee"]==n][c].sum()**

print("En", n, "il avait", Nuitees_Etr,"nuitées estimées")

#correction et calcul des nuitées une fois la correction effectuée
for col in df.columns[1:-1]:
df_corrige[col]=df[df[« Annee »]==n][col]-df[df[« Annee »]==n][col].min()
Nuitees_Etr_corrige += df_corrige[col].sum()

**df_Etr_corrige=pd.concat([df_Etr_corrige,df_corrige[col]],ignore_index=True)**
    
print("En", n, "il avait", Nuitees_Etr_corrige,"nuitées estimées après correction")
print("soit une baisse de ", (Nuitees_Etr_corrige/Nuitees_Etr-1)*100,"%")

df_Etr_corrige.head()

annees = (2019, 2020, 2021, 2022)

df_Etr_corrige = pd.DataFrame()

for annee in annees:
    Nuitees_Etr = 0
    Nuitees_Etr_corrige = 0

# calcul du nombre de nuitées initial

    for col in df.columns[1:]:  # j'ai supprimé l'indice -1 dans le slicing pour pouvoir accéder à la dernière colonne aussi.

        Nuitees_Etr = df[df["Annee"] == annee][col].sum()

    print("En", annee, "il y avait", Nuitees_Etr, "nuitées estimées.")

# correction et calcul des nuitées une fois la correction effectuée

    for col in df.columns[1:]: # pareil que précédemment

        df_corrige[col] = df[df[« Annee »]==annee][col] - df[df[« Annee »]==annee][col].min()

        Nuitees_Etr_corrige += df_corrige[col].sum()

    df_Etr_corrige = pd.concat([df_Etr_corrige, df_corrige[col]], ignore_index = True)
    
    print("En", annee, "il y avait", Nuitees_Etr_corrige, "nuitées estimées après correction.")
    print("soit une baisse de ", (Nuitees_Etr_corrige/Nuitees_Etr - 1)*100,"%")

df_Etr_corrige.head()

Bonjour Anne.
J’ai réécrit ton code pour plus de clarté. Dis-moi si je l’ai mal copié.

Je ne comprends pas la ligne suivante (la première que tu as indiquée avec des étoiles):
Nuitees_Etr = df[df["Annee"] == annee][col].sum()
Tu y calcules la somme de quoi ?; si je lis bien, dans cette ligne tu assignes à la variable Nuitees_Etr la valeur se trouvant à la case annee - col; or on ne peut pas calculer la somme d’une valeur unique.
Tu voulais peut-être plutöt écrire ceci:
Nuitees_Etr += df[df["Annee"] == annee][col] ?

Même incompréhension pour cette ligne:
df_corrige[col] = df[df[« Annee »]==annee][col] - df[df[« Annee »]==annee][col].min()
(tu calcules le minimum d’une valeur unique?)

La dernière colonne est la colonne de l’année, donc justement je veux l’exclure.

Mon DataFrame est construit ainsi:

Index / Date (ex: 2019 - 01 - 01) / Algérie / Allemagne…/ Zimbabwe / Annee

Le tableau affiche le nombre de nuitées réalisées par nationalité et par jour.
Je rencontre beaucoup de difficultés:

-Déjà j’ai voulu mettre toute les variables pays en int et il ne veut pas pourtout il n’y pas de NaNs ou de charactères.

df[« Annee »]=df[« date »].dt.year
df=df.fillna(0)
df[1:-1].astype(np.int64)
df.head(1)

A l’intérieur des colonnes des pays, il y a des volumes de nuitées. Ces variables sont des int ou float.

Je voulais ensuite créer une colonne cumul mais cela ne fonctionne pas
df[« cumul »]=df[1:-1].apply(np.sum, axis=1)

Dans mon dataframe, j’ai des données qui courent entre le 1er janvier 2019 et le 28 mars 2023. J’ai ainsi 4 années complètes : 2019, 2020,2021,2022

Je fais ainsi une 1ère boucle pour parcourir les années.

A chaque année, je calcule le nombre de nuitées réalisées durant l’année toute nationalité confondue.

Ensuite je construis un autre dataframe qui sera le précédent dataframe - le minimum chaque année pour chaque nationalité.
Puis je calcule la somme des nuitées toutes nationalités confondues et je fais le rapport pour voir de combien cette solution à réduit le nombre de nuitées toute nationalité confondue

J’ai voulu représenter sur un même graphique les 2 courbes.
plt.plot(df_2019_2022[« date »],df_2019_2022[« Algerie »],df_2019_2022[« date »],df_nettoye[« Algerie »])

mais cela ne fonctionne pas. ne s’affiche que la 2nde courbe.

  1. Avec la méthode astype tu n’as créé qu’une copie (provisoire) du DF avec le type modifié, mais tu ne l’as pas conservée dans une variable, ce qui fait que par la suite tu travailles toujours avec le type initial.
    Donc, soit tu crées un nouveau DF (df2 = df[1:-1].astype(int)) soit tu mets le paramètre copy de la méthode astype à False (prends garde car cela modifie ton DF original).

  2. dfCumul = df[1:-1].sum(axis=1) marche mieux ?
    Et tu es sûre que tu ne voulais pas plutôt: axis = 0 ?

  3. pour « le nombre de nuitées réalisées durant l’année toutes nationalités confondues », tu peux faire:
    nuitesParAn = [nombre for nombre in df.groupby("Annee").sum().sum()]
    ou simplement:
    dfAnnes = df.groupby("Annee").sum().sum()

  4. Je ne suis pas sûr d’avoir compris de quel « précédent dataframe » tu parles dans ta phrase:

« un autre dataframe qui sera le précédent dataframe - le minimum chaque année pour chaque nationalité ».

1 Like

Merci beaucoup pour votre retour.

  1. Bien sûr! c’est un oubli.
    J’ai essayé votre code. il n’a pas aimé: cannot astype a datetimelike from [datetime64[ns]] to [int32]. Bon ça ne me gêne qu’esthétiquement…

  2. cela créé bien la colonne et fait le calcul attendu, par contre j’ai un souci avec l’écriture [1,-1]. car il ne me fait pas la somme de la 1ère ligne et de la dernière ligne et me créé ainsi 2 NaNs. cela veut dire qu’il doit ajouter toutes les colonnes, ainsi l’année aux nationalités. :thinking:
    J’ai vraisemblablement un souci pour travailler sur certaines colonnes.

  3. Dans ce code, visiblement je remplace la valeur de df_2019 par celle de df_2019_corrigé. J’ai l’impression que c’est sur cette ligne pourtant je n’ai pas l’impression que le code écrase df_2019. J’avais fait cela pour créer un dataframe avec le même format.

df_2019=df[df[« Annee »]==2019]

Nuitees_Etr_2019=0
Nuitees_Etr_2019_corrige=0
df_2019_corrige = df_2019

calcul du nombre de nuitées initial en 2019

for c in df_2019.columns[1:-1]:
Nuitees_Etr_2019+= df_2019[c].sum()

for col in df_2019.columns[1:-1]:
df_2019_corrige[col]=df_2019[col]-df_2019[col].min()
Nuitees_Etr_2019_corrige+= df_2019_corrige[col].sum()

  1. j’ai essayé dfAnnes = df.groupby(« Annee »).sum().sum(). je ne comprends pas cela renvoie pas du tout ce que j’imaginais. Je ne comprends pas du tout pourquoi. c’est comme si tout était à l’envers :thinking:
    Algerie 8669454.0
    Allemagne 8379373.0
    Autriche 604152.0
    Belgique 3787956.0
    Bresil 986700.0

    Venezuela 14195.0
    Viêt Nam 121014.0
    Wallis-et-Futuna 42.0
    Zambie 643.0
    Zimbabwe 540.0
    Length: 128, dtype: float64

Pour le graph, j’ai réussi si je règle le pb de 2019 qui est remplacé:
%matplotlib inline
import matplotlib.pyplot as plt

df_pays=df_2019_2022[[« date »,« Algerie »]]

df_pays_nettoye = df_nettoye[[« date »,« Algerie »]]

df_pays_nettoye = df_pays_nettoye.rename(columns= {« Algerie » : « Algerie_corrige » })
df_comparaison = df_pays.merge(right=df_pays_nettoye,on=« date »)
df_comparaison.head()
df_comparaison.plot(x=« date »,y=[« Algerie », « Algerie_corrige »],title=« Comparaison entre les nuitées livrées et celles recalculées en deduisant le minimum - Algérie »)

Et avec axis = 0 ?

Je pense que c’est dû à un oubli de ma part:
dfAnnees = df[1:-1].groupby("Annee").sum().sum()

Qu’est-ce qui te donne l’impression que le code n’écrase pas df_2019 ?

Lorsque je fais un .head ou lorsque je fais le graphique, les 2 courbes se superposent.

Je pense que j’ai un problème de format du fichier. Le plus simple c’est de recommencer avec le bon format, peut-être que cela fonctionnera mieux?

Bonjour,

J’ai recommencé du coup à zéro.
j’ai importé les données brutes (avant j’avais transposé sous excel un fichier global).
1 fichier par bimestriel. J’ai réussi à concaténer les 6 fichiers de l’année pour constituer un fichier annuel. :+1:

J’ai filtré sur les touristes parmi les segments car ce sont les seuls segments qui nous intéressent aujourd’hui. :+1:

J’obtiens ainsi le fichier annuel suivant:

et là je suis à nouveau perdue dans mes filtrages :persevere:

Je veux que pour chaque ligne, le volume soit amputé du minimum du pays.
J’ai ainsi construit un df_min_2019, qui n’est autre qu’un groupby qui calcul le volume minimum par nationalité. :+1:

Ensuite je sèche. J’ai écrit ceci:
df_2019_touriste_corrige=df_2019_touriste

for l in df_2019_touriste_corrige.index:
pays=df_2019_touriste_corrige.loc[l,« Pays »]
df_2019_touriste_corrige.loc[l,« Volume »]-= df_min_2019[« Volume »].iloc(pays)

il me renvoie ceci

Je pense avoir réussi :+1: :
df_2019_touriste_corrige=df_2019_touriste

for l in df_2019_touriste_corrige.index:
pays=df_2019_touriste_corrige.loc[l,« Pays »]
df_2019_touriste_corrige.loc[l,« Volume »] = df_2019_touriste_corrige.loc[l,« Volume »] - df_min_2019.loc[pays, ‹ Volume ›]

df_2019_touriste_corrige.head()

Bonjour Anne,
Je suis ravi de l’apprendre. S’il y a encore une incompréhension, n’hésitez pas.

Bonne journée à vous :slight_smile:

Je vous remercie. Je tente de m’entrainer sur mes données du travail et d’automatiser. Je risque de vous déranger…
J’ai une question sans réponse :

Lorsque mon fichier à des dates type datatime
01/01/2022 08:00:00
01/01/2022 09:00:00
01/01/2022 11:00:00
01/01/2022 12:00:00

comment repérer les créneaux manquants? Dans mon exemple le 01/01/2022 10:00:00 et ajouter la ligne correspondante?

Une solution possible serait de boucler sur cette liste de datetime et de vérifier si l’écart est bien égal à une heure. Si ce n’est pas le cas, c’est qu’il y a un trou.

Je vous remercie. Je vais y réfléchir.

Par ailleurs, j’ai réussi à construire ce tableau.

Je veux afficher les lignes par exemple pays = cumul et toutes les années.

Comment peut-on filtrer quand il y a 2 index?

Je vous remercie,

Anne

Idem, je voulais organiser par pays puis par année, pour l’instant je n’y suis pas arrivée avec un sort-values().

Rebonjour,

J’ai un point de blocage ici:

Je veux calculer la part des nuitées que l’on doit retirer. J’ai mis une condition if mais cela ne fonctionne pas: Si le minimum 365 > au total alors on considère que l’on déduire le socle et on va calculer le minimum365/le total

C’est bon je pense avoir réussi :+1: