Конечно, я мог бы написать это сам, но прежде чем изобретать колесо, есть ли функция, которая уже это делает?
pandas.Series.dt.quarter
.
Конечно, я мог бы написать это сам, но прежде чем изобретать колесо, есть ли функция, которая уже это делает?
pandas.Series.dt.quarter
.
Ответы:
Учитывая экземпляр x
из datetime.date , (x.month-1)//3
даст вам четверть (0 за первый квартал, 1 за второй квартал и т.д. - добавить 1 , если вам нужно считать от 1 вместо ;-).
Первоначально два ответа, многократно проголосовавшие за и даже первоначально принятые (оба в настоящее время удалены), были ошибочными - не выполнялось -1
до деления и делилось на 4 вместо 3. Поскольку .month
идет от 1 до 12, легко проверить для себя, что такое формула право:
for m in range(1, 13):
print m//4 + 1,
print
дает 1 1 1 2 2 2 2 3 3 3 3 4
- два четырехмесячных квартала и одномесячный (eep).
for m in range(1, 13):
print (m-1)//3 + 1,
print
дает 1 1 1 2 2 2 3 3 3 4 4 4
- разве это не выглядит для вас намного предпочтительнее? -)
Это доказывает, что вопрос, я думаю, вполне обоснован ;-).
Я не думаю, что модуль datetime обязательно должен иметь все возможные полезные календарные функции, но я знаю, что поддерживаю (хорошо протестированный ;-) datetools
модуль для использования моих (и других) проектов на работе, в котором много маленьких функции для выполнения всех этих календарных вычислений - некоторые из них сложные, некоторые простые, но нет причин выполнять работу снова и снова (даже простую) или рисковать ошибками в таких вычислениях ;-).
(m+2)//3
вместо(m-1)//3 + 1
ЕСЛИ вы уже пользуетесь pandas
, это довольно просто.
import datetime as dt
import pandas as pd
quarter = pd.Timestamp(dt.date(2016, 2, 29)).quarter
assert quarter == 1
Если у вас есть date
столбец во фрейме данных, вы можете легко создать новый quarter
столбец:
df['quarter'] = df['date'].dt.quarter
pandas.Series.dt.quarter
- идеальное решение, когда у вас есть значения datetime в объекте Dataframe или Series .
Я бы предложил другое, возможно, более чистое решение. Если X - datetime.datetime.now()
экземпляр, то квартал равен:
import math
Q=math.ceil(X.month/3.)
ceil необходимо импортировать из математического модуля, так как к нему нельзя получить прямой доступ.
math.ceil(float(4)/3) = 2.0
math.ceil(4/3) = 1.0
.
сделали после тройки. math.ceil(4/3.) = 2.0
Для тех, кто пытается получить квартал финансового года, который может отличаться от календарного года, я написал модуль Python, чтобы сделать именно это.
Установка проста. Просто беги:
$ pip install fiscalyear
Нет никаких зависимостей и fiscalyear
должно работать как для Python 2, так и для Python 3.
По сути, это оболочка для встроенного модуля datetime , поэтому любые datetime
команды, с которыми вы уже знакомы, будут работать. Вот демо:
>>> 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
размещен на GitHub и PyPI . Документацию можно найти в разделе «Прочитать документацию» . Если вы ищете какие-либо функции, которых у него сейчас нет, дайте мне знать!
Вот пример функции, которая получает объект datetime.datetime и возвращает уникальную строку для каждого квартала:
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))
И результат:
2019-02-14 Q1_2019
2018-11-16 Q4_2018
2017-08-18 Q3_2017
Этот метод работает для любого отображения:
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
Мы только что сгенерировали функцию int->int
month2quarter(9) # returns 3
Этот метод также надежен
month2quarter(-1) # returns None
month2quarter('July') # returns None
Для тех, кто ищет данные за квартал финансового года, используя pandas,
import datetime
import pandas as pd
today_date = datetime.date.today()
quarter = pd.PeriodIndex(today_date, freq='Q-MAR').strftime('Q%q')
ссылка: индекс периода панд
Это старый вопрос, но он все же заслуживает обсуждения.
Вот мое решение, использующее отличный модуль 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)
Таким образом, first_day
это первый день квартала и last_day
последний день квартала (вычисляется путем нахождения первого дня следующего квартала минус один день).
хммм, поэтому расчеты могут пойти не так, вот лучшая версия (просто ради нее)
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"
. Вы должны писать тесты, как и все хорошие разработчики. Тесты - это то, что помогает уберечь вас от ошибок и выявить те, которые вы делаете. Разработчик никогда не должен жертвовать производительностью и удобочитаемостью, чтобы не допустить ошибки. Кроме того, это менее читабельно, чем если бы вы просто сделали статический диктант с использованием литералов.
(m-1)//3 + 1
, тоже не все так читабельно, не многие люди знают, что //
делает. Мой первоначальный комментарий был просто по поводу утверждения, "calculations can go wrong"
которое мне кажется странным.
Вот подробное, но также удобочитаемое решение, которое будет работать для экземпляров datetime и date.
def get_quarter(date):
for months, quarter in [
([1, 2, 3], 1),
([4, 5, 6], 2),
([7, 8, 9], 3),
([10, 11, 12], 4)
]:
if date.month in months:
return quarter