Parfois, j'ai envie de rogner et de prendre une moyenne mobile. Je souhaite également prendre une moyenne pondérée car je souhaite augmenter l'influence de la dernière valeur numérique. Fondamentalement, la tendance est la même, mais je voudrais prendre une moyenne mobile sans référence aux données de la série chronologique lorsque la valeur numérique augmente de manière ponctuelle à l'occasion ou lorsque la valeur numérique augmente à la hâte. Vous pouvez le penser. Eh non? J'écris toujours. J'ai eu un peu de mal à rouler (). Postuler, alors je veux l'écrire.
Une méthode d'agencement des valeurs numériques du groupe de données à faire la moyenne par ordre de taille et à l'exclusion de N% d'un côté ou des deux côtés pour prendre la moyenne.
On suppose qu'il y a 10 données ci-dessous.
Si vous prenez la moyenne normalement,
La moyenne de la taille (taille) est de supprimer et la moyenne comme celle-ci. S'il s'agit d'une moyenne mobile, c'est une image qui rogne et fait la moyenne de la valeur numérique dans la taille de la fenêtre. Le mérite est que les valeurs aberrantes peuvent être éliminées. Il est possible d'empêcher la moyenne d'être tirée vers la valeur aberrante.
Les explications étant écrites à divers endroits, les détails sont omis. Pour pondérer les nombres et prendre la moyenne. Les moyennes mobiles pondérées sont souvent pondérées de sorte que l'influence de la dernière valeur numérique soit grande.
Puisque nous voulons prendre la moyenne mobile pondérée ajustée cette fois, nous prenons la moyenne mobile pondérée après ajustement avec la valeur numérique dans la taille de la fenêtre de la moyenne mobile.
import.py
import numpy as np
import scipy as sp
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import datetime as dt
from dateutil.relativedelta import relativedelta
sns.set()
Créer des données en fonction de la transition du nombre d'utilisateurs actifs des applications pour smartphone
make_data.py
#Courbe de décroissance
def exp_func(x, a, b):
return b*(x**a)
x=np.linspace(1,36,36)
data=exp_func(x, -0.5, 100000)
#Trame de données
df=pd.DataFrame({'x':x,'y':data})
df=df.astype(int)
#Créer une colonne de mois, car il s'agit d'une hypothèse de données de séries chronologiques
init_mon=dt.datetime(2017,df['x'].values[0],1)
months=[init_mon]
for mon in range(1,len(df)):
months.append(init_mon + relativedelta(months=mon))
df['month']=months
df.index=months
display(df.head())
# plot
fig=plt.figure(figsize=(12,6))
ax=plt.subplot(1,1,1)
df.plot.bar('month','y',ax=ax)
plt.show()
Il semble que le nombre d'utilisateurs actifs augmentera temporairement considérablement en fonction de la campagne ou de l'événement de l'application smartphone, changeons donc la valeur numérique des données en supposant une telle situation.
change_data.py
df2=df.copy()
df2.loc[(df2.index.month==1)&(df2.index.year>=2018), 'y']=df2['y']*1.6
df2.loc[(df2.index.month==2)&(df2.index.year>=2018), 'y']=df2['y']*1.4
df2.loc[(df2.index.month==3)&(df2.index.year>=2018), 'y']=df2['y']*1.2
fig=plt.figure(figsize=(12,6))
ax=plt.subplot(1,1,1)
df2.plot.bar('month','y',ax=ax)
plt.show()
Les données qui semblent avoir augmenté le nombre d'utilisateurs actifs dans des campagnes telles que le 1er anniversaire sont terminées.
Cette fois, construisons un code avec la politique d'utiliser la moyenne mobile pondérée par ajustement comme valeur prédite. La valeur prédite de la valeur numérique après 3 mois est utilisée comme valeur de la moyenne mobile pondérée ajustée. (Exemple: la valeur numérique de 2018-08 est prédite en prenant la moyenne mobile pondérée coupée à partir de 2018-05)
Tout d'abord, couper la fonction de moyenne mobile simple
sma.py
def sma(roll_list):
# roll_Supprimer si Nan est dans la liste
roll_list=roll_list[~np.isnan(roll_list)]
# roll_Organiser la liste par ordre croissant
sorted_roll_list=sorted(roll_list)
#Rouleau disposé par ordre croissant_Définir la moitié de la longueur de la liste
harf_span=round(len(sorted_roll_list)/2)
if harf_span > 0:
# roll_Obtenez les nombres sous la médiane de la liste et prenez la moyenne
harf_index=np.where(roll_list < sorted_roll_list[harf_span])
roll_list_harf=roll_list[harf_index]
sma = np.sum(roll_list_harf) / len(roll_list_harf)
else:
# roll_La longueur de la liste étant inférieure ou égale à 1, la valeur médiane ne peut pas être obtenue.
# roll_Utilisez la valeur de list telle quelle
roll_list_harf=roll_list[0]
sma = roll_list_harf
return sma
Ensuite, la fonction moyenne mobile pondérée ajustée
sma.py
def wma(roll_list):
# roll_Supprimer si Nan est dans la liste
roll_list=roll_list[~np.isnan(roll_list)]
# roll_Organiser la liste par ordre croissant
sorted_roll_list=sorted(roll_list)
#Rouleau disposé par ordre croissant_Définir la moitié de la longueur de la liste
harf_span=round(len(sorted_roll_list)/2)
# roll_Obtenez des nombres inférieurs à la médiane de la liste
harf_index=np.where(roll_list < sorted_roll_list[harf_span])
roll_list_harf=roll_list[harf_index]
# roll_Calculez le poids des nombres sous la valeur médiane de la liste et prenez la moyenne mobile pondérée.
weight = np.arange(len(roll_list_harf)) + 1
wma = np.sum(weight * roll_list_harf) / weight.sum()
return wma
Ensuite, en utilisant la fonction ci-dessus, la taille de la fenêtre est de 6 mois, et les parties autres que les 3 mois avec les valeurs numériques les plus faibles sont coupées et la moyenne mobile pondérée est prise. Vous pouvez facilement obtenir une moyenne mobile en utilisant le roulement des pandas, et vous pouvez appliquer votre propre fonction en utilisant apply. À propos, la liste_roulés qui apparaît dans les fonctions sma et wma ci-dessus fait référence à un tableau de données acquises dans la taille de la fenêtre (période) spécifiée par le roulement des pandas. Il semble que le tableau de données puisse être mis dans la fonction en tant que type Series si rien n'est fait. Puisque les fonctions sma et wma ont été construites en supposant ndarray, une erreur se produira s'il s'agit d'un type Series. Afin d'éviter une erreur, raw = True est mis dans l'argument de apply pour en faire un type ndarray.
moving_mean.py
#Créer une colonne de nombres il y a 3 mois
df2['y_shift'] = df2['y'].shift(3)
#SMA de la valeur il y a 3 mois
df2['y_sma'] = df2['y_shift'].rolling(6,min_periods=1).apply(sma, raw = True)
#WMA d'il y a 3 mois
df2['y_wma'] = df2['y_shift'].rolling(6,min_periods=1).apply(wma, raw = True)
#WMA ne peut pas être calculé NULL est défini sur la valeur SMA
df2.loc[pd.isna(df2['y_wma']), 'y_wma']=df2['y_sma']
display(df2.head(10))
# plot
fig=plt.figure(figsize=(12,6))
ax=plt.subplot(1,1,1)
df2.plot.bar('month','y',ax=ax,color='b',alpha=0.9)
df2.plot.bar('month','y_wma',ax=ax,color='r',alpha=0.6)
plt.show()
Cadre de données La ligne jaune est la valeur réelle, la ligne bleu clair est la valeur des 3 derniers mois et la ligne verte est la valeur des 3 mois les plus bas des 6 derniers mois. Le bleu dans le graphique est la valeur réelle et le rouge est la valeur obtenue en prenant la moyenne mobile pondérée coupée des données il y a jusqu'à 3 mois (valeur prédite).
Par exemple, faites attention à juin 2018.
·Valeur actuelle:
La réduction et la prise d'une moyenne mobile pondérée élimineront l'impact de la forte hausse de janvier 2018 sur les calculs ultérieurs.
Je pense que c'est utile lorsque vous voulez prendre une moyenne mobile qui élimine l'influence des valeurs anormales dans les données de séries chronologiques qui contiennent souvent des valeurs anormales.
Recommended Posts