从Pandas Datetime列中提取月份和年份

mon*_*iz7 177 python pandas

我有一个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
...
Run Code Online (Sandbox Code Playgroud)

该列的元素是pandas.tslib.Timestamp.

我想要包括年份和月份.我认为会有简单的方法,但我无法弄清楚.

这是我尝试过的:

df['ArrivalDate'].resample('M', how = 'mean')
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

Only valid with DatetimeIndex or PeriodIndex 
Run Code Online (Sandbox Code Playgroud)

然后我尝试了:

df['ArrivalDate'].apply(lambda(x):x[:-2])
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

'Timestamp' object has no attribute '__getitem__' 
Run Code Online (Sandbox Code Playgroud)

有什么建议?

编辑:我有点想通了.

df.index = df['ArrivalDate']
Run Code Online (Sandbox Code Playgroud)

然后,我可以使用索引重新采样另一列.

但我仍然想要一种重新配置整个列的方法.有任何想法吗?

Kie*_*nPC 246

如果您想要分别显示年份和月份的新列,则可以执行以下操作:

df['year'] = pd.DatetimeIndex(df['ArrivalDate']).year
df['month'] = pd.DatetimeIndex(df['ArrivalDate']).month
Run Code Online (Sandbox Code Playgroud)

要么...

df['year'] = df['ArrivalDate'].dt.year
df['month'] = df['ArrivalDate'].dt.month
Run Code Online (Sandbox Code Playgroud)

然后你可以将它们组合起来或者像它们一样使用它们.

  • 有没有办法在一行中做到这一点?我想避免多次遍历同一列. (6认同)
  • 我有时会这样做:`df['date_column_trunc'] = df[date_column'].apply(lambda s: datetime.date(s.year, s.month, 1)` (4认同)
  • 一些使用timeit的快速基准测试表明,DatetimeIndex方法比.map / .apply或.dt都快得多。 (2认同)
  • 最好的答案显然是.. df ['mnth_yr'] = df.date_column.dt.to_period('M'),如下所示,来自@ jaknap32 (2认同)

Pan*_*bra 206

找到最佳方式 !!

df['date_column']必须是日期时间格式.

df['month_year'] = df['date_column'].dt.to_period('M')
Run Code Online (Sandbox Code Playgroud)

您也可以使用DDay,2M2个月等不同的采样间隔,如果有时间序列数据带有时间戳,我们可以采用粒度采样间隔,例如45Min45分钟,15Min15分钟采样等.

  • 请注意,结果列不再是`datetime64` dtype.使用`df.my_date_column.astype('datetime64 [M]')`,如[@ Juan的答案](/sf/answers/3049296561/)转换为代表每个月第一天的日期. (7认同)

ely*_*ely 132

您可以直接访问yearmonth属性,或者请求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
Run Code Online (Sandbox Code Playgroud)

将年份和月份组合在一起的一种方法是对它们进行整数编码,例如:2014082014年8月.在整个列中,您可以这样做:

df['YearMonth'] = df['ArrivalDate'].map(lambda x: 100*x.year + x.month)
Run Code Online (Sandbox Code Playgroud)

或其许多变体.

但是,我并不是这样做的忠实粉丝,因为它会使日期对齐和算术变得更加痛苦,对于那些在没有相同约定的情况下遇到代码或数据的人来说尤其痛苦.更好的方法是选择一个月日约定,例如最终非美国假日工作日或第一天等,并将数据保留为具有所选日期约定的日期/时间格式.

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])
    )
)
Run Code Online (Sandbox Code Playgroud)

如果您正在寻找一种方法来解决将datetime列格式化为某种字符串化表示的简单问题,那么您可以使用该类中的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
Run Code Online (Sandbox Code Playgroud)

  • 性能可能很差,因此最好尽可能地使用辅助函数,向量化操作和"pandas"split-apply-combine技术.我上面的建议并不意味着认为它们是你的案例中最有效的方法 - 只是它们在风格上是有效的Pythonic选择的一系列案例. (2认同)
  • 最好的答案显然是.. df ['mnth_yr'] = df.date_column.dt.to_period('M'),如下所示,来自@ jaknap32 (2认同)
  • 你应该在`df['YearMonth'] = df['ArrivalDate'].map(lambda x: 1000*x.year + x.month)`中乘以100。 (2认同)

Pan*_*bra 28

如果你想要月份独特的一对,使用apply非常光滑.

df['mnth_yr'] = df['date_column'].apply(lambda x: x.strftime('%B-%Y')) 
Run Code Online (Sandbox Code Playgroud)

在一栏中输出月份年份.

别忘了先将格式改为日期时间,我一般都会忘记:|

df['date_column'] = pd.to_datetime(df['date_column'])
Run Code Online (Sandbox Code Playgroud)

  • 您也可以避免使用 lambda 函数:`df['month_year'] = df['date_column'].dt.strftime('%B-%Y')` (6认同)

小智 12

提取年份说自['2018-03-04']

df['Year'] = pd.DatetimeIndex(df['date']).year  
Run Code Online (Sandbox Code Playgroud)

df ['Year']创建一个新列.如果你想提取月份只需使用.month


Mat*_*000 11

单行:添加一个带有'year-month'-paires 的列:('pd.to_datetime'在操作之前首先将列dtype更改为date-time)

df['yyyy-mm'] = pd.to_datetime(df['ArrivalDate']).dt.strftime('%Y-%m')?
Run Code Online (Sandbox Code Playgroud)

因此,对于额外的“年”或“月”列:

df['yyyy'] = pd.to_datetime(df['ArrivalDate']).dt.strftime('%Y')?
df['mm'] = pd.to_datetime(df['ArrivalDate']).dt.strftime('%m')?
Run Code Online (Sandbox Code Playgroud)

  • 与 ``.dt.year + "-" + .dt.month``` 中的切片和添加相比,.dt.strftime('%Y-%m') 非常慢,尤其是在数百万条记录上 (2认同)

Jua*_*rro 7

您可以首先使用pandas.to_datetime转换日期字符串,这使您可以访问所有的numpy datetime和timedelta工具。例如:

df['ArrivalDate'] = pandas.to_datetime(df['ArrivalDate'])
df['Month'] = df['ArrivalDate'].values.astype('datetime64[M]')
Run Code Online (Sandbox Code Playgroud)

  • 这对我来说非常有效,因为我正在寻找类似于 pyspark 的 [`trunc`](https://spark.apache.org/docs/latest/api/python/pyspark.sql.html?highlight=date# pyspark.sql.functions.trunc)。是否有关于“astype('datetime64[M]')”约定的任何文档? (2认同)

jpp*_*jpp 7

@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
Run Code Online (Sandbox Code Playgroud)


小智 5

感谢jaknap32,我想根据Year和Month汇总结果,所以可以这样:

df_join['YearMonth'] = df_join['timestamp'].apply(lambda x:x.strftime('%Y%m'))
Run Code Online (Sandbox Code Playgroud)

输出整洁:

0    201108
1    201108
2    201108
Run Code Online (Sandbox Code Playgroud)