web-dev-qa-db-fra.com

python pandas: comment calculer la dérivée / le gradient

Étant donné que j'ai les deux vecteurs suivants:

In [99]: time_index
Out[99]: 
[1484942413,
 1484942712,
 1484943012,
 1484943312,
 1484943612,
 1484943912,
 1484944212,
 1484944511,
 1484944811,
 1484945110]

In [100]: bytes_in
Out[100]: 
[1293981210388,
 1293981379944,
 1293981549960,
 1293981720866,
 1293981890968,
 1293982062261,
 1293982227492,
 1293982391244,
 1293982556526,
 1293982722320]

bytes_in est un compteur incrémentiel uniquement et time_index est une liste de horodatages unix (Epoch).

Objectif: Ce que je voudrais calculer, c'est le débit binaire.

Cela signifie que je vais construire un bloc de données comme

In [101]: timeline = pandas.to_datetime(time_index, unit="s")

In [102]: recv = pandas.Series(bytes_in, timeline).resample("300S").mean().ffill().apply(lambda i: i*8)

In [103]: recv
Out[103]: 
2017-01-20 20:00:00    10351849683104
2017-01-20 20:05:00    10351851039552
2017-01-20 20:10:00    10351852399680
2017-01-20 20:15:00    10351853766928
2017-01-20 20:20:00    10351855127744
2017-01-20 20:25:00    10351856498088
2017-01-20 20:30:00    10351857819936
2017-01-20 20:35:00    10351859129952
2017-01-20 20:40:00    10351860452208
2017-01-20 20:45:00    10351861778560
Freq: 300S, dtype: int64

Question: Maintenant, ce qui est étrange, le calcul manuel du gradient me donne:

In [104]: (bytes_in[1]-bytes_in[0])*8/300
Out[104]: 4521.493333333333

qui est la bonne valeur ..

tout en calculant le gradient avec pandas me donne

In [124]: recv.diff()
Out[124]: 
2017-01-20 20:00:00          NaN
2017-01-20 20:05:00    1356448.0
2017-01-20 20:10:00    1360128.0
2017-01-20 20:15:00    1367248.0
2017-01-20 20:20:00    1360816.0
2017-01-20 20:25:00    1370344.0
2017-01-20 20:30:00    1321848.0
2017-01-20 20:35:00    1310016.0
2017-01-20 20:40:00    1322256.0
2017-01-20 20:45:00    1326352.0
Freq: 300S, dtype: float64

qui n'est pas la même que ci-dessus, 1356448.0 est différent de 4521.493333333333

Pourriez-vous s'il vous plaît éclairer ce que je fais mal?

12
onedreamcloser

pd.Series.diff() ne prend que les différences. Il ne se divise pas également par le delta de l'indice.

Cela vous donne la réponse

recv.diff() / recv.index.to_series().diff().dt.total_seconds()

2017-01-20 20:00:00            NaN
2017-01-20 20:05:00    4521.493333
2017-01-20 20:10:00    4533.760000
2017-01-20 20:15:00    4557.493333
2017-01-20 20:20:00    4536.053333
2017-01-20 20:25:00    4567.813333
2017-01-20 20:30:00    4406.160000
2017-01-20 20:35:00    4366.720000
2017-01-20 20:40:00    4407.520000
2017-01-20 20:45:00    4421.173333
Freq: 300S, dtype: float64

Vous pouvez également utiliser numpy.gradient en passant le bytes_in et le delta que vous attendez. Cela ne réduira pas la longueur d'un, mais fera des hypothèses sur les bords.

np.gradient(bytes_in, 300) * 8

array([ 4521.49333333,  4527.62666667,  4545.62666667,  4546.77333333,
        4551.93333333,  4486.98666667,  4386.44      ,  4387.12      ,
        4414.34666667,  4421.17333333])
15
piRSquared

Comme il n'y a pas de méthode derivative intégrée dans Pandas Series/DataFrame, vous pouvez utiliser https://github.com/scls19fr/pandas-helper-calc =.

Il fournira un nouvel accessoire appelé calc à Pandas Series et DataFrames pour calculer la dérivée numérique et l'intégrale.

Vous pourrez donc simplement faire

recv.calc.derivative()

Il utilise diff() sous le capot.

0
scls

Une explication naïve serait que diff soustrait littéralement les entrées suivantes tandis que np.gradient utilise un schéma de différence central.

0
Zitzero