En R, vous pouvez calculer une moyenne glissante avec une fenêtre spécifiée qui peut se décaler d'une quantité spécifiée à chaque fois.
Cependant, peut-être que je ne l'ai simplement trouvé nulle part, mais il ne semble pas que vous puissiez le faire dans pandas ou une autre bibliothèque Python?
Est-ce que quelqu'un connaît un moyen de contourner cela? Je vais vous donner un exemple de ce que je veux dire:
Ici, nous avons des données bihebdomadaires, et je calcule les deux mois moyenne mobile qui se décale d'un mois, soit 2 lignes.
Donc, dans RI ferait quelque chose comme: two_month__movavg = rollapply (mydata, 4, mean, by = 2, na.pad = FALSE)
N'y a-t-il pas d'équivalent en Python?
EDIT1:
DATE A DEMAND ... AA DEMAND A Price 0 2006/01/01 00:30:00 8013.27833 ... 5657.67500 20.03 1 2006/01/01 01:00:00 7726.89167 ... 5460.39500 18.66 2 2006/01/01 01:30:00 7372.85833 ... 5766.02500 20.38 3 2006/01/01 02:00:00 7071.83333 ... 5503.25167 18.59 4 2006/01/01 02:30:00 6865.44000 ... 5214.01500 17.53
3 Réponses :
Maintenant, c'est un peu exagéré pour un tableau 1D de données, mais vous pouvez le simplifier et extraire ce dont vous avez besoin. Puisque les pandas peuvent compter sur numpy, vous voudrez peut-être vérifier comment leur fonction de roulement / strided est implémentée. Résultats pour 20 numéros séquentiels. Une fenêtre de 7 jours, marchant / glissant de 2
nans = np.full_like(z, np.nan, dtype='float') # z is the 20 number sequence means = np.mean(s, axis=1) # results from the strided mean # assign the means to the output array skipping the first and last 3 and striding by 2 nans[3:-3:2] = means nans # array([nan, nan, nan, 3., nan, 5., nan, 7., nan, 9., nan, 11., nan, 13., nan, 15., nan, nan, nan, nan])
Voici le code que j'utilise sans la majeure partie de la documentation. Il est dérivé de nombreuses implémentations de fonction strided dans numpy que l'on peut trouver sur ce site. Il y a des variantes et des incarnations, c'est juste une autre.
def stride(a, win=(3, 3), stepby=(1, 1)): """Provide a 2D sliding/moving view of an array. There is no edge correction for outputs. Use the `pad_` function first.""" err = """Array shape, window and/or step size error. Use win=(3,) with stepby=(1,) for 1D array or win=(3,3) with stepby=(1,1) for 2D array or win=(1,3,3) with stepby=(1,1,1) for 3D ---- a.ndim != len(win) != len(stepby) ---- """ from numpy.lib.stride_tricks import as_strided a_ndim = a.ndim if isinstance(win, int): win = (win,) * a_ndim if isinstance(stepby, int): stepby = (stepby,) * a_ndim assert (a_ndim == len(win)) and (len(win) == len(stepby)), err shp = np.array(a.shape) # array shape (r, c) or (d, r, c) win_shp = np.array(win) # window (3, 3) or (1, 3, 3) ss = np.array(stepby) # step by (1, 1) or (1, 1, 1) newshape = tuple(((shp - win_shp) // ss) + 1) + tuple(win_shp) newstrides = tuple(np.array(a.strides) * ss) + a.strides a_s = as_strided(a, shape=newshape, strides=newstrides, subok=True).squeeze() return a_s
J'ai omis de souligner que vous pouvez créer une sortie que vous pourriez ajouter en tant que colonne aux pandas. Revenons aux définitions originales utilisées ci-dessus
z = np.arange(20) z #array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]) s = stride(z, (7,), (2,)) np.mean(s, axis=1) # array([ 3., 5., 7., 9., 11., 13., 15.])
Vous pouvez utiliser à nouveau le roulement, il suffit juste de travailler un peu avec vous attribuez un index
Ici by = 2
by = 2 df.loc[df.index[np.arange(len(df))%by==1],'New']=df.Price.rolling(window=4).mean() df Price New 0 63 NaN 1 92 NaN 2 92 NaN 3 5 63.00 4 90 NaN 5 3 47.50 6 81 NaN 7 98 68.00 8 100 NaN 9 58 84.25 10 38 NaN 11 15 52.75 12 75 NaN 13 19 36.75
Pouvez-vous fournir une explication à ce sujet? df.loc [df.index [np.arange (len (df))% by == 1], 'Nouveau'
@newtoR c'est pour obtenir le mod de la taille des fenêtres, donc par exemple, si nous avons 6 lignes, 0,1,2,3,4,5 sera 0,1,0,1,0,1 et nous coupons le mod égal à 1, puis nous coupons à partir de l'index d'origine de df, puis nous attribuons la valeur, puisque les pandas sont sensibles à l'index, l'index non mentionné à gauche sera renvoyé comme NaN
D'accord, et si vous changez votre by = 2
en by = 3
, votre moyenne mobile sera mise à jour?
@newtoR si vous augmentez de == 3, je pense qu'il renverra le même résultat lorsque vous entrez par = 3 dans votre rollapply dans R
Ok c'est super
Si la taille des données n'est pas trop grande, voici un moyen simple:
by = 2 win = 4 start = 3 ## it is the index of your 1st valid value. df.rolling(win).mean()[start::by] ## calculate all, choose what you need.
Il peut être plus sûr de couper avec iloc, ie. df.rolling (win) .mean (). iloc [start :: by]
au cas où l'index DF ne serait pas une séquence numérique commençant à 0.
Pouvez-vous nous montrer la trame de données plutôt qu'une image?
Oui, il s'agit donc de données d'une demi-heure, et je veux que la moyenne sur un an (17520) se déplace chaque semaine (de 336). (J'ai édité le message pour le montrer)
L'exemple mensuel ci-dessus était juste pour illustrer mon problème un peu plus simple