4
votes

agrégation python de deux séries chronologiques

J'ai deux cadres de données de séries chronologiques pandas et je souhaite agréger les valeurs par rapport à une série chronologique en fonction des intervalles de l'autre. Laissez-moi vous montrer par l'exemple. La première série chronologique est la suivante:

     date        value
 0   2016-03-21  20
 1   2016-03-31   0
 2   2016-04-10  10
 3   2016-04-20   0
 4   2016-04-30  10

La seconde est une plage de dates avec des intervalles de 10 jours civils extraits de la série ci-dessus. J'ai écrit le code pour extraire ceci des données ci-dessus.

     date
 0   2016-03-21
 1   2016-03-31
 2   2016-04-10
 3   2016-04-20
 4   2016-04-30

Je veux écrire du code pour obtenir ce dataframe résultant:

        date    value
0 2016-03-21       10
1 2016-03-25       10
2 2016-04-10       10
3 2016-05-05       10


1 commentaires

@Vaishali Je pense que le problème est différent ...


3 Réponses :


5
votes

Vous pouvez regrouper les données dans df1 en fonction des bins des dates df2,

bins = pd.date_range(df2.date.min(), df2.date.max() + pd.DateOffset(10), freq = '10D')
labels = df2.date
df1.groupby(pd.cut(df1.date, bins = bins, right = False, labels = labels)).value.sum().reset_index()


    date        value
0   2016-03-21  20
1   2016-03-31  0
2   2016-04-10  10
3   2016-04-20  0
4   2016-04-30  10


4 commentaires

Question non triviale et excellente réponse. Allez les potes! Où est l'appréciation?


Celui-ci suffit 😊


Un de plus à la liste 😊


Excellente réponse! :)



4
votes

Numpy searchsorted

C'est la première chose à laquelle j'ai pensé mais ce n'était pas anodin à régler. La réponse de @ Vaishali est dans un esprit très similaire et plus simple. Mais je suis comme un chien avec un os et je ne peux pas le laisser partir tant que je ne l'ai pas compris.

Pour expliquer un peu. searchsorted passera par un tableau, dans ce cas les dates également espacées, et trouvera où dans un autre tableau ils seraient placés afin de maintenir le tri. Cela semble compliqué, mais si nous visualisons, nous pouvons voir ce qui se passe. J'utiliserai des lettres pour démontrer. Je vais choisir les lettres qui correspondent aux dates.

d = df.date.values
v = df.value.values

i = dates.searchsorted(d, side='right') - 1

pd.DataFrame(dict(
    date=dates, value=np.bincount(i, v).astype(v.dtype)
))

        date  value
0 2016-03-21     20
1 2016-03-31      0
2 2016-04-10     10
3 2016-04-20      0
4 2016-04-30     10

Notez que pour chaque lettre de x j'ai trouvé où se trouvait le backstop dans y

d = df.date.values
v = df.value.values

i = dates.searchsorted(d, side='right') - 1
a = np.zeros(len(dates), dtype=v.dtype)

np.add.at(a, i, v)

pd.DataFrame(dict(
    date=dates, value=a
))

        date  value
0 2016-03-21     20
1 2016-03-31      0
2 2016-04-10     10
3 2016-04-20      0
4 2016-04-30     10

Cela correspond à ce que je fais ci-dessous.

Configuration

df = pd.DataFrame(dict(
    date=pd.to_datetime(['2016-03-21', '2016-03-25', '2016-04-10', '2016-05-05']),
    value=[10, 10, 10, 10]
))

dates = pd.date_range(df.date.min(), df.date.max(), freq='10D')

Solution

#  i -> 0 0   2     4
#  x -> a b   d     g
#  y -> a   c d e f

Vous remarquerez que j'ai utilisé np.add.at pour additionner v code > aux bons endroits. J'aurais pu aussi le faire avec np.bincount . J'aime mieux l'approche ci-dessus car np.bincount convertit en float même si le v est de type int .

x = np.array([*'abdg'])
y = np.array([*'acdef'])

5 commentaires

Solution géniale! même si je ne l'ai pas encore entièrement compris. : D Merci.


Travailler sur l'explication


s'il vous plaît laissez-moi le faire moi-même au moins;)


C'est une explication rapide et sale. Laissez le travail et conduisez maintenant. Bonne chance.


Voyant cela maintenant, je n'ai jamais utilisé de recherche triée. Il y a tant à apprendre :)



3
votes

Ayez juste le temps d'ajouter ma solution, numpy diffusez

s1=df1.date.values
s2=df2.date.values
a=(np.abs(s1-s2[:,None])/np.timedelta64(60*60*24, 's')<10).dot(df1.value.values)
a
Out[183]: array([20, 10, 10,  0, 10], dtype=int64)

#df2['value']=a


0 commentaires