Pandalar Tarih / Saat sütunundan yalnızca Ay ve Yılı ayrı olarak çıkarma


221

Aşağıdaki sütun ile bir Dataframe, df var:

df['ArrivalDate'] =
...
936   2012-12-31
938   2012-12-29
965   2012-12-31
966   2012-12-31
967   2012-12-31
968   2012-12-31
969   2012-12-31
970   2012-12-29
971   2012-12-31
972   2012-12-29
973   2012-12-29
...

Sütunun elemanları pandas.tslib.Timestamp'tır.

Sadece yılı ve ayı dahil etmek istiyorum. Bunu yapmanın basit bir yolu olacağını düşündüm, ama çözemiyorum.

İşte denedim:

df['ArrivalDate'].resample('M', how = 'mean')

Aşağıdaki hatayı aldım:

Only valid with DatetimeIndex or PeriodIndex 

Sonra denedim:

df['ArrivalDate'].apply(lambda(x):x[:-2])

Aşağıdaki hatayı aldım:

'Timestamp' object has no attribute '__getitem__' 

Baska öneri?

Düzenleme: Ben bunu anladım.

df.index = df['ArrivalDate']

Ardından, dizini kullanarak başka bir sütunu yeniden örnekleyebilirim.

Ancak yine de tüm sütunu yeniden yapılandırmak için bir yöntem istiyorum. Herhangi bir fikir?


11
en iyi cevap açıkça .. df ['mnth_yr'] = df.date_column.dt.to_period ('M') aşağıdaki gibi @ jaknap32
ihightower

1
Yapmanız bile gerekmiyor to_period: df.date_column.dt.month(veya .year, veya .day) çalışıyor
elz


2
@elphz: .dt.monthyılı kaybeder. Ve .dt.to_period('M')veri türünü artık datetime64 olmayan bir şeye değiştirir. Ben kullanarak sona erdi Juan'ın cevabı düşündüren .astype('datetime64[M]')değerlerini kesecek.
Nickolay

En iyi cevabı değiştirebilir misin?
Gonzalo Garcia

Yanıtlar:


306

Yıl ve ayı ayrı ayrı gösteren yeni sütunlar istiyorsanız, bunu yapabilirsiniz:

df['year'] = pd.DatetimeIndex(df['ArrivalDate']).year
df['month'] = pd.DatetimeIndex(df['ArrivalDate']).month

veya...

df['year'] = df['ArrivalDate'].dt.year
df['month'] = df['ArrivalDate'].dt.month

O zaman onları birleştirebilir veya onlarla olduğu gibi çalışabilirsiniz.


7
Bunu tek bir satırda yapmanın bir yolu var mı? Aynı sütunu birden çok kez geçmekten kaçınmak istiyorum.
fixxxer

2
İle kıyaslama Bazı hızlı timeitdüşündürmektedir DatetimeIndexyaklaşım önemli ölçüde daha hızlı ya daha .map/.applyya .dt.
Snorfalorpagus

2
en iyi cevap açıkça .. df ['mnth_yr'] = df.date_column.dt.to_period ('M') aşağıdaki gibi @ jaknap32
ihightower

pd.Datetimeindex aslında ne yapar?
JOHN

Bazen bunu yaparım: df['date_column_trunc'] = df[date_column'].apply(lambda s: datetime.date(s.year, s.month, 1)
Stewbaca

229

En iyi yol bulundu !!

df['date_column']tarih saat biçiminde olmalıdır.

df['month_year'] = df['date_column'].dt.to_period('M')

Farklı örnekleme aralıkları Diçin Gün, 2M2 Ay vb. İçin de kullanabilirsiniz ve zaman damgalı zaman serisi verilerinin olması durumunda, 45Min45 dakika, 15Min15 dakika örnekleme vb. Gibi granül örnekleme aralıkları için gidebiliriz .


8
Sonuçta elde edilen sütunun datetime64artık dtype olmadığını unutmayın. @ Juan'dadf.my_date_column.astype('datetime64[M]') olduğu gibi kullanmak , her ayın ilk gününü temsil eden tarihlere dönüşür.
Nickolay

3
Buraya kadar geldiğine şaşırdım.
Tim

154

yearVe monthözniteliklerine doğrudan erişebilir veya aşağıdakileri isteyebilirsiniz datetime.datetime:

In [15]: t = pandas.tslib.Timestamp.now()

In [16]: t
Out[16]: Timestamp('2014-08-05 14:49:39.643701', tz=None)

In [17]: t.to_pydatetime() #datetime method is deprecated
Out[17]: datetime.datetime(2014, 8, 5, 14, 49, 39, 643701)

In [18]: t.day
Out[18]: 5

In [19]: t.month
Out[19]: 8

In [20]: t.year
Out[20]: 2014

Yıl ve ayı birleştirmenin bir yolu, bunları kodlayan bir tamsayı yapmaktır, örneğin: 201408Ağustos 2014 için. Tüm bir sütun boyunca, bunu şu şekilde yapabilirsiniz:

df['YearMonth'] = df['ArrivalDate'].map(lambda x: 100*x.year + x.month)

veya bunların birçok varyantı.

Yine de bunu yapmanın büyük bir hayranı değilim, çünkü tarih hizalamasını ve aritmetiği daha sonra ağrılı ve özellikle aynı kural olmadan kodunuza veya verilerinize giren başkaları için acı verici hale getiriyor. Daha iyi bir yol, ABD tatil günleri hariç hafta içi veya ilk gün vb. Gibi ayın bir gününü seçmek ve verileri seçilen tarih kuralıyla bir tarih / saat biçiminde bırakmaktır.

calendarBu modül, son çalışma günü gibi belirli gün sayısı değeri elde etmek için kullanışlıdır. Sonra şöyle bir şey yapabilirsiniz:

import calendar
import datetime
df['AdjustedDateToEndOfMonth'] = df['ArrivalDate'].map(
    lambda x: datetime.datetime(
        x.year,
        x.month,
        max(calendar.monthcalendar(x.year, x.month)[-1][:5])
    )
)

Tarih-saat sütununu bazı dizgi gösterimlerine biçimlendirmek gibi daha basit bir sorunu çözmek için bir yol arıyorsanız, bunun strftimeiçin datetime.datetimesınıftan işlevi kullanabilirsiniz , örneğin:

In [5]: df
Out[5]: 
            date_time
0 2014-10-17 22:00:03

In [6]: df.date_time
Out[6]: 
0   2014-10-17 22:00:03
Name: date_time, dtype: datetime64[ns]

In [7]: df.date_time.map(lambda x: x.strftime('%Y-%m-%d'))
Out[7]: 
0    2014-10-17
Name: date_time, dtype: object

4
Performans kötü olabilir, bu nedenle yardımcı fonksiyonlar, vektörleştirilmiş işlemler ve pandassplit-uygula-birleştir tekniklerini mümkün olan en iyi şekilde kullanmak her zaman iyidir . Yukarıdaki önerilerim, sizin durumunuz için en etkili yaklaşımlar olduklarını onaylamak anlamına gelmez - sadece bir dizi vaka için stilistik olarak geçerli Pythonic seçimleridir.
ely

@KieranPC'nin aşağıdaki cevabı çok daha hızlı
Ben

2
en iyi cevap açıkça .. df ['mnth_yr'] = df.date_column.dt.to_period ('M') aşağıdaki gibi @ jaknap32
ihightower

2
100 inç ile çarpmanız gerekiyor df['YearMonth'] = df['ArrivalDate'].map(lambda x: 1000*x.year + x.month).
Git Gud

1
@ zthomas.nc Bence iki ayrı cevap olarak daha iyi işlev görüyorlar, çünkü çözmek için iki farklı yol sunuyorlar.
ely

34

Ay yıl benzersiz çift istiyorsanız, uygulamak oldukça şık.

df['mnth_yr'] = df['date_column'].apply(lambda x: x.strftime('%B-%Y')) 

Bir sütunda ay-yıl çıktısı.

Önce formatı tarih-saat olarak değiştirmeyi unutmayın, genellikle unuturum.

df['date_column'] = pd.to_datetime(df['date_column'])

Lambda fonksiyonundan da kaçınabilirsiniz:df['month_year'] = df['date_column'].dt.strftime('%B-%Y')
Rishabh

13

Yılın Ayıklanması: ['2018-03-04']

df['Year'] = pd.DatetimeIndex(df['date']).year  

Df ['Year'] yeni bir sütun oluşturur. Eğer ay ayıklamak istiyorsanız sadece kullanın .month


1
Teşekkürler, date_1 = pd.DatetimeIndex (df ['date']) --year = date_1.year # Yıllar için - --month = date_1.month # Aylar için - --dy = date_1. gün # Günler için--
Edwin Torres

7

Tarih dizelerinizi ilk olarak tüm numtiftime ve timedelta olanaklarına erişmenizi sağlayan pandas.to_datetime ile dönüştürebilirsiniz . Örneğin:

df['ArrivalDate'] = pandas.to_datetime(df['ArrivalDate'])
df['Month'] = df['ArrivalDate'].values.astype('datetime64[M]')

Pyspark'ınkine benzer bir işlevsellik arıyordu çünkü bu benim için gerçekten iyi çalıştı trunc. astype('datetime64[M]')Kongre için herhangi bir belge var mı ?
h1-the-swan

6

Jaknap32 sayesinde sonuçları Yıl ve Ay'a göre toplamak istedim, bu yüzden bu işe yaradı:

df_join['YearMonth'] = df_join['timestamp'].apply(lambda x:x.strftime('%Y%m'))

Çıktı düzgün:

0    201108
1    201108
2    201108

6

@ KieranPC'nin çözümü Pandalar için doğru yaklaşımdır, ancak keyfi özellikler için kolayca genişletilemez. Bunun için getattrbir jeneratör kavrayışı içinde kullanabilir ve aşağıdakileri kullanarak birleştirebilirsiniz pd.concat:

# input data
list_of_dates = ['2012-12-31', '2012-12-29', '2012-12-30']
df = pd.DataFrame({'ArrivalDate': pd.to_datetime(list_of_dates)})

# define list of attributes required    
L = ['year', 'month', 'day', 'dayofweek', 'dayofyear', 'weekofyear', 'quarter']

# define generator expression of series, one for each attribute
date_gen = (getattr(df['ArrivalDate'].dt, i).rename(i) for i in L)

# concatenate results and join to original dataframe
df = df.join(pd.concat(date_gen, axis=1))

print(df)

  ArrivalDate  year  month  day  dayofweek  dayofyear  weekofyear  quarter
0  2012-12-31  2012     12   31          0        366           1        4
1  2012-12-29  2012     12   29          5        364          52        4
2  2012-12-30  2012     12   30          6        365          52        4

1
df['year_month']=df.datetime_column.apply(lambda x: str(x)[:7])

Bu benim için iyi çalıştı, pandaların ortaya çıkan dize tarihini tarih olarak yorumlayacağını düşünmedim, ancak arsa yaptığımda, gündemi ve düzgün bir şekilde sipariş edilen year_month dizesini çok iyi biliyordu ... pandaları seviyorum!


1

Yöntem uygulanmadan tüm veri çerçevesi için yıl ayıklamak için iki adım vardır.

Aşama 1

sütunu tarih saatine dönüştür:

df['ArrivalDate']=pd.to_datetime(df['ArrivalDate'], format='%Y-%m-%d')

Adım 2

DatetimeIndex()yöntemi kullanarak yılı veya ayı ayıkla

 pd.DatetimeIndex(df['ArrivalDate']).year

1

TEK HAT: 'Yıl-ay'-çiftleri içeren bir sütun eklemek: ('pd.to_datetime' ilk önce sütun türünü işlemden önceki tarih-saat olarak değiştirir)

df['yyyy-mm'] = pd.to_datetime(df['ArrivalDate']).dt.strftime('%Y-%m')

Buna göre fazladan bir 'yıl' veya 'ay' sütunu için:

df['yyyy'] = pd.to_datetime(df['ArrivalDate']).dt.strftime('%Y')

df['mm'] = pd.to_datetime(df['ArrivalDate']).dt.strftime('%m')
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.