Vous pouvez interpoler les valeurs manquantes ( N๐โN ) dans ๐ฉโ๐โ๐งโ๐โ๐โ๐ฌโ.D๐โ๐ญโ๐โF๐ซโ๐โ๐ฆโ๐โ et ๐ฉโ๐โ๐งโ๐โ๐โ๐ฌโ.S๐โ๐ซโ๐ขโ๐โ๐ฌโ avec le Mรฉthode ๐ข๐ง๐๐ฌ๐ญ๐๐ง๐ญ๐๐ซ๐ฉ๐จ๐ง๐ญ๐๐ง๐ญ() .
- pandas.DataFrame.interpolate โ documentation de pandas 2.0.3
- pandas.Series.interpolate โ documentation de pandas 2.0.3
- Utilisation de base de ๐ขโ๐งโ๐ญโ๐โ๐ซโ๐ฉโ๐จโ๐ฅโ๐โ๐ญโ๐โ()
- Ligne ou colonne : ๐โ๐ฑโ๐ขโ๐ฌโ
- Nombre maximal de N๐โN successions ร remplir : ๐ฅโ๐ขโ๐ฆโ๐ขโ๐ญโ
- Direction pour interpoler : ๐ฅโ๐ขโ๐ฆโ๐ขโ๐ญโ_๐โ๐ขโ๐ซโ๐โ๐โ๐ญโ๐ขโ๐จโ๐งโ
- Interpoler ou extrapoler ou les deux : ๐ฅโ๐ขโ๐ฆโ๐ขโ๐ญโ_๐โ๐ซโ๐โ๐โ
- Opรฉrer sur place : ๐ขโ๐งโ๐ฉโ๐ฅโ๐โ๐โ๐โ
- Mรฉthode d’interpolation : ๐ฆโ๐โ๐ญโ๐กโ๐จโ๐โ
- Interpolation linรฉaire : ๐ฅโ๐ขโ๐งโ๐โ๐โ๐ซโ , ๐ขโ๐งโ๐โ๐โ๐ฑโ , ๐ฏโ๐โ๐ฅโ๐ฎโ๐โ๐ฌโ
- Utilisation des valeurs existantes : ๐โ๐โ๐ขโ๐ฅโ๐ฅโ , ๐ฉโ๐โ๐โ , ๐โ๐โ๐ขโ๐ฅโ๐ฅโ , ๐โ๐โ๐โ๐คโ๐โ๐ขโ๐ฅโ๐ฅโ
- Spline d’interpolation : ๐ฌ๐จ๐ฎ๐ฌ๐ฌ๐ข๐๐ง ๐๐ฌ๐ญ ๐ฉ๐๐ซ๐ญ๐๐ง
- Autres
- Pour les donnรฉes de sรฉries chronologiques
- Dans le cas oรน le type de donnรฉes ( ๐โ๐ญโ๐ฒโ๐ฉโ๐โ ) est ๐จโ๐โ๐ฃโ๐โ๐โ๐ญโ
Consultez l’article suivant sur la suppression, le remplacement et le comptage des valeurs manquantes.
- pandas : supprime NaN (valeurs manquantes) avec dropna()
- pandas : remplacez NaN (valeurs manquantes) par fillna()
- pandas : dรฉtecter et compter les NaN (valeurs manquantes) avec isnull(), isna()
L’exemple de code de cet article utilise la version 2.0.3 de pandas . NumPy est รฉgalement importรฉ.
import pandas as pd import numpy as np print(pd.__version__) # 2.0.3
Utilisation de base de ๐ขโ๐งโ๐ญโ๐โ๐ซโ๐ฉโ๐จโ๐ฅโ๐โ๐ญโ๐โ()
L’exemple suivant ๐ฉโ๐โ๐งโ๐โ๐โ๐ฌโ.D๐โ๐ญโ๐โF๐ซโ๐โ๐ฆโ๐โ est utilisรฉ.
df = pd.DataFrame({'col1': [0, np.nan, np.nan, 3, 4], 'col2': [np.nan, 1, 2, np.nan, np.nan], 'col3': [4, np.nan, np.nan, 7, 10]}) print(df) # col1 col2 col3 # 0 0.0 NaN 4.0 # 1 NaN 1.0 NaN # 2 NaN 2.0 NaN # 3 3.0 NaN 7.0 # 4 4.0 NaN 10.0
Par dรฉfaut, une interpolation linรฉaire est effectuรฉe sur chaque colonne. La mรชme valeur est rรฉpรฉtรฉe pour N๐โN en bas, tandis que N๐โN en haut reste similaire.
print(df.interpolate()) # col1 col2 col3 # 0 0.0 NaN 4.0 # 1 1.0 1.0 5.0 # 2 2.0 2.0 6.0 # 3 3.0 2.0 7.0 # 4 4.0 2.0 10.0
Ligne ou colonne : ๐โ๐ฑโ๐ขโ๐ฌโ
Si ๐โ๐ฑโ๐ขโ๐ฌโ=1 , l’interpolation est effectuรฉe sur chaque ligne. La mรชme valeur est rรฉpรฉtรฉe pour le N๐โN le plus ร droite , tandis que le N๐โN le plus ร gauche reste inchangรฉ.
print(df.interpolate(axis=1)) # col1 col2 col3 # 0 0.0 2.0 4.0 # 1 NaN 1.0 1.0 # 2 NaN 2.0 2.0 # 3 3.0 5.0 7.0 # 4 4.0 7.0 10.0
Nombre maximal de N๐โN successions ร remplir : ๐ฅโ๐ขโ๐ฆโ๐ขโ๐ญโ
Vous pouvez utiliser l’argument ๐ฅโ๐ขโ๐ฆโ๐ขโ๐ญโ pour spรฉcifier le nombre maximal de valeurs N๐โN consรฉcutives ร interpoler. Par dรฉfaut, ce paramรจtre est dรฉfini sur N๐จโ๐งโ๐โ , ce qui signifie que toutes les valeurs N๐โN consรฉcutives seront interpolรฉes.
print(df.interpolate(limit=1)) # col1 col2 col3 # 0 0.0 NaN 4.0 # 1 1.0 1.0 5.0 # 2 NaN 2.0 NaN # 3 3.0 2.0 7.0 # 4 4.0 NaN 10.0
Direction pour interpoler : ๐ฅโ๐ขโ๐ฆโ๐ขโ๐ญโ_๐โ๐ขโ๐ซโ๐โ๐โ๐ญโ๐ขโ๐จโ๐งโ
Vous pouvez prรฉciser la direction de l’interpolation avec l’argument ๐ฅโ๐ขโ๐ฆโ๐ขโ๐ญโ_๐โ๐ขโ๐ซโ๐โ๐โ๐ญโ๐ขโ๐จโ๐งโ , qui peut รชtre dรฉfini sur ‘๐โ๐จโ๐ซโ๐ฐโ๐โ๐ซโ๐โ’ , ‘๐โ๐โ๐โ๐คโ๐ฐโ๐โ๐ซโ๐โ’ , ou ‘๐๐จ๐ญ๐ข๐๐ง’ .
print(df.interpolate(limit=1, limit_direction='forward')) # col1 col2 col3 # 0 0.0 NaN 4.0 # 1 1.0 1.0 5.0 # 2 NaN 2.0 NaN # 3 3.0 2.0 7.0 # 4 4.0 NaN 10.0 print(df.interpolate(limit=1, limit_direction='backward')) # col1 col2 col3 # 0 0.0 1.0 4.0 # 1 NaN 1.0 NaN # 2 2.0 2.0 6.0 # 3 3.0 NaN 7.0 # 4 4.0 NaN 10.0 print(df.interpolate(limit=1, limit_direction='both')) # col1 col2 col3 # 0 0.0 1.0 4.0 # 1 1.0 1.0 5.0 # 2 2.0 2.0 6.0 # 3 3.0 2.0 7.0 # 4 4.0 NaN 10.0
Comme mentionnรฉ ci-dessus, par dรฉfaut, les valeurs N๐โN supรฉrieures (ou les plus ร gauche) restent prรฉsentes. Cependant, le rรฉglage ๐ฅโ๐ขโ๐ฆโ๐ขโ๐ญโ_๐โ๐ขโ๐ซโ๐โ๐ โ๐ญโ๐ขโ๐จโ๐งโ=’๐โ๐จโ๐ญโ๐กโ’ permet l’interpolation aux deux extrรฉmitรฉs.
print(df.interpolate(limit_direction='both')) # col1 col2 col3 # 0 0.0 1.0 4.0 # 1 1.0 1.0 5.0 # 2 2.0 2.0 6.0 # 3 3.0 2.0 7.0 # 4 4.0 2.0 10.0
Interpoler ou extrapoler ou les deux : ๐ฅโ๐ขโ๐ฆโ๐ขโ๐ญโ_๐โ๐ซโ๐โ๐โ
Vous pouvez dรฉfinir la zone ร interpoler avec l’argument ๐ฅโ๐ขโ๐ฆโ๐ขโ๐ญโ_๐โ๐ซโ๐โ๐โ .
- ‘๐ขโ๐งโ๐ฌโ๐ขโ๐โ๐โ’ : Interpolation uniquement
- ‘๐จ๐ฎโ๐ญโ๐ฌโ๐ขโ๐โ๐โ’ : uniquement une extrapolation
- N๐จโ๐งโ๐โ (par dรฉfaut) : interpolation et extrapolation
print(df.interpolate(limit_area='inside')) # col1 col2 col3 # 0 0.0 NaN 4.0 # 1 1.0 1.0 5.0 # 2 2.0 2.0 6.0 # 3 3.0 NaN 7.0 # 4 4.0 NaN 10.0 print(df.interpolate(limit_area='outside')) # col1 col2 col3 # 0 0.0 NaN 4.0 # 1 NaN 1.0 NaN # 2 NaN 2.0 NaN # 3 3.0 2.0 7.0 # 4 4.0 2.0 10.0 print(df.interpolate(limit_area='outside', limit_direction='both')) # col1 col2 col3 # 0 0.0 1.0 4.0 # 1 NaN 1.0 NaN # 2 NaN 2.0 NaN # 3 3.0 2.0 7.0 # 4 4.0 2.0 10.0
Notez que le terme ยซ extrapolation ยป est utilisรฉ ici pour des raisons pratiques. Pour l’interpolation linรฉaire (par dรฉfaut), les valeurs extรฉrieures ne sont que des rรฉpรฉtitions des valeurs finales, et ne sont pas vรฉritablement extrapolรฉes. Cependant, dans l’interpolation spline dรฉcrite ci-dessous, les valeurs extรฉrieures sont vรฉritablement extrapolรฉes.
Opรฉrer sur place : ๐ขโ๐งโ๐ฉโ๐ฅโ๐โ๐โ๐โ
Comme de nombreuses autres mรฉthodes, vous pouvez modifier directement l’objet d’origine en dรฉfinissant ๐ขโ๐งโ๐ฉโ๐ฅโ๐โ๐โ๐โ=T๐ซโ๐ฎโ๐โ .
df.interpolate(inplace=True) print(df) # col1 col2 col3 # 0 0.0 NaN 4.0 # 1 1.0 1.0 5.0 # 2 2.0 2.0 6.0 # 3 3.0 2.0 7.0 # 4 4.0 2.0 10.0
Mรฉthode d’interpolation : ๐ฆโ๐โ๐ญโ๐กโ๐จโ๐โ
La mรฉthode d’interpolation est spรฉcifiรฉe par le premier argument ๐ฆโ๐โ๐ญโ๐กโ๐จโ๐โ . La valeur par dรฉfaut est ‘๐ฅโ๐ขโ๐งโ๐โ๐โ๐ซโ’ (interpolation linรฉaire).
Interpolation linรฉaire : ๐ฅโ๐ขโ๐งโ๐โ๐โ๐ซโ , ๐ขโ๐งโ๐โ๐โ๐ฑโ , ๐ฏโ๐โ๐ฅโ๐ฎโ๐โ๐ฌโ
Avec ๐ฆโ๐โ๐ญโ๐กโ๐จโ๐โ=’๐ฅโ๐ขโ๐งโ๐โ๐โ๐ซโ’ (par dรฉfaut), l’index est ignorรฉ, mais avec ๐ฆโ๐โ๐ญโ๐กโ๐จโ๐โ=’๐ขโ๐งโ๐โ๐โ๐ฑโ’ ou ๐ฆโ๐โ๐ญโ๐กโ๐จโ๐โ=’๐ฏโ๐โ๐ฅโ๐ฎโ๐โ๐ฌโ’ , il est interpolรฉ ร l’aide de la valeur d’index.
s = pd.Series([0, np.nan, np.nan, 3], index=[0, 4, 6, 8]) print(s) # 0 0.0 # 4 NaN # 6 NaN # 8 3.0 # dtype: float64 print(s.interpolate()) # 0 0.0 # 4 1.0 # 6 2.0 # 8 3.0 # dtype: float64 print(s.interpolate('index')) # 0 0.00 # 4 1.50 # 6 2.25 # 8 3.00 # dtype: float64
Si la colonne d’index contient des chaรฎnes, ๐ฆโ๐โ๐ญโ๐กโ๐จโ๐โ=’๐ฅโ๐ขโ๐งโ๐โ๐โ๐ซโ’ (par dรฉfaut) fonctionne correctement, mais si ๐ฆโ๐โ๐ญโ๐กโ๐จโ๐โ est dรฉfini sur ‘๐ขโ๐งโ๐โ๐โ๐ฑโ’ ou ‘๐ฏโ๐โ๐ฅโ๐ฎโ๐โ๐ฌโ’ , une erreur est fournir.
s.index = list('abcd') print(s) # a 0.0 # b NaN # c NaN # d 3.0 # dtype: float64 print(s.interpolate()) # a 0.0 # b 1.0 # c 2.0 # d 3.0 # dtype: float64 # print(s.interpolate('index')) # TypeError: Cannot cast array data from dtype('O') to dtype('float64') according to the rule 'safe'
Utilisation des valeurs existantes : ๐โ๐โ๐ขโ๐ฅโ๐ฅโ , ๐ฉโ๐โ๐โ , ๐โ๐โ๐ขโ๐ฅโ๐ฅโ , ๐โ๐โ๐โ๐คโ๐โ๐ขโ๐ฅโ๐ฅโ
Les valeurs N๐โN sont remplies avec la valeur existante prรฉcรฉdente si ๐ฆโ๐โ๐ญโ๐กโ๐จโ๐โ=’๐โ๐โ๐ขโ๐ฅโ๐ฅโ’ ou ๐ฆโ๐โ๐ญโ๐กโ๐จโ๐โ=’๐ฉโ๐โ๐โ’ , ou avec la valeur existante suivante si ๐ฆโ๐โ๐ญโ๐กโ๐จโ๐โ=’๐โ๐โ๐โ๐คโ๐โ๐ขโ๐ฅโ๐ฅโ’ ou ๐ฆโ๐โ๐ญโ๐กโ๐จโ๐โ=’๐โ๐โ๐โ๐คโ๐โ๐ขโ๐ฅโ๐ฅโ’ .
s = pd.Series([np.nan, 1, np.nan, 2, np.nan]) print(s) # 0 NaN # 1 1.0 # 2 NaN # 3 2.0 # 4 NaN # dtype: float64 print(s.interpolate('ffill')) # 0 NaN # 1 1.0 # 2 1.0 # 3 2.0 # 4 2.0 # dtype: float64 print(s.interpolate('bfill')) # 0 1.0 # 1 1.0 # 2 2.0 # 3 2.0 # 4 NaN # dtype: float64
Le ๐ฅโ๐ขโ๐ฆโ๐ขโ๐ญโ_๐โ๐ขโ๐ซโ๐โ๐โ๐ญโ๐ขโ๐จโ๐งโ doit รชtre dรฉfini sur ยซ ๐โ๐จโ๐ซโ๐ฐโ๐โ๐ซโ๐โ ยป si ๐ฆโ๐โ๐ญโ๐กโ๐จโ๐โ est dรฉfini sur ยซ ๐โ๐โ๐ขโ๐ฅโ๐ฅโ ยป ou ‘๐ฉโ๐โ๐โ’ et ร ‘๐โ๐โ๐โ๐คโ๐ฐโ๐โ๐ซโ๐โ’ si ๐ฆโ๐โ๐ญโ๐กโ๐จโ๐โ est dรฉfini sur ‘๐โ๐โ๐ขโ๐ฅโ๐ฅโ’ ou ‘๐โ๐โ๐โ๐คโ๐โ๐ขโ๐ฅโ๐ฅโ’ .
# s.interpolate('ffill', limit_direction='both') # ValueError: `limit_direction` must be 'forward' for method `ffill` # s.interpolate('bfill', limit_direction='both') # ValueError: `limit_direction` must be 'backward' for method `bfill`
Vous pouvez faire la mรชme chose avec la mรฉthode ๐โ๐ขโ๐ฅโ๐ฅโ๐งโ๐โ() avec l’argument ๐ฆโ๐โ๐ญโ๐กโ๐จโ๐โ .
print(s.fillna(method='ffill')) # 0 NaN # 1 1.0 # 2 1.0 # 3 2.0 # 4 2.0 # dtype: float64 print(s.fillna(method='bfill')) # 0 1.0 # 1 1.0 # 2 2.0 # 3 2.0 # 4 NaN # dtype: float64
Spline d’interpolation : ๐ฌ๐จ๐ฎ๐ฌ๐ฌ๐ข๐๐ง ๐๐ฌ๐ญ ๐ฉ๐๐ซ๐ญ๐๐ง
Si ๐ฆโ๐โ๐ญโ๐กโ๐จโ๐โ=’๐ฌโ๐ฉโ๐ฅโ๐ขโ๐งโ๐โ’ , l’interpolation spline est effectuรฉe. Vous devez prรฉciser l’argument ๐จโ๐ซโ๐โ๐โ๐ซโ .
s = pd.Series([0, 10, np.nan, np.nan, 4, np.nan], index=[0, 2, 5, 6, 8, 12]) print(s) # 0 0.0 # 2 10.0 # 5 NaN # 6 NaN # 8 4.0 # 12 NaN # dtype: float64 print(s.interpolate('spline', order=2)) # 0 0.00 # 2 10.00 # 5 13.75 # 6 12.00 # 8 4.00 # 12 -30.00 # dtype: float64
L’interpolation spline dรฉpend toujours de l’index, donc toute modification de l’index modifiera en consรฉquence les rรฉsultats.
s.index = range(6) print(s) # 0 0.0 # 1 10.0 # 2 NaN # 3 NaN # 4 4.0 # 5 NaN # dtype: float64 print(s.interpolate('spline', order=2)) # 0 0.0 # 1 10.0 # 2 14.0 # 3 12.0 # 4 4.0 # 5 -10.0 # dtype: float64
Par consรฉquent, l’interpolation spline nรฉcessite que l’index soit numรฉrique. S’il s’agit de chaรฎnes, une erreur est gรฉnรฉrรฉe.
s.index = list('abcdef') print(s) # a 0.0 # b 10.0 # c NaN # d NaN # e 4.0 # f NaN # dtype: float64 # print(s.interpolate('spline', order=2)) # ValueError: Index column must be numeric or datetime type when using spline method other than linear. # Try setting a numeric or datetime index column before interpolating.
Autres
Il existe d’autres mรฉthodes d’interpolation qui peuvent รชtre spรฉcifiques pour l’ argument , ‘๐ณโ๐โ๐ซโ๐จโ’ , โโโโโโโโโโโโโ’๐ฌโ๐ฅโ๐ขโ๐งโ๐โ๐โ๐ซโ’ , ‘ ๐ซโ๐โ๐ญโ๐ขโ๐ ‘, ‘ ๐๐ฎ๐ญ๐ซ๐จ๐ข๐ฌ๐ฌ๐ข ‘ , ‘๐ฉ๐จ๐ฅโ๐ฒโ๐งโ๐จโ๐ฆโ๐ขโ๐โ๐ฅโ’ , ‘๐ฉ๐ขโ๐โ๐โ๐โ๐ฐโ๐ขโ๐ฌโ๐โ_๐ฉโ๐จโ๐ฅโ๐ฒโ๐งโ๐จโ๐ฆโ๐ขโ๐โ๐ฅโ’ , ‘๐๐ซโ๐จโ๐ฆโ_๐โ๐โ๐ซโ๐ขโ๐ฏโ๐โ๐ญโ๐ขโ๐ฏโ๐โ๐ฌ’ , ‘๐๐ฎ๐ญ๐ข๐ฆ๐๐ง๐ญ’ , ‘๐๐ฎ๐ญ’ .
Comme mentionnรฉ dans la documentation officielle, ce sont des wrappers pour les fonctions SciPy, y compris l’interpolation spline ( ‘๐ฌโ๐ฉโ๐ฅโ๐ขโ๐งโ๐โ’ ) mentionnรฉe ci-dessus.
- pandas.DataFrame.interpolate โ documentation de pandas 2.0.3
- Interpolation (scipy.interpolate) โ Manuel SciPy v1.11.1
Dans toutes ces mรฉthodes, l’index doit รชtre numรฉrique, tout comme dans l’interpolation spline.
Pour les donnรฉes de sรฉries chronologiques
๐ฆโ๐โ๐ญโ๐กโ๐จโ๐โ=’๐ญโ๐ขโ๐ฆโ๐โ’ est fourni pour les donnรฉes de sรฉries chronologiques. Dans le cas de ๐ฆโ๐โ๐ญโ๐กโ๐จโ๐โ=’๐ญโ๐ขโ๐ฆโ๐โ’ , l’interpolation linรฉaire est effectuรฉe en fonction de la date et de l’heure de la colonne d’index.
df_nan = pd.DataFrame({'value': [1, np.nan, np.nan, np.nan, 31]}, index=pd.to_datetime(['2018-01-01', '2018-01-02', '2018-01-15', '2018-01-20', '2018-01-31'])) print(df_nan) # value # 2018-01-01 1.0 # 2018-01-02 NaN # 2018-01-15 NaN # 2018-01-20 NaN # 2018-01-31 31.0 print(df_nan.interpolate()) # value # 2018-01-01 1.0 # 2018-01-02 8.5 # 2018-01-15 16.0 # 2018-01-20 23.5 # 2018-01-31 31.0 print(df_nan.interpolate('time')) # value # 2018-01-01 1.0 # 2018-01-02 2.0 # 2018-01-15 15.0 # 2018-01-20 20.0 # 2018-01-31 31.0
Dans le cas oรน le type de donnรฉes ( ๐โ๐ญโ๐ฒโ๐ฉโ๐โ ) est ๐จโ๐โ๐ฃโ๐โ๐โ๐ญโ
Par exemple, le type de donnรฉes ( ๐โ๐ญโ๐ฒโ๐ฉโ๐โ ) d’une colonne contenant un รฉlรฉment de chaรฎne est ๐จโ๐โ๐ฃโ๐โ๐โ๐ญโ .
s_object = pd.Series(['A', np.nan, 'C']) print(s_object) # 0 A # 1 NaN # 2 C # dtype: object
La colonne ๐จโ๐โ๐ฃโ๐โ๐โ๐ญโ n’est pas interpolรฉe par ๐ฆโ๐โ๐ญโ๐กโ๐จโ๐โ=’๐ฅโ๐ขโ๐งโ๐โ๐โ๐ซโ’ (par dรฉfaut) ou d’autres mรฉthodes. Il peut รชtre rempli par des mรฉthodes telles que ๐โ๐โ๐ขโ๐ฅโ๐ฅโ , ๐ฉโ๐โ๐โ , ๐โ๐โ๐ขโ๐ฅโ๐ฅโ et ๐โ๐โ๐โ๐คโ๐โ๐ขโ๐ฅโ๐ฅโ , qui utilise les valeurs existantes.
print(s_object.interpolate()) # 0 A # 1 NaN # 2 C # dtype: object print(s_object.interpolate('ffill')) # 0 A # 1 A # 2 C # dtype: object
Il en va de mรชme si l’รฉlรฉment est un nombre mais que le type de donnรฉes est ๐จโ๐โ๐ฃโ๐โ๐โ๐ญโ .
s_object_num = pd.Series([0, np.nan, 2], dtype=object) print(s_object_num) # 0 0 # 1 NaN # 2 2 # dtype: object print(s_object_num.interpolate()) # 0 0 # 1 NaN # 2 2 # dtype: object print(s_object_num.interpolate('ffill')) # 0 0 # 1 0 # 2 2 # dtype: int64
Si vous le convertissez en ๐โ๐ฅโ๐จโ๐โ๐ญโ avec ๐โ๐ฌโ๐ญโ๐ฒโ๐ฉโ๐โ() , vous pouvez effectuer une interpolation. Notez qu’il ne peut pas รชtre converti en ๐ขโ๐งโ๐ญโ s’il contient N๐โN .
print(s_object_num.astype(float).interpolate()) # 0 0.0 # 1 1.0 # 2 2.0 # dtype: float64 # print(s_object_num.astype(int)) # ValueError: cannot convert float NaN to integer
