从给定日期提取日、月和年的最快方法是啥?

Posted

技术标签:

【中文标题】从给定日期提取日、月和年的最快方法是啥?【英文标题】:Which is the fastest way to extract day, month and year from a given date?从给定日期提取日、月和年的最快方法是什么? 【发布时间】:2014-03-24 03:13:33 【问题描述】:

我将一个包含 150,000 行的 csv 文件读入 pandas 数据帧。此数据框有一个字段 Date,其日期为 yyyy-mm-dd 格式。我想从中提取月、日和年,并分别复制到数据框的列MonthDayYear。对于几百条记录,以下两种方法可以正常工作,但是对于 150,000 条记录,执行都需要很长的时间。对于 100,000 多条记录,是否有更快的方法?

第一种方法:

df = pandas.read_csv(filename)
for i in xrange(len(df)): 
   df.loc[i,'Day'] = int(df.loc[i,'Date'].split('-')[2])

第二种方法:

df = pandas.read_csv(filename)
for i in xrange(len(df)):
   df.loc[i,'Day'] = datetime.strptime(df.loc[i,'Date'], '%Y-%m-%d').day

谢谢。

【问题讨论】:

您的时间限制是多少?或者从考虑中去除机器能力,你需要什么因素来加速它?我认为“长得离谱”不足以让回答这个问题的人知道像int(df.loc[i,'Date'][-2:]) 这样的答案是否足够快,暂时搁置数据格式是否足够可靠的问题认为是正确的。 我没有设置时间限制。数据是干净的 - 没有 NaN/NaT 条目或混乱/格式不正确的值。我想不出第三种方法来做到这一点。因此,我试图找出是否有更好的逻辑,或者是否有一些内置的 pandas 方法可以在同一台机器上加快速度。 您是否考虑过包装一个 csv 阅读器,以便它拆分日期列并附加日、月和年,并使用该迭代器创建一个 pandas 框架。 @Steve:非常感谢。这比上面两个要快。有没有办法找出每个代码执行所花费的时间? @ram:使用timeit 模块。 【参考方案1】:

This is the cleanest answer I've found.

df = df.assign(**t:getattr(df.data.dt,t) for t in nomtimes)

In [30]: df = pd.DataFrame('data':pd.date_range(start, end))

In [31]: df.head()
Out[31]:
        data
0 2011-01-01
1 2011-01-02
2 2011-01-03
3 2011-01-04
4 2011-01-05

nomtimes = ["year", "hour", "month", "dayofweek"] 
df = df.assign(**t:getattr(df.data.dt,t) for t in nomtimes)

In [33]: df.head()
Out[33]:
        data  dayofweek  hour  month  year
0 2011-01-01          5     0      1  2011
1 2011-01-02          6     0      1  2011
2 2011-01-03          0     0      1  2011
3 2011-01-04          1     0      1  2011
4 2011-01-05          2     0      1  2011

【讨论】:

【参考方案2】:

我使用下面的代码非常适合我

df['Year']=[d.split('-')[0] for d in df.Date]
df['Month']=[d.split('-')[1] for d in df.Date]
df['Day']=[d.split('-')[2] for d in df.Date]

df.head(5)

【讨论】:

【参考方案3】:

在 0.15.0 中,您将能够使用新的 .dt 访问器在语法上做到这一点。

In [36]: df = DataFrame(date_range('20000101',periods=150000,freq='H'),columns=['Date'])

In [37]: df.head(5)
Out[37]: 
                 Date
0 2000-01-01 00:00:00
1 2000-01-01 01:00:00
2 2000-01-01 02:00:00
3 2000-01-01 03:00:00
4 2000-01-01 04:00:00

[5 rows x 1 columns]

In [38]: %timeit f(df)
10 loops, best of 3: 22 ms per loop

In [39]: def f(df):
    df = df.copy()
    df['Year'] = DatetimeIndex(df['Date']).year
    df['Month'] = DatetimeIndex(df['Date']).month
    df['Day'] = DatetimeIndex(df['Date']).day
    return df
   ....: 

In [40]: f(df).head()
Out[40]: 
                 Date  Year  Month  Day
0 2000-01-01 00:00:00  2000      1    1
1 2000-01-01 01:00:00  2000      1    1
2 2000-01-01 02:00:00  2000      1    1
3 2000-01-01 03:00:00  2000      1    1
4 2000-01-01 04:00:00  2000      1    1

[5 rows x 4 columns]

从 0.15.0 起(2014 年 9 月底发布),现在可以使用新的 .dt 访问器实现以下功能:

df['Year'] = df['Date'].dt.year
df['Month'] = df['Date'].dt.month
df['Day'] = df['Date'].dt.day

【讨论】:

请注意,读取 csv 时应使用 parse_dates kw 杰夫,当每个日期都是时间戳时(或者如果“日期”是 DatetimeIndex。但这让我想到将您的代码修改为 df['Days'] = DatetimeIndex(to_datetime(df['Date'])).day 以达到相同的结果。谢谢一吨。这实际上在我的机器上的 pandas 0.13.1 中工作。 我忘了提。事实证明这是迄今为止最快的。在这里,使用 'for' 超过 150,000 个 'Date' 元素与使用 'DatetimeIndex' 超过 pandas Series 'Date' 之间的区别是显而易见的。我想我会做一个“timeit”比较并研究所有三种方法。

以上是关于从给定日期提取日、月和年的最快方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

从 HBase 中提取数据的最快方法是啥

Excel确定现有日期的上一个月和年

从 C++ 中的字节数组中提取非零索引的最快方法是啥

Drupal 视图 UI,过滤器暴露,集合字段内容中的日期仅按月和年(无天)

从 URL 获取域名/主机名的最快方法是啥?

仅用月和年更改日期格式