web-dev-qa-db-fra.com

Pandas rééchantillonner avec la date de début

Je voudrais rééchantillonner un pandas objet à l'aide d'une date (ou de mois) spécifique en tant que bord du premier bac. Par exemple, dans l'extrait suivant, je voudrais ma première valeur d'index à être 2020-02-29 Et je serais heureux de préciser start=2 ou alors start="2020-02-29".

>>> dates = pd.date_range("2020-01-29", "2021-07-04")
>>> s = pd.Series(range(len(dates)), index=dates)
>>> s.resample('4M').count()
2020-01-31      3
2020-05-31    121
2020-09-30    122
2021-01-31    123
2021-05-31    120
2021-09-30     34
Freq: 4M, dtype: int64

Jusqu'à présent, c'est le plus propre que je puisse proposer des utilisations pd.cut et groupby:

>>> rule = "4M"
>>> start = pd.Timestamp("2020-02-29") - pd.tseries.frequencies.to_offset(rule)
>>> end = s.index.max() + pd.tseries.frequencies.to_offset(rule)
>>> bins = pd.date_range(start, end, freq=rule)
>>> gb = s.groupby(pd.cut(s.index, bins)).count()
>>> gb.index = gb.index.categories.right
>>> gb
2020-02-29     32
2020-06-30    122
2020-10-31    123
2021-02-28    120
2021-06-30    122
2021-10-31      4
dtype: int64
19
jsignell

Ce n'est pas une réponse originale, mais combine plutôt les améliorations de @Alollz (commentaire) et @MHDmedf (réponse) en une seule réponse à la clarté car ils représentent des améliorations compatibles. Voir également ci-dessous pour une note de synchronisation.

rule = "4M"
start = pd.Timestamp("2020-02-29") - pd.tseries.frequencies.to_offset(rule)
end = s.index.max() + pd.tseries.frequencies.to_offset(rule)
bins = pd.date_range(start, end, freq=rule)
gb = pd.cut(s.index, bins, labels=bins[1:]).value_counts()

(La dernière ligne ci-dessus remplace les deux dernières lignes de la réponse dans l'OP. Les quatre premières lignes sont inchangées mais incluses ici pour plus de clarté.)

Résultats:

2020-02-29     32
2020-06-30    122
2020-10-31    123
2021-02-28    120
2021-06-30    122
2021-10-31      4

Vitesse/Timing: Le code dans l'OP prend une quantité de temps non triviale compte tenu de seulement 524 lignes (6 ms sur ma machine). À l'aide des données OP, ces deux améliorations se combinent pour environ une vitesse de 3x. Bien sûr, sur une série plus grande/Dataframe, les résultats de synchronisation peuvent différer substantiellement de ceux observés ici.

1
JohnE