pandas 在Python中将日期时间列转换为纪元

zpqajqem  于 2022-11-27  发布在  Python
关注(0)|答案(5)|浏览(137)

我目前在使用Python时遇到了一个问题。我有一个Pandas DataFrame,其中一列是一个带日期的字符串。格式为:
“%Y-%m-%d %H:%m:00.000”。例如:“2011年4月24日01:30:00.000”
我需要将整个列转换为整数。我试着运行这段代码,但它非常慢,而且我有几百万行。

for i in range(calls.shape[0]):
    calls['dateint'][i] = int(time.mktime(time.strptime(calls.DATE[i], "%Y-%m-%d %H:%M:00.000")))

你们知道怎么把整列时间换算成纪元时间吗?

vhmi4jdf

vhmi4jdf1#

使用to_datetime将字符串转换为datetime,然后减去日期时间1970-1-1,并调用dt.total_seconds()

In [2]:
import pandas as pd
import datetime as dt
df = pd.DataFrame({'date':['2011-04-24 01:30:00.000']})
df

Out[2]:
                      date
0  2011-04-24 01:30:00.000

In [3]:
df['date'] = pd.to_datetime(df['date'])
df

Out[3]:
                 date
0 2011-04-24 01:30:00

In [6]:    
(df['date'] - dt.datetime(1970,1,1)).dt.total_seconds()

Out[6]:
0    1303608600
Name: date, dtype: float64

您可以看到,将此值转换回来会产生相同的时间:

In [8]:
pd.to_datetime(1303608600, unit='s')

Out[8]:
Timestamp('2011-04-24 01:30:00')

因此,您可以添加新列或覆盖:

In [9]:
df['epoch'] = (df['date'] - dt.datetime(1970,1,1)).dt.total_seconds()
df

Out[9]:
                 date       epoch
0 2011-04-24 01:30:00  1303608600

编辑

更好的方法是@Jeff:

In [3]:
df['date'].astype('int64')//1e9

Out[3]:
0    1303608600
Name: date, dtype: float64

In [4]:
%timeit (df['date'] - dt.datetime(1970,1,1)).dt.total_seconds()
%timeit df['date'].astype('int64')//1e9

100 loops, best of 3: 1.72 ms per loop
1000 loops, best of 3: 275 µs per loop

您还可以看到,它的速度明显加快

zyfwsgd6

zyfwsgd62#

我知道这是旧的,但我相信正确的(和最干净的)方式是下面的一行:

calls['DATE'].apply(lambda x: x.timestamp())

假设calls['DATE']datetime64[ns]类型。如果不是,请转换为:

pd.to_datetime(calls['DATE'], format="%Y-%m-%d %H:%m:00.000")

说明

要获取pd.Timestamp的历元值(以秒为单位),请用途:

pd.Timestamp('20200101').timestamp()

这应该会给予你1577836800.0。如果你愿意的话,你可以转换成int。它是浮点的原因是因为任何亚秒的时间都会在小数部分。
您还可以获取原始纪元值(单位为纳秒):

pd.Timestamp('20200101').value

给出1577836800000000000,它是上述日期的epoch。.value属性是epoch之后的纳秒数,因此除以1e6可得到毫秒。如果希望epoch以秒为单位作为第一次调用,则除以1e9。

vojdkbi0

vojdkbi03#

从Pandas关于处理时间序列数据的文档中:
我们减去历元(1970年1月1日的午夜UTC),然后将下限除以“单位”(1毫秒)。

# generate some timestamps
stamps = pd.date_range('2012-10-08 18:15:05', periods=4, freq='D')

# convert it to milliseconds from epoch
(stamps - pd.Timestamp("1970-01-01")) // pd.Timedelta('1ms')

这将给予以毫秒为单位的历元时间。

5cnsuln7

5cnsuln74#

为了扩展s5s的答案,我认为代码可以进一步推广以满足缺失的数据(例如,用pd.NaT表示)。在Pandas 1.2.4上测试,在Pandas〈1.0上不起作用。

calls['DATE'].apply(lambda x: x.timestamp() if not pd.isna(x) else pd.NA).astype('Int64')

一些评论:

  • pd.isna()将捕获pd.NaT
  • lambda表达式将pd.NaT转换为pd.NA,这将是缺失数据的新表示形式
  • 最后,lambda表达式的输出将是整数和pd.NA的混合,因此我们需要一个Pandas ExtensionDtype(如Int64)来处理它

示例输出:

0            <NA>
1            <NA>
2            <NA>
3            <NA>
4            <NA>
          ...
865    1619136000
866    1619136000
          ...
Name: DATE, Length: 870, dtype: Int64
dy1byipe

dy1byipe5#

另一种方法是,在减去Unix epoch之后,将dtype转换为'timedelta64[s]'(注意[s])以指定您希望差值以秒为单位,或者将dtype转换为'timedelta[ms]'以指定它应该以毫秒为单位,等等。

df['epoch'] = df['date'].sub(pd.Timestamp('1970-01-01')).astype('timedelta64[s]')

相关问题