Bir tarihin yılın hangi çeyreğinde olduğunu belirleyen bir Python işlevi var mı?


113

Elbette bunu kendim yazabilirim, ancak tekerleği yeniden icat etmeden önce bunu zaten yapan bir işlev var mı?


22
Soru İlk cevaplar biraz küçümseyici görünse bile ("sadece bir mesele", "oldukça basit görünüyor"): ÇOK garantilidir: cevaplardan ikisi (YÜKSELTİLMİŞ olanı da dahil!) Korkunç derecede hatalı, her şeyin o kadar basit olmadığını gösteriyor veya " sadece "...
Alex Martelli

Eminim geri dönüp bunu düzeltir
Nadia Alramli

Bu soru 2018'de çok yardımcı oldu: D
wdfc

Tarih saat nesneleri saklanır ise Pandalar Serisi veya Dataframe , ilgili çeyrek (lar) döndüren bir yöntem vardır: pandas.Series.dt.quarter.
Sumanth Lazarus

Yanıtlar:


162

Bir örnek göz önüne alındığında xait datetime.date , (x.month-1)//3sen ;-) yerine 1'den saymak gerekirse 1 eklenir - vb ikinci çeyrek için, ilk çeyreği için size 1 çeyrek (0 verecektir.


Başlangıçta iki cevap, çarpılarak yükseltilmiş ve hatta başlangıçta kabul edilmiş (her ikisi de şu anda silinmiş) hatalıydı - -1önceki bölümü yapmamak ve 3 yerine 4'e bölmek. .month1'den 12'ye kadar olduğu için formülün ne olduğunu kendiniz kontrol etmek kolaydır. sağ:

for m in range(1, 13):
  print m//4 + 1,
print

verir 1 1 1 2 2 2 2 3 3 3 3 4- dört aylık iki çeyrek ve bir aylık bir (eep).

for m in range(1, 13):
  print (m-1)//3 + 1,
print

verir 1 1 1 2 2 2 3 3 3 4 4 4- şimdi bu sizin için çok tercih edilir görünmüyor mu? -)

Bu, sorunun haklı olduğunu kanıtlıyor, sanırım ;-).

Datetime modülünün her olası yararlı takvim işlevine sahip olması gerektiğini düşünmüyorum, ancak datetoolsişyerinde projelerimin (ve diğerlerinin) kullanımı için bir (iyi test edilmiş ;-) modülüne sahip olduğumu biliyorum ; tüm bu takvim hesaplamalarını gerçekleştirmek için işlevler - bazıları karmaşık, bazıları basit, ancak bu tür hesaplamalarda işi tekrar tekrar yapmak (hatta basit işler bile) veya hata riski ;-).


3
Teşekkürler Alex. Bu yüzden bir fonksiyon olmalı. Bak kaç kişi yanlış anladı.
Jason Christa

Sanırım amacını kanıtladın. Sayfanın tamamını tekrar eden yorumlarla kirletmek gereksizdir.
João Silva

1
@ Jason, evet, kesinlikle - bu yüzden diğer hatalı cevapları (şu anda silinmiş) gördüğümde sorunuzu yükselttim, bir başkası benim olumlu oyumu saymak için olumsuz oy vermiş gibi görünse de, ah iyi.
Alex Martelli

1
@JG, ne "tekrarlanan yorumlar"? Hatalı cevaplar silindiğinde, yorumlar da onlarla birlikte kayboldu, bu yüzden içeriklerini cevaba getirdim - dikkatinin dağılmasının veya aceleye getirilmesinin ne kadar kolay olduğunun farkında olmak ve basit bir hesaplamada bile önlenebilir bir hata elde etmek önemlidir. ve programlama en iyi uygulamaları için sonuçları (yeniden kullanılabilir işlevlerin yapılması ve sağlam bir şekilde test edilmesi açısından); bu dava iyi bir örnek (ki bu sorunun haklı olduğunu kanıtladığını düşünüyorum).
Alex Martelli

7
Şunu da kullanabilir: (m+2)//3Bunun yerine(m-1)//3 + 1
Ben

49

EĞER zaten kullandığınız pandas, oldukça basit.

import datetime as dt
import pandas as pd

quarter = pd.Timestamp(dt.date(2016, 2, 29)).quarter
assert quarter == 1

Bir veri çerçevesinde bir datesütununuz varsa, kolayca yeni bir quartersütun oluşturabilirsiniz :

df['quarter'] = df['date'].dt.quarter

Mali yıl üç aylık dönemim Eylül'de başlıyorsa ne olur?
Arthur D. Howland

Pandas yöntemi pandas.Series.dt.quarter, Dataframe veya Series nesnesinde datetime değerlerine sahip olduğunuzda ideal bir çözümdür .
Sumanth Lazarus

31

Tartışmalı olarak daha temiz başka bir çözüm öneririm. X bir datetime.datetime.now()örnek ise, çeyrek şu şekildedir:

import math
Q=math.ceil(X.month/3.)

ceil doğrudan erişilemediği için matematik modülünden içe aktarılmalıdır.


1
Şimdiye kadarki en iyisi. Çok teşekkürler!
curlyreggie

3
Muhtemelen bunu bir int () ile
sarmalıyım

@Garbanzio cevabının önerdiği gibi. Ben bu işe almak için şamandıra işlevi aracılığıyla aylık argüman koymak için gerekli math.ceil(float(4)/3) = 2.0süremath.ceil(4/3) = 1.0
Theo Kouzelis

1
Beni görmezden gelin .3'ün ne yaptığını anlamadım. math.ceil(4/3.) = 2.0
Theo Kouzelis

11

Takvim yılından farklı olabilecek mali yılın çeyreğini almaya çalışan herkes için , bunu yapmak için bir Python modülü yazdım.

Kurulum basittir. Sadece koş:

$ pip install fiscalyear

Bağımlılık yoktur ve fiscalyearhem Python 2 hem de 3 için çalışmalıdır.

Temelde yerleşik datetime modülü etrafında bir sarmalayıcıdır , bu nedenle datetimezaten aşina olduğunuz tüm komutlar çalışacaktır. İşte bir demo:

>>> 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)

fiscalyearGitHub ve PyPI'de barındırılmaktadır . Belgeler, Belgeleri Okuyun adresinde bulunabilir . Şu anda sahip olmayan herhangi bir özelliği arıyorsanız, bize bildirin!


4

Bir datetime.datetime nesnesi alan ve her çeyrek için benzersiz bir dize döndüren bir işlev örneği aşağıda verilmiştir:

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))

Ve çıktı:

2019-02-14 Q1_2019
2018-11-16 Q4_2018
2017-08-18 Q3_2017


2

Bu yöntem herhangi bir eşleme için işe yarar:

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

Az önce bir fonksiyon oluşturduk int->int

month2quarter(9) # returns 3

Bu yöntem aynı zamanda kusursuzdur

month2quarter(-1) # returns None
month2quarter('July') # returns None

2

Pandalar kullanarak mali yıl çeyrek verilerini arayanlar için,

import datetime
import pandas as pd
today_date = datetime.date.today()
quarter = pd.PeriodIndex(today_date, freq='Q-MAR').strftime('Q%q')

başvuru: pandalar dönem dizini


1

Bu eski bir sorudur ama yine de tartışmaya değer.

İşte benim çözümüm, mükemmel dateutil modülünü kullanarak .

  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)

Bu first_day, çeyreğin ilk günüdür ve çeyreğin last_dayson günüdür (sonraki çeyreğin ilk günü eksi bir gün bulunarak hesaplanır).


1

Bu çok basittir ve python3'te çalışır:

from datetime import datetime

# Get current date-time.
now = datetime.now()

# Determine which quarter of the year is now. Returns q1, q2, q3 or q4.
quarter_of_the_year = 'q'+str((now.month-1)//3+1)

0

hmmm hesaplamalar yanlış gidebilir, işte daha iyi bir versiyon (sadece uğruna)

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]

@RussBradberry bu durumda haklı olabilirsiniz, ancak bazen okunabilirlik ve açık olmak, kısa bir hesaplama yerine sayılır ve daha az hataya yol açar
Anurag Uniyal

1
@RussBradberry de bununla ilgili silinen cevapları ve yorumları görün, basit bir hesaplamanın iyi programcılar için de yanıltıcı olabileceğini görün ve test etmek dışında doğruluğu görmek zor, benim
çözümümde

1
aynen dediğin gibi "it is difficult to see correctness except by testing it". Tüm iyi geliştiricilerin yapması gerektiği gibi testler yazmalısınız. Testler, sizi hata yapmaktan alıkoymaya ve yaptığınız hataları yakalamanıza yardımcı olan şeydir. Bir geliştirici, hata yapmasını engellemek için performans ve okunabilirlikten asla ödün vermemelidir. Ayrıca, bu, değişmez değerleri kullanarak statik bir diktede bulunmanızdan daha az okunabilir.
Russ Bradberry

Beni yanlış anlama (m-1)//3 + 1o kadar da okunabilir değil, çoğu insan ne yaptığını bilmiyor //. Orijinal yorumum sadece "calculations can go wrong"bana garip gelen ifadesi üzerineydi.
Russ Bradberry

@RussBradberry aslında sana katılıyorum cevabım bir alternatifti ve bazen de insanların bir haritaya kodlanmış bir şeyi hesaplamaya / çıkarmaya çalıştığı çok sayıda kod gördüm
Anurag Uniyal

0

İşte datetime ve tarih örnekleri için çalışacak ayrıntılı, ancak okunabilir bir çözüm

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

0

sözlükleri kullanarak, bunu şu şekilde yapabilirsiniz:

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))
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.