Je vous suggère de regarder le code source afin d'obtenir dans le nitty gritty de ce roulement n'. En particulier, je vous suggère d'avoir un coup d'oeil à l' rolling
fonctions generic.py et window.py. De là, vous pouvez jeter un oeil à l' Window
de la classe qui est utilisée si vous spécifiez un type de fenêtre ou de la valeur par défaut Rolling
classe. Le dernier hérite _Rolling_and_Expanding
et, finalement, _Rolling
et _Window
.
Cela dit, je vais donner à mes deux cents: les Pandas de " l'ensemble du mécanisme de rotation, s'appuie sur la fonction numpy apply_along_axis
. En particulier, il est utilisé ici dans les pandas. Il est utilisé en conjonction avec l' windows.pyx
cython module. En va de votre série, sort de l'ensemble roulant fenêtre. Pour les fonctions d'agrégation, il les gère pour vous de manière efficace, mais pour ceux personnalisées (à l'aide d' apply()
), il utilise un roll_generic()
en windows.pyx
.
Les rolling fonction dans les pandas fonctionne sur les pandas trame de données des colonnes de façon indépendante. Ce n'est pas un python itérateur, et n'est pas chargé, de sens, rien n'est calculé jusqu'à ce que vous appliquer une fonction d'agrégation à elle. Les fonctions qui s'appliquent en fait l'roulant fenêtre de données ne sont pas utilisés jusqu'à ce que juste avant une agrégation est faite.
Une source de confusion et peut-être que vous êtes la pensée de l'objet roulant comme un dataframe. (Vous avez nommé les rolling objet df
dans votre dernier extrait de code). Il est vraiment pas. C'est un objet qui peut produire des dataframes en appliquant des agrégations sur la fenêtre de la logique qu'elle abrite.
Le lambda que vous fournissez est appliquée pour chaque cellule de votre nouveau dataframe. Il faut une fenêtre vers l'arrière (le long de chaque colonne) dans votre ancien dataframe, et il agrège à une seule cellule dans la nouvelle dataframe. L'agrégation peut être des choses comme sum
, mean
, quelque chose de personnalisé que vous avez fait, etc., sur certains la taille de la fenêtre, dire 3. Voici quelques exemples:
a = np.arange(5)
df = pd.DataFrame(a, columns=['a'])
df.rolling(3).mean().dropna()
... qui peut aussi être fait par:
df.rolling(3).apply(np.mean).dropna()
... et produit:
a
2 3.0
3 6.0
4 9.0
(La première colonne est la valeur de l'indice et peut être ignoré ici, et pour les exemples).
Remarquez comment nous avons fourni un existant numpy la fonction d'agrégation. C'est l'idée. Nous sommes censés être en mesure de fournir tout ce qu'on veut tant qu'il se conforme à ce que des fonctions d'agrégation faire, c'est à dire, prendre un vecteur de valeurs et de produire une seule valeur de celui-ci. En voici une autre où l'on créer une fonction d'agrégation, dans ce cas, la norme L2 de la fenêtre:
df.rolling(3).apply(lambda x: np.sqrt(x.dot(x))).dropna()
si vous n'êtes pas familier avec les lambda fonctions c'est la même chose que:
def euclidean_dist(x):
return np.sqrt(x.dot(x))
df.rolling(3).apply(euclidean_dist).dropna()
... rendement:
a
2 2.236068
3 3.741657
4 5.385165
Juste pour être sûr, nous pouvons vérifier manuellement que np.sqrt(0**2 + 1**2 + 2**2)
est en effet 2.236068
.
[Vos originaux de modifier, dans le] dernier extrait de code, votre code est probablement à défaut tôt que prévu. Il est en panne avant l'invocation de l' df.apply(...)
Vous essayez d'ajouter un roulement objet nommé df
le nombre 2 avant de passer à l' df.apply(...)
. Les rolling objet n'est pas quelque chose que vous faites des opérations. La fonction d'agrégation que vous avez fourni n'est pas conforme à une fonction d'agrégation en général. L' a
une liste avec les valeurs d'une fenêtre, b
serait une constante paramètre supplémentaire que vous transmettez. Il peut être un roulement objet si vous voulez, mais il ne serait généralement pas être quelque chose que vous aimeriez faire. Pour rendre cela plus clair, ici est quelque chose qui est similaire à ce que vous faisiez dans votre edition originale mais qui fonctionne:
a = np.arange(8)
df = pd.DataFrame(a, columns=['a'])
n = 4
rol = df.rolling(n)
def prod(window_list, constant_rol):
return window_list.dot(constant_rol.sum().dropna().head(n))
rol.apply(prod, args=(rol,)).dropna()
# [92.0, 140.0, 188.0, 236.0, 284.0]
C'est un exemple artificiel, mais je vais les montrer à faire le point que vous pouvez passer dans tout ce que vous voulez comme une constante, même les rolling objet que vous êtes en utilisant lui-même. La partie dynamique est le premier argument a
dans votre cas ou window_list
dans mon cas. Tous les windows, sous la forme de listes individuelles, sont passés dans cette fonction, un par un.
Basé sur votre suivi des commentaires, cela pourrait être ce que vous cherchez:
import numpy as np
import pandas as pd
n = 3
a = np.arange(5)
df = pd.DataFrame(a, columns=['a'])
def keep(window, windows):
windows.append(window.copy())
return window[-1]
windows = list()
df['a'].rolling(n).apply(keep, args=(windows,))
df = df.tail(n)
df['a_window'] = windows
qui ajoute des matrices/vecteurs pour chaque bloc de roulement produisant ainsi:
a a_window
2 2 [0.0, 1.0, 2.0]
3 3 [1.0, 2.0, 3.0]
4 4 [2.0, 3.0, 4.0]
Notez que cela ne fonctionne que si vous le faites sur une colonne à la fois. Si vous voulez faire un peu de maths sur la fenêtre, avant de les stocker à l'écart en keep
c'est très bien aussi.
Cela dit, sans plus de commentaires sur exactement ce que vous essayez d'atteindre, il est difficile de construire un exemple qui répond à vos besoins.
Si votre but ultime est de créer un dataframe de retard variables, alors j'irais pour l'utilisation réelle des colonnes à l'aide de shift()
:
import numpy as np
import pandas as pd
a = np.arange(5)
df = pd.DataFrame(a, columns=['a'])
for i in range(1,3):
df['a-%s' % i] = df['a'].shift(i)
df.dropna()
... donnant:
a a-1 a-2
2 2 1.0 0.0
3 3 2.0 1.0
4 4 3.0 2.0
(Il pourrait y avoir une plus belle façon de le faire, mais il fait le travail.)
Concernant votre variable b
lors de votre premier extrait de code, n'oubliez pas DataFrames dans les pandas ne sont généralement pas traités comme des tenseurs de l'arbitraire dimensions/objet. Vous pouvez probablement des trucs ce que vous voulez, mais en fin de compte les chaînes, le temps des objets, des entiers et des flottants est ce qui est prévu. Qui pourraient être les raisons les concepteurs de pandas n'ai pas pris la peine avec permettant de rouler agrégation de non-valeurs scalaires. Il n'a même pas sembler comme une simple chaîne de caractères est autorisé en sortie de la fonction d'agrégation.
De toute façon, j'espère que cela répond à certaines de vos questions. Si non, laissez-moi savoir, et je vais essayer de vous aider dans les commentaires, ou une mise à jour.
Note finale sur l' _create_blocks()
fonction des objets roulants.
L' _create_blocks()
fonction gère la réindexation et binning lorsque vous utilisez l' freq
argument de l' rolling
.
Si vous utilisez freq avec, disons, des semaines, tels que freq=W
:
import pandas as pd
a = np.arange(50)
df = pd.DataFrame(a, columns=['a'])
df.index = pd.to_datetime('2016-01-01') + pd.to_timedelta(df['a'], 'D')
blocks, obj, index = df.rolling(4, freq='W')._create_blocks(how=None)
for b in blocks:
print(b)
... alors nous obtenons la mise à la poubelle (pas de roulement) de données d'origine à la semaine:
a
a
2016-01-03 2.0
2016-01-10 9.0
2016-01-17 16.0
2016-01-24 23.0
2016-01-31 30.0
2016-02-07 37.0
2016-02-14 44.0
2016-02-21 NaN
Notez que ce n'est pas la sortie de l'ensemble roulant. C'est tout simplement la nouvelle blocs, il fonctionne sur. Après cette. Nous faisons une agrégation comme sum
et obtenez:
a
a
2016-01-03 NaN
2016-01-10 NaN
2016-01-17 NaN
2016-01-24 50.0
2016-01-31 78.0
2016-02-07 106.0
2016-02-14 134.0
2016-02-21 NaN
... qui vérifie avec un test de sommation: 50 = 2 + 9 + 16 + 23.
Si vous n'utilisez pas freq
comme argument, elle renvoie simplement les données d'origine de la structure:
import pandas as pd
a = np.arange(5)
df = pd.DataFrame(a, columns=['a'])
blocks, obj, index = df.rolling(3)._create_blocks(how=None)
for b in blocks:
print(b)
... qui produit ...
a
a
2016-01-01 0
2016-01-02 1
2016-01-03 2
2016-01-04 3
2016-01-05 4
... et est utilisé pour le déploiement de la fenêtre de l'agrégation.