从给定日期提取日、月和年的最快方法是啥?
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
格式。我想从中提取月、日和年,并分别复制到数据框的列Month
、Day
和Year
。对于几百条记录,以下两种方法可以正常工作,但是对于 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”比较并研究所有三种方法。以上是关于从给定日期提取日、月和年的最快方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章