Впевнений, що я міг би це написати сам, але перед тим, як зайнятися винаходом колеса, є функція, яка вже це робить?
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- тепер це не виглядає для вас надзвичайно переважним? -)
Це доводить, що питання, на мою думку, є досить обґрунтованим; я думаю ;-).
Я не вважаю, що модуль дати повинен обов'язково виконувати всі можливі корисні функції календаря, але я знаю, що я підтримую (добре перевірений ;-) 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є ідеальним рішенням, коли у вас є значення дати в об'єкті 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
.зробив після 3-х. math.ceil(4/3.) = 2.0
Для тих, хто намагається отримати квартал фінансового року, який може відрізнятися від календарного року, я написав модуль Python, щоб зробити саме це.
Установка проста. Просто запустіть:
$ pip install fiscalyear
Немає залежностей, і fiscalyear повинні працювати як для Python 2, так і для 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
Для тих, хто шукає дані за квартал фінансового року, використовуючи панди,
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"яке мені просто звучить дивно.
Ось багатослівне, але також читабельне рішення, яке буде працювати для екземплярів дати та дати
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
використовуючи словники, ви можете витягнути це
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))