Python pandas 通过 dt 访问器有效地将日期时间转换为时间戳
Posted
技术标签:
【中文标题】Python pandas 通过 dt 访问器有效地将日期时间转换为时间戳【英文标题】:Python pandas convert datetime to timestamp effectively through dt accessor 【发布时间】:2017-04-14 09:26:15 【问题描述】:我有一个包含一些(数亿)行的数据框。我想有效地将日期时间转换为时间戳。我该怎么做?
我的样本df
:
df = pd.DataFrame(index=pd.DatetimeIndex(start=dt.datetime(2016,1,1,0,0,1),
end=dt.datetime(2016,1,2,0,0,1), freq='H'))\
.reset_index().rename(columns='index':'datetime')
df.head()
datetime
0 2016-01-01 00:00:01
1 2016-01-01 01:00:01
2 2016-01-01 02:00:01
3 2016-01-01 03:00:01
4 2016-01-01 04:00:01
现在我使用 .apply()
将日期时间逐个值转换为时间戳值,但如果我有一些(数亿)行,则需要很长时间(几个小时):
df['ts'] = df[['datetime']].apply(lambda x: x[0].timestamp(), axis=1).astype(int)
df.head()
datetime ts
0 2016-01-01 00:00:01 1451602801
1 2016-01-01 01:00:01 1451606401
2 2016-01-01 02:00:01 1451610001
3 2016-01-01 03:00:01 1451613601
4 2016-01-01 04:00:01 1451617201
上面的结果就是我想要的。
如果我尝试使用pandas.Series
的.dt
访问器,则会收到错误消息:
df['ts'] = df['datetime'].dt.timestamp
AttributeError: 'DatetimeProperties' 对象没有属性 '时间戳'
如果我尝试创建例如。使用 .dt
访问器的日期时间的日期部分比使用 .apply()
快得多:
df['date'] = df['datetime'].dt.date
df.head()
datetime ts date
0 2016-01-01 00:00:01 1451602801 2016-01-01
1 2016-01-01 01:00:01 1451606401 2016-01-01
2 2016-01-01 02:00:01 1451610001 2016-01-01
3 2016-01-01 03:00:01 1451613601 2016-01-01
4 2016-01-01 04:00:01 1451617201 2016-01-01
我想要类似时间戳的东西...
但我不太了解官方文档:它谈论“Converting to Timestamps”但我没有看到任何时间戳;它只是谈论使用pd.to_datetime()
转换为日期时间而不是时间戳...
pandas.Timestamp
构造函数也不起作用(返回以下错误):
df['ts2'] = pd.Timestamp(df['datetime'])
TypeError:无法将输入转换为时间戳
pandas.Series.to_timestamp
也做出了我想要的完全不同的东西:
df['ts3'] = df['datetime'].to_timestamp
df.head()
datetime ts ts3
0 2016-01-01 00:00:01 1451602801 <bound method Series.to_timestamp of 0 2016...
1 2016-01-01 01:00:01 1451606401 <bound method Series.to_timestamp of 0 2016...
2 2016-01-01 02:00:01 1451610001 <bound method Series.to_timestamp of 0 2016...
3 2016-01-01 03:00:01 1451613601 <bound method Series.to_timestamp of 0 2016...
4 2016-01-01 04:00:01 1451617201 <bound method Series.to_timestamp of 0 2016...
谢谢!!
【问题讨论】:
【参考方案1】:我认为您需要先通过values
转换为numpy array
并转换为int64
- 输出在ns
,所以需要除以10 ** 9
:
df['ts'] = df.datetime.values.astype(np.int64) // 10 ** 9
print (df)
datetime ts
0 2016-01-01 00:00:01 1451606401
1 2016-01-01 01:00:01 1451610001
2 2016-01-01 02:00:01 1451613601
3 2016-01-01 03:00:01 1451617201
4 2016-01-01 04:00:01 1451620801
5 2016-01-01 05:00:01 1451624401
6 2016-01-01 06:00:01 1451628001
7 2016-01-01 07:00:01 1451631601
8 2016-01-01 08:00:01 1451635201
9 2016-01-01 09:00:01 1451638801
10 2016-01-01 10:00:01 1451642401
11 2016-01-01 11:00:01 1451646001
12 2016-01-01 12:00:01 1451649601
13 2016-01-01 13:00:01 1451653201
14 2016-01-01 14:00:01 1451656801
15 2016-01-01 15:00:01 1451660401
16 2016-01-01 16:00:01 1451664001
17 2016-01-01 17:00:01 1451667601
18 2016-01-01 18:00:01 1451671201
19 2016-01-01 19:00:01 1451674801
20 2016-01-01 20:00:01 1451678401
21 2016-01-01 21:00:01 1451682001
22 2016-01-01 22:00:01 1451685601
23 2016-01-01 23:00:01 1451689201
24 2016-01-02 00:00:01 1451692801
to_timestamp
用于转换from period to datetime index。
【讨论】:
谢谢!它在不到 5 秒的时间内将 datetime 列转换为包含 +3 亿行数据帧的时间戳!!!【参考方案2】:还有另一种方法可以使用DatetimeIndex
的“隐藏”属性asi8
,它创建一个整数时间戳。
pd.DatetimeIndex(df.datetime).asi8
Wes McKinney 在链接 here 的这个切向相关的 *** 问题中提出了建议
【讨论】:
【参考方案3】:如果您不想使用 numpy,可以使用纯 pandas 转换
df['ts'] = pd.to_timedelta(df['datetime'], unit='ns').dt.total_seconds().astype(int)
【讨论】:
将日期时间转换为时间增量不是一个有意义的操作,是吗?【参考方案4】:我认为你不应该使用 apply,
只需astype
就可以了:
df['ts'] = df.datetime.astype('int64') // 10**9
【讨论】:
【参考方案5】:一种选择是使用这样的 lambda 表达式
df['datetime'] = df['datetime'].apply(lambda x: pd.Timestamp(x))
【讨论】:
这很慢,出于同样的原因。 我建议避免申请,因为它实际上是为了循环。尝试使用我在这里提到的矢量熊猫解决方案***.com/a/54429530/1683626【参考方案6】:将 pandas.datetime 转换为 unix 时间戳的最简单方法是:df['datetime'].values.tolist()
【讨论】:
【参考方案7】:另一个option是使用pandas.to_numeric
:
df['datetime'] = pandas.to_numeric(df['datetime'].values) / 10 ** 9
【讨论】:
以上是关于Python pandas 通过 dt 访问器有效地将日期时间转换为时间戳的主要内容,如果未能解决你的问题,请参考以下文章