• Aucun résultat trouvé

1 Lire un fichier

N/A
N/A
Protected

Academic year: 2021

Partager "1 Lire un fichier"

Copied!
11
0
0

Texte intégral

(1)

C OURBES EXPÉRIMENTALES

OBJECTIF :L’objectif de ce tp est de rendre l’élève capable :

• d’ouvrir un fichier de points et de les représenter dans un graphique

• de tracer des courbes et les mettre en forme

• d’obtenir les coefficients d’une régression linéaire

1 Lire un fichier

1.1 Préparation des documents et consignes

Tout d’abord, il faut se placer dans le dossier lié au Tp :

~/INFO/1-INTRO/INTRO-2/ . Le fichier .py que vous écrirez doit com- porter la première lettre de votre prénom, votre nom et le numéro du Tp (pnom-INTRO-2-Tp-2.py) et sera corrigé par un automate (petit programme perso). Veilliez donc au respect des consignes !

La réponse à chaque question devra être précédée du numéro de la question sous la forme# Question N. Si une fonction doit être créée, prévoir un test de la fonction comme dans l’exemple ci-contre :

# Question 0 def Exemple(a,b):

return ...

# Test de Exemple(a,b) print(Exemple(2,3))

Le Tp est livré avec un fichierpts-exp-rc.txt. Il s’agit des points expérimentaux de mesure de la charge d’un conden- sateur. Placer ce fichier dans le répertoire (ou dossier) consacré à ce Tp.

1.2 Récupérer un tableau de données de façon éclair avec numpy

Pour récupérer un tableau de données enregistrées dans un fichier.txt, le plus simple est de charger la fonctionloadtxt du modulenumpy. Comme vu dans le Tp précédent, il est possible d’importer un module via un alias (icinp) pour appeler les éléments contenus dans le module.

# Charger le module numpy via un alias np import numpy as np

t, val =np.loadtxt('pts-exp-rc.txt', unpack = True) ou bien

# Charger juste la fonction loadtxt de numpy from numpy import loadtxt

t, val =loadtxt('pts-exp-rc.txt', unpack = True) ou encore

# Charger tout numpy pour ne pas se poser de question (mais c'est plus lourd !) from numpy import *

t, val =loadtxt('pts-exp-rc.txt', unpack = True)

(2)

REMARQUE: Lorsque le module est importé une fois dans le fichier.py, il n’est pas nécessaire de le réimporté à chaque question. On prendra donc l’habitudede mettre les modulestout en hautdu fichier, juste après déclaration (auteur, date, thème).

Q - 1:Récupérer les points expérimentaux du fichierpts-exp-rc.txt.

REMARQUE:parfois, la chance n’est pas au rendez-vous et le message suivant peut apparaître : ValueError: could not convert string to float: b’\xef\xbb\xbf’

ATTENTION !Le fichier.txtn’est pas encodé au bon format (UTF-16BE). C’est ce qui est écrit page 110 du bouquin Fluent Python. C’est de la faute de Windows®!! Il suffit d’enregistrer le fichier de points avec Wordpad et non avec le Notepad. . .

Q - 2:Tester l’importation des points :

• soit en écrivant dans l’interpréteurtpuis en tapant la toucheentréepour exécuter l’instruction

• soit dans l’éditeur en écrivantprint(t)puis en tapantF5pour exécuter le fichier puis faire de même avecval.

On comprend donc qu’avec deux colonnes dans le fichier, la première est rangée danstla deuxième dansval.

Comment faire quand on ne connaît pas le nombre de colonnes ? Le plus simple est de tout ranger dans un tableau mais on verra cela dans un autre Tp. Pour les curieux, c’est dans la partie 5.

1.3 Ouvrir un fichier.txtet récupérer les données à la main. . .

REMARQUE:Ne pas passer trop de temps sur cette partie. Il s’agit ici de refaire à la main ce queloadtxtdenumpyfait très bien tout seul. Un Tp ultérieur nous permettra de manipuler des fichiers (de chaînes) de caractères. La zapper conduit à la partie 2.1.

1.3.1 Préparation du fichier avec tabulations

On considère ici que le fichier est dans le même répertoire que le script.

Soit le fichier texte, appelédata.txt. Y placer le contenu ci-contre :

0 1

1 3

4.5 6 7.8 2.5

Chaque valeur d’une même ligne est séparée par une tabulation.

Pour ouvrir un fichier on utilise l’instruction open().

#on ouvre le fichier data.txt, en mode lecture fichier=open("data.txt","r")

avec"r"commeread.

1.3.2 Lecture du contenu entier d’un fichier

Pour lire un fichier, on utilise l’instructionread().

(3)

fichier=open("data.txt","r") contenu=fichier.read()

print(contenu)

Une fois la lecture terminée, on ferme le fichier, pour éliminer les problèmes d’accès à ce même fichier :

fichier.close()

Le programme suivant affiche :’0\t1\n1\t3\n4.5\t6\n7.8\t2.5’lorsqu’on tapecontenu. Il s’agit d’une seule variable de typestr. Pour utiliser le contenu du fichier, il convient donc de traiter le résultat précédent pour transformer la variablecontenuen tableau de valeurs.

REMARQUE: \tcorrespond à une tabulation et\nest le caractère réservé pourretour à la ligne. La variable contenu est donc cohérente avec les données du fichier.

OBJECTIF :: A partir du fichier texte, on souhaite créer les deux listes suivantes

t=[0,1,4.5,7.8] et x=[1,3,6,2.5] pour tracerxen fonction det, par exemple.

Tout d’abord, il fautcoupercontenupour enlever les\tet les\n. Pour cela on utilise l’instruction,split():

t1=contenu.split('\n') Cette ligne donne :

['0\t1', '1\t3', '4\t5 6', '7.8\t2.5']

On voit qu’à chaque fois qu’il y un\n, on coupecontenu, et on place les éléments dans une liste. Reste à continuer en coupantles\t.

t2=[]

for i in range(len(t1)):

t2.append(t1[i].split('\t'))

# Ce programme donne :

[['0', '1'], ['1', '3'], ['4', '5 6'], ['7.8', '2.5']]

La variablet2est donc un tableau de 2 lignes et 4 colonnes.

Reste à créer les listes pour tracer les courbes : t=[]

x=[]

for i in range(len(t2)):

t.append(float(t2[i][0])) x.append(float(t2[i][1]))

Ce qui donne :

>>> t

[0.0, 1.0, 4.5, 7.8]

>>> x

[1.0, 3.0, 6.0, 2.5]

A la place defloat, on pouvait aussi utilisereval (ouint mais seulement pour les entiers ou pour prendre la partie entière des valeurs). L’exploitation est donc maintenant possible.

1.3.3 Autre méthode

(4)

Il est possible d’utiliser d’autres instructions comme readlines():

fichier=open("data.txt","r") contenu=fichier.readlines() fichier.close()

# print(contenu)

# Taper contenu affiche :

['0\t1\n', '1\t3\n', '4.5\t6\n', '7.8\t2.5']

Le programme suivant aboutit au même résultat que le précédent :

fichier=open("data.txt","r") contenu=fichier.readlines() t=[]

x=[]

for i in range(len(contenu)):

a=contenu[i].split('\n') b=a[0].split('\t')

t.append(float(b[0])) x.append(float(b[1]))

2 Tracer des courbes avec Python

Pour tracer des courbes sousPython, plusieurs bibliothèques existent. L’une des plus pratiques et utilisées estmatplotlib.

Aussi, pour utiliser les outils de l’algèbre linéaire (manipulation des vecteurs et des matrices), on utilise la bibliothèque numpy. Afin de différencier les éléments denumpyde ceux dematplotlib, ce Tp est présenté avec les deux bibliothèques.

Pour combiner les deux d’un coup, on pourrait utiliserpylab.

On importera donc en début de programme les bibliothèquesmath,numpy et matplotlib.pyploten créant des alias pour chacune d’elle, respectivementm,np etplt.

import math as m import numpy as np

import matplotlib.pyplot as plt

2.1 Tracer une courbe

Pour tracer des courbesa, on utilise l’instructionplot. Pour afficher les figures, on utilise l’instructionshow().

x=[1,2,3]

y=[4,5,6]

plt.plot(x,y) plt.show()

ce programme donne :

a. Les " courbes " tracées sont en fait des segments de droites dont les extrémités sont définies par les éléments successifs d’une liste.

1 .0 1 .5 2 .0 2 .5 3 .0

4 .0 4 .5 5 .0 5 .5 6 .0

Ajouter l’optionblock=Falsedansshow()permet de ne pas avoir à fermer la figure pour continuer le programme.

L’effet secondaire, c’est que la figure suivante se construit sur la figure précédente. Il est possible d’effacer celle d’avant avecplt.clf()ou de numéroter les figures avecplt.figure(n). L’avantage, c’est qu’on peut écrire sur une figure, puis une autre, puis revenir à la première.

Pour avoir toutes les figures sans se poser de questions, on peut mettrenfig=0en début de programme et à chaque nouvelle figure, écrirenfig+=1puisplt.figure(nfig).

Q - 3:Tracer la courbe représentative de l’équation y(t)=yf.

1−e−t/τ

avec yf =5etτ=0,1sur[0,7.τ]et 200 points.

(5)

REMARQUE: On peut très bien faire une jolie boucle pour calculer les 200 abscisses.

tau,n=0.1,200

pas,t=7*tau/(n-1),[0]

for i in range (n-1):

t.append(t[i]+pas)

On peut aussi utiliser la commandelinspacedenumpy: t=linspace(0,0.1,200).

REMARQUE: et plus drôle que la syntaxe for x in X et ligne suivante y=f(x), on peut utiliser y=[f(x) for x in X]. . .

2.2 Définition des axes

Pour définir les domaines des axes, on peut utiliser les instructionsxlim(xmin,xmax)etylim(ylim,ymax).

nfig+=1

plt.figure(nfig)

t=np.linspace(0,10,200) y=[m.sin(i) for i in t ] plt.xlim(-1,11)

plt.ylim(-1.5,1.5) plt.plot(t,y)

plt.show(block=False) 0 2 4 6 8 1 0

− 1 .5

− 1 .0

− 0 .5 0 .0 0 .5 1 .0 1 .5

2.3 Mettre les légendes

On utilise l’instructiontitle()pour rajouter un titre, l’instruction legend() pour rajouter une légende (il faut obligatoire- ment utiliser label pour que la légende soit correctement écrite), et les instructionsxlabel()etylabel()pour rajouter un titre aux axes.

Pour définir les domaines des axes, on peut utiliser les instructions xlim(xmin,xmax) et ylim(ylim,ymax).

t=np.linspace(0,10,200)

y=[m.sin(2*i)*m.exp(-i/5) for i in t ] plt.xlim(-1,11)

plt.ylim(-1.5,1.5)

plt.title("une sinusoide amortie") plt.xlabel("temps en secondes") plt.ylabel(" y(t) en metre") plt.plot(t,y,label="y(t)") plt.legend()

0 2 4 6 8 1 0

t e m p s e n s e c o n d e s

− 1 .5

− 1 .0

− 0 .5 0 .0 0 .5 1 .0 1 .5

y(t) en mètre

u n e s in u s o ïd e a m o rt ie

y (t )

(6)

2.4 Modifier le style des courbes

Il est possible de changer la couleur des courbes, le style des courbes, le symbole des courbes (ou marqueur,marker), et la largeur des courbes.

Chaîne Effet

- solid line style -- dashed line style -. dash-dot line style

: dotted line style . point marker , pixel marker

o circle marker

v triangle_down marker

^ triangle_up marker

< triangle_left marker

> triangle_right marker 1 tri_down marker 2 tri_up marker

3 tri_left marker 4 tri_right marker s square marker p pentagon marker

* star marker h hexagon1 marker H hexagon2 marker

+ plus marker x x marker D diamond marker d thin_diamond marker

| vline marker _ hline marker

Chaîne b g r c m y k w

Couleur bleu vert rouge cyan magenta jaune noir blanc

t,x,y=[],[],[]

for i in range(101):

t.append(i/100)

x.append(m.sin(t[i]*10)) y.append(m.cos(t[i]*10)) plt.ylim(-1.5,1.5)

plt.plot(t,x,'c--v',label="sin(t)")

plt.plot(t,y,'r-s',label="cos(t)",linewidth=4) plt.legend()

plt.xlabel("temps en secondes") plt.title(" sin(t/10) et cos(t/10)") plt.grid()#permet d'ajouter une grille

0 .0 0 .2 0 .4 0 .6 0 .8 1 .0

t e m p s e n s e c o n d e s

− 1 .5

− 1 .0

− 0 .5 0 .0 0 .5 1 .0

1 .5 s in (t /1 0 ) e t c o s (t /1 0 )

s in (t ) c o s (t )

2.5 Définir le ratio abscisse/ordonnée

OBJECTIF :Faire apparaître à l’écran un cercle.

n,x,y=100,[],[]

t=[i*2*m.pi/(n-1) for i in range(n)]

for i in range(n):

x.append(m.cos(t[i])) y.append(m.sin(t[i])) plt.axis('equal')

plt.xlim(-1.5,1.5) plt.ylim(-1.5,1.5)

plt.plot(x,y) − 1 .5 − 1 .0 − 0 .5 0 .0 0 .5 1 .0 1 .5

− 1 .0

− 0 .5 0 .0 0 .5 1 .0

(7)

L’équation paramétrique d’un cercle est :





x(t) = cos(t)

y(t) = sin(t) ∀t∈[0; 2.π].

Pourcontraindreles axes à avoir la même graduation en abscisse et en ordonnée, on place l’instructionaxis(’equal’) avant l’insertion des bornes. Vous pouvez essayer sans et avec.

2.6 Echelle logarithmique

Il n’est pas rare en science d’avoir besoin d’échelles logarithmique. En physique et en SI, on utilise les diagrammes de Bode qui fonctionnent avec une échelle semi-logarithmique.

Pour comparer les vitesses de convergence d’algorithmes, on trace l’erreurεnen fonction de nombre d’itérationsn. Au bout d’un certain nombre d’itérationsm, il est possible de trouver une valeurpet un coefficientKtels que∀n>m |εn+1| ≤ K

εnp

. On parle alors de :

• converge linéaire pourp=1

• converge quadratique pourp=2

Afin de visualiser les évolutions des erreurs, il possible de représenter le log de l’erreur ou l’erreur en échelle logarithmique.

Q - 4 : Ecrire un programme puls(xmin,xmax, nbpts) qui donne une répartition logarithmique de nbptspoints entre10xminet10xmaxinclu.

REMARQUE:Pour obtenir le résultat avec 200 points, les petits malins auront tenté le programme suivant : from numpy import logspace

w=logspace(10**xmin,10**xmax,nbpts) w=np.logspace(10**xmin,10**xmax,nbpts) Q - 5:Tracer les pointspuls(-2,4,1000)sur un graphique en échelle linéaire puis sur un graphique en échelle logarithmique en y

plt.semilogy(puls(-2,4,1000))

plt.grid('on',which='both') #permet de tracer le quadrillage 'fin' plt.show()

REMARQUE: Pour tracer une diagramme semi-logarithmique en x on utilise semilogx() et pour un tracé log-log on utiliseloglog().

2.7 Tracer plusieurs figures dans une même fenêtre

On veut faire apparaitre les deux graphiques précédents cote-à-cote sur une même fenêtre.

On utilisesubplot()pour résoudre afficher plusieurs figures dans une même fenêtre.

• le premier argument de la fonction est le nombre de lignes de figures désiré

• le deuxième, le nombre de colonnes

• le troisième argument, donne le numéro de la figure

Python remplit alors les figures lignes par lignes comme on remplirait les cases d’un tableau, ligne par ligne.

(8)

Ainsi l’exemple précédent donne : plt.subplot(2,1,1)

plt.plot(puls(-2,4,1000),label='echelle lineaire') plt.grid('on',which='both')

plt.xlabel("numero du points") plt.legend()

plt.subplot(2,1,2)

plt.semilogy(puls(-2,4,1000),label='echelle logarithmique en y') plt.grid('on',which='both')

plt.xlabel("numero du points") plt.legend()

plt.suptitle("Echelles logarithmique et lineaires") plt.show()

0 2 0 0 4 0 0 6 0 0 8 0 0 1 0 0 0

n u m é ro d u p o in t s 0

2 0 0 0 4 0 0 0 6 0 0 0 8 0 0 0 1 0 0 0 0

é c h e lle lin é a ire

0 2 0 0 4 0 0 6 0 0 8 0 0 1 0 0 0

n u m é ro d u p o in t s 10-2

10-1 100 101 102 103 104

é c h e lle lo g a rit h m iq u e e n y

Ec h e lle s lo g a rit h m iq u e e t lin é a ire s

(9)

3 Compléments

3.1 Effectuer une régression linéaire

Lorsqu’on veut récupérer le coefficient directeur a et l’ordonnée à l’origine b d’une droite passant au plus près d’un ensemble de points, on peut utiliser la fonctionpolyfit(incluse danspylab).

>>> X=np.linspace(-2,4,1000)

>>> Y=[3*x+1 for x in X]

>>> a,b=np.polyfit(X,Y,1)

>>> print(a,b)

3.0 1.0

Comme polyfit ne s’appelle pas régression linéaire, on com- prend l’intérêt du1dans l’argument. On peut donc faire plus puis- sant !

3.2 Nombres complexes - module et ar- gument

>>> print(abs(-1))

1

>>> print(abs(1j))

1.0

>>> print(abs(1+1j))

1.4142135623730951

>>> a=(1+m.sqrt(3)*1j)/2

>>> print(a.real,a.imag)

0.5 0.8660254037844386

>>> ang_rad=m.atan(a.imag/a.real)

>>> ang_deg=ang_rad*180/m.pi

>>> print(ang_rad,ang_deg)

1.0471975511965976 59.99999999999999

4 Exercices

4.1 Régression linéaire

Lors d’une expérience de chimie (cf M. Barsu), on mesure la concentration d’un produit (en mol/mL). Les mesures sont regroupées dans un tableau ci-contre.

Q - 6:A partir du fichierChimie.txt, placer dans une variabletla liste des instants de mesure et dans une variableCl’évolution de la concentration en fonction de temps.

Q - 7:Tracer sur la même figure mais sur deux graphes différents, l’évolution de la concentration (en mol/L) et de son inverse (en L/mol) en fonction du temps.

Q - 8:A l’aide d’une régression linéaire, déterminer l’évolution de la concentration en fonction du temps.

Q - 9:Superposer aux points expérimentaux, l’évolution modélisée de la concen- tration avec 200 points pris dans l’intervalle [20 ;120].

t (min) [A] (mol/mL)

20 2.77

40 1.92

60 1.47

80 1.19

100 1

120 0.86

4.2 Diagrammes de Bode

OBJECTIF :Tracer les diagrammes de Bode deHpourω∈h

10−2; 103i .

On cherche ici à tracer les diagrammes de Bode de la fonction suivante :H(p)= K

1+τ.p avecK =10 etτ=0,5 s

(10)

10-3 10-2 10-1 100 101 102 103 104 Pu ls a t io n (ra d /s )

− 4 0

− 3 0

− 2 0

− 1 0 0 1 0

2 0 c o u rb e d e g a in

10-3 10-2 10-1 100 101 102 103 104 Pu ls a t io n (ra d /s )

− 8 0

− 6 0

− 4 0

− 2 0

0 c o u rb e d e p h a s e

Dia g ra m m e d e Bo d e c o m p le t

On appelle GdB(ω) le gain en décibel de H(j.ω) et ϕ(ω), la phase deH(j.ω).

Dans le cas de la fonction de transfert du premier ordre, on obtient :

GdB(ω) = 20.log











 K q

1+(τ.ω)2











et ϕ(ω)=−arctan(τ.ω)

Q - 10 : A partir des lignes ci- dessus, écrire un programme per- mettant de tracer les diagrammes de Bode de la fonction du premier ordre donnée.

GdB(ω)=20.log (H(j.ω)) ϕ(ω) = −arg (H(j.ω))

= arctan =(H(j.ω))

<(H(j.ω))

!

Q - 11:Écrire un programme qui prend en argument une fonction de transfertHet une liste de pulsation W et renvoie une liste[W,GdB,phi] où West une liste des pulsations,GdB, une liste des gains associés aux pulsationsWetphi, une liste des phases associées aux pulsationsW.

Q - 12:A partir des lignes ci-dessus, écrire un programme permettant de tracer les diagrammes de Bode d’une fonction de transfert quelconque.

5 Partie optionnelle

5.1 Récupérer avec numpy des tableaux dont on ne connaît pas le nombre de colonnes Si on veut se fabriquer son propre fichier de points, il est possible de recopier le ’texte’ ci-contre dans un nouveau fichier texte (mesdonnees.txt) :

ATTENTION!ce tableau contient 3 colonnes tandis que le fichier fourni n’en contient que 2.

Q - 13:A partir du fichier de pointsmesdonnes.txtranger les données dans un tableauTab.

1 4 6

2 1234 7

2.5 23 8.90

14.5 3 22

12 4 12.345

Tab=np.loadtxt('mesdonnees.txt',unpack=True)

ObserverTab. . . ça devient un peu compliqué :

(11)

>>> Tab

array([[ 1.00000000e+00, 2.00000000e+00, 2.50000000e+00, 1.45000000e+01, 1.20000000e+01],

[ 4.00000000e+00, 1.23400000e+03, 2.30000000e+01, 3.00000000e+00, 4.00000000e+00],

[ 6.00000000e+00, 7.00000000e+00, 8.90000000e+00, 2.20000000e+01, 1.23450000e+01]])

>>> len(Tab)

3

En effet, il y a bien 3 colonnes. Comment récupérer une d’entre elles ?

>>> Tab[0,:]

array([ 1. , 2. , 2.5, 14.5, 12. ])

>>> c0=Tab[0,:]

>>> len(c0)

5

>>> c0[2]

2.5

Le tableau de départ avait donc 3 colonnes et 5 lignes. La commande shapedenumpypermet de connaître la taille du tableau.

La valeurTab[i,j]est celle de la i-1èmecolonnede la j-1èmeligne.

On peut extraire des éléments un sous-tableausTab=Tab[0:2,2:4]:

sTab=Tab[0:2,2:4]

>>> sTab

array([[ 2.5, 14.5], [ 23. , 3. ]])

Surprise (ou pas),0:2ne prend en compte que les valeurs 0 et 1.

De même,2:4, ne prend en compte que les valeurs 2 et 3. Python ne prend pas la dernière valeur. Il va falloir s’y faire.

Ainsi0:ncontient biennvaleurs mais avec le0et pas len.

5.2 Récupérer sans numpy des tableaux dont on ne connaît pas le nombre de colonnes - jouer avec les chaînes de caractères.

La partie 1.3.2 montrer comment récupérer toutes les données dans une unique chaîne de caractère.

Pour obtenir un tableau en bonne et due forme, il convient de traiter la chaîne de caractère où chaque\ntraduit une nouvelle ligne. Reste ensuite à séparer les colonnes en repérant les \t dans la chaîne de caractères.

Voici ci-contre, une proposition de fonction pour remplacernumpy.

""" Lecture de points

a partir d'un fichier texte """

def Lecture(nomfichier):

fichier=open(nomfichier,"r") T=fichier.read()

Tab,C,s,n=[],[],'',len(T) for i in range(n):

if T[i]=='\n':

C.append(eval(s)) Tab.append(C) s=''

C=[]

elif T[i]=='\t':

C.append(eval(s)) s=''

else:

s+=T[i]

C.append(eval(s)) Tab.append(C) fichier.close() return Tab

pts=Lecture("Mesdonnees.txt")

Références

Documents relatifs

== Unregistered application 'VoiceMailMain' == Unregistered application 'MailboxExists' == Unregistered application 'VMAuthenticate' asterisk1*CLI&gt; module

Nous pouvons enchaîner directement avec le composant d’apprentissage que nous allons chercher dans l’onglet CLASSIFY.. Nous ne modifions pas les paramètres du

Enfin, la zone TREE SEQUENCES indique l’évolution de la réduction de l’erreur RE (RE = 1 – R²) en fonction du nombre de feuilles de l’arbre, sur le fichier d’expansion

Il est d’usage avec les réseaux de neurones d’utiliser une fraction des données d’apprentissage, appelé « ensemble de validation » pour suivre l’évolution

Si l’on devait faire un parallèle, il faudrait comparer ces valeurs avec ceux de l’ACP où on ne tenait pas compte de l’endogène pour élaborer les axes factoriels : nous

Nous introduisons maintenant le composant UNIVARIATE DISCRETE STAT (onglet STATISTICS) dans le diagramme, à la suite du DEFINE STATUS.. Nous activons menu VIEW pour accéder

Quatre tests sont automatiquement calculés : le test de SHAPIRO WILK – utilisable uniquement pour un effectif inférieur à 5000 observations ; le test de

Dernier sujet que nous aborderons dans ce didacticiel, nous voulons vérifier que dans un ménage, l’homme a tendance à avoir un salaire plus élevé que celui de la