Bien sûr, je pourrais l'écrire moi-même, mais avant de réinventer la roue, y a-t-il une fonction qui le fait déjà?
pandas.Series.dt.quarter
.
Bien sûr, je pourrais l'écrire moi-même, mais avant de réinventer la roue, y a-t-il une fonction qui le fait déjà?
pandas.Series.dt.quarter
.
Réponses:
Étant donné une instance x
de datetime.date , (x.month-1)//3
vous donnera le trimestre (0 pour le premier trimestre, 1 pour le deuxième trimestre, etc. - ajoutez 1 si vous devez compter à partir de 1 à la place ;-).
À l'origine, deux réponses, multipliées par vote positif et même acceptées à l'origine (toutes deux actuellement supprimées), étaient boguées - ne faisant pas -1
avant la division, et divisant par 4 au lieu de 3. Puisque .month
va de 1 à 12, il est facile de vérifier par vous-même quelle formule est droite:
for m in range(1, 13):
print m//4 + 1,
print
donne 1 1 1 2 2 2 2 3 3 3 3 4
- deux trimestres de quatre mois et un seul mois (eep).
for m in range(1, 13):
print (m-1)//3 + 1,
print
donne 1 1 1 2 2 2 3 3 3 4 4 4
- maintenant cela ne vous semble-t-il pas largement préférable? -)
Cela prouve que la question est bien justifiée, je pense ;-).
Je ne pense pas que le module datetime devrait nécessairement avoir toutes les fonctions de calendrier utiles possibles, mais je sais que je maintiens un datetools
module (bien testé ;-) pour l'utilisation de mes projets (et d'autres) au travail, qui a beaucoup peu fonctions pour effectuer tous ces calculs calendriers - certains sont complexes, d'autres simples, mais il n'y a aucune raison de faire le travail encore et encore (même un travail simple) ou de risquer des bogues dans de tels calculs ;-).
(m+2)//3
au lieu de(m-1)//3 + 1
SI vous utilisez déjà pandas
, c'est assez simple.
import datetime as dt
import pandas as pd
quarter = pd.Timestamp(dt.date(2016, 2, 29)).quarter
assert quarter == 1
Si vous avez une date
colonne dans un dataframe, vous pouvez facilement créer une nouvelle quarter
colonne:
df['quarter'] = df['date'].dt.quarter
pandas.Series.dt.quarter
est une solution idéale lorsque vous avez des valeurs datetime dans un objet Dataframe ou Series .
Je suggérerais une autre solution sans doute plus propre. Si X est une datetime.datetime.now()
instance, alors le quart est:
import math
Q=math.ceil(X.month/3.)
ceil doit être importé du module mathématique car il n'est pas accessible directement.
math.ceil(float(4)/3) = 2.0
pendantmath.ceil(4/3) = 1.0
.
après le 3. math.ceil(4/3.) = 2.0
Pour tous ceux qui essaient d'obtenir le trimestre de l' année fiscale , qui peut différer de l' année civile , j'ai écrit un module Python pour faire exactement cela.
L'installation est simple. Exécutez simplement:
$ pip install fiscalyear
Il n'y a pas de dépendances et fiscalyear
devrait fonctionner pour Python 2 et 3.
Il s'agit essentiellement d'un wrapper autour du module datetime intégré, donc toutes les datetime
commandes que vous connaissez déjà fonctionneront. Voici une démo:
>>> from fiscalyear import *
>>> a = FiscalDate.today()
>>> a
FiscalDate(2017, 5, 6)
>>> a.fiscal_year
2017
>>> a.quarter
3
>>> b = FiscalYear(2017)
>>> b.start
FiscalDateTime(2016, 10, 1, 0, 0)
>>> b.end
FiscalDateTime(2017, 9, 30, 23, 59, 59)
>>> b.q3
FiscalQuarter(2017, 3)
>>> b.q3.start
FiscalDateTime(2017, 4, 1, 0, 0)
>>> b.q3.end
FiscalDateTime(2017, 6, 30, 23, 59, 59)
fiscalyear
est hébergé sur GitHub et PyPI . La documentation peut être trouvée sur Lire les documents . Si vous recherchez des fonctionnalités qu'il n'a pas actuellement, faites le moi savoir!
Voici un exemple de fonction qui obtient un objet datetime.datetime et renvoie une chaîne unique pour chaque trimestre:
from datetime import datetime, timedelta
def get_quarter(d):
return "Q%d_%d" % (math.ceil(d.month/3), d.year)
d = datetime.now()
print(d.strftime("%Y-%m-%d"), get_q(d))
d2 = d - timedelta(90)
print(d2.strftime("%Y-%m-%d"), get_q(d2))
d3 = d - timedelta(180 + 365)
print(d3.strftime("%Y-%m-%d"), get_q(d3))
Et le résultat est:
2019-02-14 Q1_2019
2018-11-16 Q4_2018
2017-08-18 Q3_2017
Cette méthode fonctionne pour n'importe quel mappage:
month2quarter = {
1:1,2:1,3:1,
4:2,5:2,6:2,
7:3,8:3,9:3,
10:4,11:4,12:4,
}.get
Nous venons de générer une fonction int->int
month2quarter(9) # returns 3
Cette méthode est également infaillible
month2quarter(-1) # returns None
month2quarter('July') # returns None
Pour ceux qui recherchent des données trimestrielles de l'exercice, en utilisant des pandas,
import datetime
import pandas as pd
today_date = datetime.date.today()
quarter = pd.PeriodIndex(today_date, freq='Q-MAR').strftime('Q%q')
reference: index des périodes pandas
C'est une question ancienne mais qui mérite toujours d'être discutée.
Voici ma solution, en utilisant l'excellent module dateutil .
from dateutil import rrule,relativedelta
year = this_date.year
quarters = rrule.rrule(rrule.MONTHLY,
bymonth=(1,4,7,10),
bysetpos=-1,
dtstart=datetime.datetime(year,1,1),
count=8)
first_day = quarters.before(this_date)
last_day = (quarters.after(this_date)
-relativedelta.relativedelta(days=1)
Il en first_day
va de même pour le premier jour du trimestre et last_day
est le dernier jour du trimestre (calculé en trouvant le premier jour du trimestre suivant, moins un jour).
hmmm donc les calculs peuvent mal tourner, voici une meilleure version (juste pour le plaisir)
first, second, third, fourth=1,2,3,4# you can make strings if you wish :)
quarterMap = {}
quarterMap.update(dict(zip((1,2,3),(first,)*3)))
quarterMap.update(dict(zip((4,5,6),(second,)*3)))
quarterMap.update(dict(zip((7,8,9),(third,)*3)))
quarterMap.update(dict(zip((10,11,12),(fourth,)*3)))
print quarterMap[6]
"it is difficult to see correctness except by testing it"
. Vous devriez écrire des tests, comme le devraient tous les bons développeurs. Les tests sont ce qui vous aide à ne pas commettre d'erreurs et à attraper celles que vous faites. Un développeur ne doit jamais sacrifier les performances et la lisibilité pour éviter de se tromper. De plus, c'est moins lisible que si vous faisiez simplement un dict statique en utilisant des littéraux.
(m-1)//3 + 1
n'est pas tout à fait lisible non plus, peu de gens savent ce que //
fait. Mon commentaire original portait uniquement sur la déclaration "calculations can go wrong"
qui me semble étrange.
en utilisant des dictionnaires, vous pouvez le retirer en
def get_quarter(month):
quarter_dictionary = {
"Q1" : [1,2,3],
"Q2" : [4,5,6],
"Q3" : [7,8,9],
"Q4" : [10,11,12]
}
for key,values in quarter_dictionary.items():
for value in values:
if value == month:
return key
print(get_quarter(3))