แยกเฉพาะเดือนและปีแยกจากคอลัมน์ Pandas Datetime


221

ฉันมี Dataframe, df โดยมีคอลัมน์ต่อไปนี้:

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

องค์ประกอบของคอลัมน์คือ pandas.tslib.Timestamp

ฉันต้องการที่จะรวมปีและเดือน ฉันคิดว่าจะมีวิธีง่าย ๆ ในการทำ แต่ฉันไม่สามารถเข้าใจได้

นี่คือสิ่งที่ฉันได้ลอง:

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

ฉันได้รับข้อผิดพลาดต่อไปนี้:

Only valid with DatetimeIndex or PeriodIndex 

จากนั้นฉันก็ลอง:

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

ฉันได้รับข้อผิดพลาดต่อไปนี้:

'Timestamp' object has no attribute '__getitem__' 

ข้อเสนอแนะใด ๆ

แก้ไข: ฉันคิดออก

df.index = df['ArrivalDate']

จากนั้นฉันสามารถสุ่มคอลัมน์อีกครั้งโดยใช้ดัชนี

แต่ฉันยังต้องการวิธีกำหนดค่าคอลัมน์ทั้งหมดอีกครั้ง ความคิดใด ๆ


11
คำตอบที่ดีที่สุดคือชัดเจน .. df ['mnth_yr'] = df.date_column.dt.to_period ('M') ด้านล่างจาก @ jaknap32
ihightower

1
คุณไม่ต้องทำto_period: df.date_column.dt.month(หรือ.yearหรือ.day) ทำงาน
elz


2
@ elphz: .dt.monthแพ้ทั้งปี และ.dt.to_period('M')เปลี่ยนชนิดข้อมูลเป็นสิ่งที่ไม่ใช่ datetime64 อีกต่อไป ฉันลงเอยด้วยการใช้คำตอบของ Juan ที่แนะนำ.astype('datetime64[M]')ให้ตัดทอนค่า
Nickolay

คุณเปลี่ยนคำตอบที่ดีที่สุดได้ไหม?
กอนซาโล่การ์เซีย

คำตอบ:


306

หากคุณต้องการคอลัมน์ใหม่แสดงปีและเดือนแยกจากกันคุณสามารถทำได้:

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

หรือ...

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

จากนั้นคุณสามารถรวมพวกเขาหรือทำงานกับพวกเขาเช่นเดียวกับพวกเขา


7
มีวิธีการทำเช่นนี้ในบรรทัดเดียวหรือไม่? ฉันต้องการหลีกเลี่ยงการข้ามคอลัมน์เดียวกันหลายครั้ง
fixxxer

2
บางอย่างรวดเร็วเปรียบเทียบกับtimeitแสดงให้เห็นว่าDatetimeIndexวิธีการอย่างมีนัยสำคัญได้เร็วกว่าอย่างใดอย่างหนึ่งหรือ.map/.apply .dt
Snorfalorpagus

2
คำตอบที่ดีที่สุดคือชัดเจน .. df ['mnth_yr'] = df.date_column.dt.to_period ('M') ด้านล่างจาก @ jaknap32
ihightower

pd.Datetimeindex ทำอะไรได้จริง
จอห์น

บางครั้งฉันทำสิ่งนี้: df['date_column_trunc'] = df[date_column'].apply(lambda s: datetime.date(s.year, s.month, 1)
Stewbaca

229

วิธีที่ดีที่สุดที่พบ !!

df['date_column']จะต้องมีในรูปแบบวันที่และเวลา

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

คุณสามารถใช้Dสำหรับวันเป็น2Mเวลา 2 เดือนเป็นต้นสำหรับช่วงเวลาการสุ่มตัวอย่างที่แตกต่างกันและในกรณีที่มีข้อมูลอนุกรมเวลาที่มีการประทับเวลาเราสามารถไปช่วงเวลาการสุ่มตัวอย่างแบบละเอียดเช่น45Min45 นาที15Minสำหรับการสุ่มตัวอย่าง 15 นาทีเป็นต้น


8
โปรดทราบว่าคอลัมน์ผลลัพธ์นั้นไม่ใช่ของdatetime64dtype อีกต่อไป การใช้df.my_date_column.astype('datetime64[M]')เช่นเดียวกับในคำตอบของ @ Juanจะแปลงเป็นวันที่ซึ่งเป็นวันแรกของแต่ละเดือน
Nickolay

3
ฉันประหลาดใจที่นี่ลงมาถึงที่นี่
ทิม

154

คุณสามารถเข้าถึงyearและmonthแอตทริบิวต์โดยตรงหรือขอ a 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

วิธีหนึ่งในการรวมปีและเดือนคือทำการเข้ารหัสจำนวนเต็มเช่น: 201408สำหรับเดือนสิงหาคม 2014 ตามคอลัมน์ทั้งคอลัมน์คุณสามารถทำได้ดังนี้:

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

หรือหลายรุ่น

ฉันไม่ใช่แฟนตัวยงของการทำเช่นนี้ แต่เนื่องจากมันทำให้การจัดเรียงวันที่และเลขคณิตเจ็บปวดในภายหลังและโดยเฉพาะอย่างยิ่งความเจ็บปวดสำหรับคนอื่น ๆ ที่มากับรหัสหรือข้อมูลของคุณโดยไม่ต้องมีการประชุมเดียวกันนี้ วิธีที่ดีกว่าคือการเลือกการประชุมแบบวันต่อเดือนเช่นวันธรรมดาที่ไม่ใช่วันหยุดสุดสัปดาห์หรือวันแรกเป็นต้นและออกจากข้อมูลในรูปแบบวันที่ / เวลาด้วยการประชุมวันที่ที่เลือก

calendarโมดูลจะเป็นประโยชน์สำหรับการได้รับค่าจำนวนวันบางอย่างเช่นวันสุดท้าย จากนั้นคุณสามารถทำสิ่งที่ชอบ:

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

หากคุณกำลังมองหาวิธีในการแก้ปัญหาที่ง่ายกว่าเพียงแค่การจัดรูปแบบคอลัมน์วันที่และเวลาในการแสดงแบบสตริงสำหรับการที่คุณสามารถใช้strftimeฟังก์ชันจากdatetime.datetimeคลาสเช่นนี้:

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
ประสิทธิภาพอาจไม่ดีดังนั้นจึงเป็นการดีที่จะใช้ฟังก์ชันตัวช่วยได้ดีที่สุดการดำเนินการแบบเวกเตอร์และpandasเทคนิคแบบแยกส่วน คำแนะนำของฉันข้างต้นไม่ได้มีไว้เพื่อรับรองว่าเป็นแนวทางที่มีประสิทธิภาพมากที่สุดสำหรับกรณีของคุณ - เพียงแค่ว่าพวกเขาเป็นตัวเลือก Pythonic ที่ถูกต้องตามสไตล์สำหรับกรณีต่างๆ
ely

คำตอบด้านล่างโดย @KieranPC นั้นเร็วกว่ามาก
เบ็น

2
คำตอบที่ดีที่สุดคือชัดเจน .. df ['mnth_yr'] = df.date_column.dt.to_period ('M') ด้านล่างจาก @ jaknap32
ihightower

2
คุณควรจะคูณด้วย df['YearMonth'] = df['ArrivalDate'].map(lambda x: 1000*x.year + x.month)100
Git Gud

1
@ zthomas.nc ฉันคิดว่าพวกเขาทำงานได้ดีขึ้นเป็นสองคำตอบแยกกันเนื่องจากพวกเขามีวิธีที่แตกต่างกันสองวิธีในการแก้ปัญหา
ely

34

หากคุณต้องการคู่ที่ไม่เหมือนใครของปีในเดือนนี้

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

ส่งออกเดือนปีในหนึ่งคอลัมน์

อย่าลืมเปลี่ยนรูปแบบเป็นวันที่ก่อนก่อนโดยทั่วไปฉันลืม

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

คุณสามารถหลีกเลี่ยงฟังก์ชั่นแลมบ์ดาได้เช่นกัน:df['month_year'] = df['date_column'].dt.strftime('%B-%Y')
Rishabh

13

แยกปีพูดจาก ['2018-03-04']

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

df ['Year'] สร้างคอลัมน์ใหม่ ในขณะที่ถ้าคุณต้องการแยกเดือนเพียงใช้. เดือน


1
ขอขอบคุณมันเป็นประโยชน์จริง ๆ date_1_1 pd.DatetimeIndex (df ['date']) - ปี = date_1.year # สำหรับปี - --month = date_1.month # สำหรับเดือน - --dy = date_1 วัน # สำหรับวัน
Edwin Torres

7

ครั้งแรกที่คุณสามารถแปลงสตริงวันของคุณด้วยpandas.to_datetimeซึ่งจะช่วยให้คุณสามารถเข้าถึงทั้งหมดของnumpy datetime timedelta และสิ่งอำนวยความสะดวก ตัวอย่างเช่น:

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

นี้ทำงานได้ดีจริงๆสำหรับผมขณะที่ผมกำลังมองหาการทำงานคล้ายคลึงกับ truncpyspark มีเอกสารสำหรับการastype('datetime64[M]')ประชุมหรือไม่?
h1-the-swan

6

ขอบคุณjaknap32ฉันต้องการรวมผลลัพธ์ตามปีและเดือนดังนั้นสิ่งนี้จึงได้ผล:

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

ผลลัพธ์เป็นระเบียบ:

0    201108
1    201108
2    201108

6

@ โซลูชั่นของ KieranPC เป็นแนวทางที่ถูกต้องสำหรับ Pandas แต่ไม่สามารถขยายได้อย่างง่ายดายสำหรับคุณลักษณะที่กำหนดเอง สำหรับสิ่งนี้คุณสามารถใช้getattrภายในเครื่องกำเนิดความเข้าใจและรวมการใช้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])

สิ่งนี้ใช้ได้ผลดีสำหรับฉันไม่คิดว่าแพนด้าจะตีความวันที่ของสตริงผลลัพธ์เป็นวันที่ แต่เมื่อฉันทำพล็อตมันรู้ดีว่าวาระของฉันและสตริง year_month ที่สั่งอย่างถูกต้อง ... ต้องรักแพนด้า!


1

มีสองขั้นตอนในการแยกปีสำหรับดาต้าเฟรมทั้งหมดโดยไม่ต้องใช้วิธี

ขั้นตอนที่ 1

แปลงคอลัมน์เป็นวันที่และเวลา:

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

ขั้นตอนที่ 2

แยกปีหรือเดือนโดยใช้DatetimeIndex()วิธีการ

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

1

บรรทัดเดียว: การเพิ่มคอลัมน์ที่มี 'year-month'-paires: ('pd.to_datetime' ครั้งแรกเปลี่ยนคอลัมน์ dtype เป็นวันที่ - เวลาก่อนการดำเนินการ)

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

ดังนั้นสำหรับคอลัมน์ 'ปี' หรือ 'เดือน' เพิ่มเติม:

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

df['mm'] = pd.to_datetime(df['ArrivalDate']).dt.strftime('%m')
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.