Trích xuất riêng tháng và năm từ cột Pandas Datetime


221

Tôi có một Dataframe, df, với cột sau:

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

Các yếu tố của cột là pandas.tslib.Timestamp.

Tôi muốn chỉ bao gồm năm và tháng. Tôi nghĩ rằng sẽ có cách đơn giản để làm điều đó, nhưng tôi không thể tìm ra nó.

Đây là những gì tôi đã thử:

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

Tôi đã nhận được lỗi sau:

Only valid with DatetimeIndex or PeriodIndex 

Sau đó tôi đã thử:

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

Tôi đã nhận được lỗi sau:

'Timestamp' object has no attribute '__getitem__' 

Bất kỳ đề xuất?

Chỉnh sửa: Tôi sắp xếp nó ra.

df.index = df['ArrivalDate']

Sau đó, tôi có thể lấy mẫu lại một cột khác bằng cách sử dụng chỉ mục.

Nhưng tôi vẫn muốn một phương pháp để cấu hình lại toàn bộ cột. Có ý kiến ​​gì không?


11
câu trả lời tốt nhất là rõ ràng .. df ['mnth_yr'] = df.date_column.dt.to_apse ('M') như dưới đây từ @ jaknap32
ihightower

1
Bạn thậm chí không phải làm to_period: df.date_column.dt.month(hoặc .year, hoặc .day) hoạt động
elz


2
@elphz: .dt.monthmặc dù mất năm. Và .dt.to_period('M')thay đổi kiểu dữ liệu thành một thứ không còn là datetime64 nữa. Tôi đã kết thúc bằng cách sử dụng câu trả lời của Juan đề nghị .astype('datetime64[M]')cắt bớt các giá trị.
Nickolay

Bạn có thể thay đổi câu trả lời tốt nhất?
Gonzalo Garcia

Câu trả lời:


306

Nếu bạn muốn các cột mới hiển thị riêng năm và tháng, bạn có thể làm điều này:

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

hoặc là...

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

Sau đó, bạn có thể kết hợp chúng hoặc làm việc với chúng như chúng là.


7
Có cách nào để làm điều này trong một dòng duy nhất? Tôi muốn tránh đi qua cùng một cột nhiều lần.
fixxxer

2
Một số điểm chuẩn nhanh với timeitgợi ý rằng DatetimeIndexcách tiếp cận nhanh hơn đáng kể so với .map/.applyhoặc .dt.
Snorfalorpagus

2
câu trả lời tốt nhất rõ ràng là .. df [ 'mnth_yr'] = df.date_column.dt.to_period ( 'M') như sau từ @ jaknap32
ihightower

pd.Datetimeindex thực sự làm gì?
JOHN

Thỉnh thoảng tôi làm điều này: df['date_column_trunc'] = df[date_column'].apply(lambda s: datetime.date(s.year, s.month, 1)
Stewbaca

229

Cách tốt nhất được tìm thấy !!

các df['date_column']có phải ở định dạng thời gian ngày.

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

Bạn cũng có thể sử dụng Dcho Ngày, 2Mtrong 2 tháng, vv cho các khoảng thời gian lấy mẫu khác nhau và trong trường hợp người ta có dữ liệu chuỗi thời gian với dấu thời gian, chúng ta có thể sử dụng các khoảng thời gian lấy mẫu dạng hạt như 45Mintrong 45 phút, 15Minđể lấy mẫu 15 phút, v.v.


8
Lưu ý rằng cột kết quả không phải là của datetime64dtype nữa. Sử dụng df.my_date_column.astype('datetime64[M]'), như trong câu trả lời của @ Juan chuyển thành ngày đại diện cho ngày đầu tiên mỗi tháng.
Nickolay

3
Tôi ngạc nhiên rằng đây là tất cả các cách ở đây.
Tim

154

Bạn có thể truy cập trực tiếp yearmonthcác thuộc tính hoặc yêu cầu 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

Một cách để kết hợp năm và tháng là tạo một số nguyên mã hóa chúng, chẳng hạn như: 201408cho tháng 8 năm 2014. Cùng với toàn bộ một cột, bạn có thể làm điều này như sau:

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

hoặc nhiều biến thể của chúng.

Tuy nhiên, tôi không phải là một fan hâm mộ lớn của việc này, vì nó làm cho việc căn chỉnh ngày và số học trở nên đau đớn và đặc biệt đau đớn cho những người khác tìm thấy mã hoặc dữ liệu của bạn mà không có quy ước này. Cách tốt hơn là chọn một quy ước ngày trong tháng, chẳng hạn như ngày cuối tuần không phải là ngày nghỉ lễ ở Hoa Kỳ, hoặc ngày đầu tiên, v.v., và để dữ liệu theo định dạng ngày / giờ với quy ước ngày đã chọn.

Các calendarmô-đun là hữu ích cho việc thu thập các giá trị số ngày nhất định như các ngày trong tuần chính thức. Sau đó, bạn có thể làm một cái gì đó như:

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

Nếu bạn tình cờ tìm cách giải quyết vấn đề đơn giản hơn là chỉ định dạng cột datetime thành một số biểu diễn được sắp xếp theo chuỗi, bạn có thể sử dụng strftimehàm từ datetime.datetimelớp, như sau:

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
Hiệu suất có thể là xấu, do đó, luôn luôn tốt để sử dụng tốt nhất các chức năng của trình trợ giúp, các hoạt động được vector hóa và pandascác kỹ thuật kết hợp phân tách. Những gợi ý của tôi ở trên không có nghĩa là được coi là một cách chứng thực rằng chúng là cách tiếp cận hiệu quả nhất cho trường hợp của bạn - chỉ là chúng là những lựa chọn Pythonic có giá trị về mặt phong cách cho một loạt các trường hợp.
ely

Câu trả lời dưới đây của @KieranPC nhanh hơn nhiều
Ben

2
câu trả lời tốt nhất rõ ràng là .. df [ 'mnth_yr'] = df.date_column.dt.to_period ( 'M') như sau từ @ jaknap32
ihightower

2
Bạn phải nhân lên 100 in df['YearMonth'] = df['ArrivalDate'].map(lambda x: 1000*x.year + x.month).
Git Gud

1
@ zthomas.nc Tôi nghĩ rằng chúng hoạt động tốt hơn như hai câu trả lời riêng biệt, vì chúng đưa ra hai cách rất khác nhau để giải quyết nó.
ely

34

Nếu bạn muốn cặp đôi độc đáo tháng, sử dụng áp dụng là khá đẹp.

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

Sản lượng tháng năm trong một cột.

Đừng quên thay đổi định dạng trước thành thời gian trước đó, tôi thường quên.

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

Bạn cũng có thể tránh chức năng lambda:df['month_year'] = df['date_column'].dt.strftime('%B-%Y')
Rishabh

13

Trích xuất năm nói từ ['2018-03-04']

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

Df ['Year'] tạo một cột mới. Trong khi nếu bạn muốn trích xuất tháng, chỉ cần sử dụng .month


1
Cảm ơn, ngày thực sự hữu ích_1 = pd.Datetime Index (df ['date']) --year = date_1.year # Trong nhiều năm-- --month = date_1.month # Trong nhiều tháng-- --dy = date_1. ngày # Trong nhiều ngày--
Edwin Torres

7

Trước tiên, bạn có thể chuyển đổi chuỗi ngày của mình bằng pandas.to_datetime , cho phép bạn truy cập vào tất cả các tiện ích datetime và timedelta numpy . Ví dụ:

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

Điều này thực sự hiệu quả với tôi, vì tôi đang tìm kiếm chức năng tương tự như pyspark trunc. Có tài liệu nào cho astype('datetime64[M]')hội nghị không?
h1-the-swan

6

Nhờ jaknap32 , tôi muốn tổng hợp kết quả theo Năm và Tháng, vì vậy điều này đã hoạt động:

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

Đầu ra gọn gàng:

0    201108
1    201108
2    201108

6

Giải pháp của @ KieranPC là cách tiếp cận chính xác cho Pandas, nhưng không dễ dàng mở rộng cho các thuộc tính tùy ý. Đối với điều này, bạn có thể sử dụng getattrtrong phạm vi hiểu biết của trình tạo và kết hợp bằng cách sử dụng 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])

Điều này làm việc tốt với tôi, không nghĩ gấu trúc sẽ diễn giải ngày kết quả là ngày, nhưng khi tôi thực hiện cốt truyện, nó biết rất rõ chương trình nghị sự của tôi và chuỗi năm_month nơi đặt mua đúng cách ... phải yêu gấu trúc!


1

Có hai bước để trích xuất năm cho tất cả các khung dữ liệu mà không sử dụng phương pháp áp dụng.

Bước 1

chuyển đổi cột thành datetime:

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

Bước 2

trích xuất năm hoặc tháng sử dụng DatetimeIndex()phương pháp

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

1

SINGLE LINE: Thêm một cột với cặp 'năm-tháng': ('pd.to_datetime' trước tiên thay đổi dtype cột thành thời gian trước khi hoạt động)

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

Theo đó cho một cột 'năm' hoặc 'tháng' thêm:

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

df['mm'] = pd.to_datetime(df['ArrivalDate']).dt.strftime('%m')
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.