在前几篇关于 pandas 的文章中,笔者分别介绍了:
本篇介绍 Pandas 中关于日期时间的数据类型及其处理方法。在一个数据表中经常会出现年月日、某季度、星期几等关于日期和几点几分等关于时间的数据列,而且会出现在索引中,经常会拿日期/时间做分组聚合,或者排序、做差、采样等等操作,这就要对日期时间类型数据进行处理。如果原始数据是字符串表示的,可能要先把它转化成特定的日期时间类型,方便后续处理。
在 Python 中自带了 time库 和 datetime库,是处理日期时间数据的好工具,可以拿来 pandas 中使用。Pandas 提供了表示时间戳、时间段、时间间隔等三种与时间有关的类型,以及元素为这些类型的索引对象,还提供了许多与时间序列相关的函数。本篇先介绍python的time、datetime库和pandas时间戳,时间段和时间索引对象及其操作留待下一篇。
在 Python 内置的 time 库中以 time.struct_time 类型存储时间数据;而 datetime 库中以 datetime.time 类型存储时间数据,以 datetime.date 类型存储日期数据,以 datetime.datetime 类型存储时间日期数据,以 datetime.timedelta 类型存储时间差。常用方法如下:
import time
import datetime
time.time() # Unix 时间戳,返回从1970年以来的秒数
time.ctime() # 获取当前日期和时间,返回一个字符串,如:'Mon Nov 7 08:06:03 2022'
time.localtime() # 获取当前日期和时间,返回一个 struct_time 对象
time.strptime('2013-12-5 12:23:09', '%Y-%m-%d %H:%M:%S') # 把字符串形式的日期时间转换成 struct_time 形式
time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) # 格式化输出当前时间
t1 = datetime.time(12, 24, 45) # 用数值初始化获得 datetime.time 类型时间
t1.hour, t1.minute, t1.second # datetime.time 类的 hour、minute、second 属性
t1.isoformat() # 返回时间字符串形式:'12:24:45'
t1.strftime('%H:%M:%S') # 格式化输出 t1 时间
t2 = datetime.date(2022,10,31) # 用数值初始化获得 datetime.date 类型日期
t2 = datetime.date.fromisoformat('2022-01-13') # 从字符串获得 datetime.date 类型日期
t2 = datetime.date.fromtimestamp(time.time()) # 从时间戳获得 datetime.date 类型日期
t2.year, t2.month, t2.day # datetime.date 类的年月日属性
t2.isoweekday() # t2 的星期(返回1~6表示星期一~六,返回7表示星期日)
t2.strftime('%Y-%m-%d') # 格式化输出 datetime.date 对象
datetime.date.today() # 获取当前日期,返回一个 datetime.date 类型
t2 < datetime.date.today() # t2 日期是否比当前日期早,返回布尔值
t3 = datetime.datetime(2021, 5, 7, 8, 9, 17) # 用数值初始化获得 datetime.datetime 类型日期时间
t3 = datetime.datetime.strptime('2021-05-07 12:09:10', '%Y-%m-%d %H:%M:%S') # 从字符串中创建 datetime
t3 = datetime.datetime.combine(t2, t1) # 从 date 和 time 对象中创建 datetime
t3 = datetime.datetime.fromtimestamp(time.time()) # 根据时间戳创建时间日期
t3.year, t3.month, t3.day, t3.hour, t3.minute, t3.second # datetime.datetime 类的年月日时分秒属性
t3.date() # t3 中的日期,返回一个 datetime.date 对象
t3.time() # t3 中的时间,返回一个 datetime.time 对象
t3.isoweekday() # t3 的星期(返回1~6表示星期一~六,返回7表示星期日)
t3.strftime('%Y-%m-%d %H:%M:%S')# 格式化输出 datetime.datetime 对象
datetime.datetime.today() # 获取当前日期和时间,返回一个 datetime.datetime 类型
datetime.datetime.now() # 同上
t3 > datetime.datetime.now() # t3 时间是否比当前时间晚,返回布尔值
dt1 = datetime.date(2011,1,5) - datetime.date(2009,2,19) # 计算日期天数差值,返回一个 datetime.timedelta 类型
dt1.days # 返回相差的天数
datetime.date.today() + datetime.timedelta(55) # 计算当前日期55天之后的日期
dt2 = datetime.datetime(2023,1,1,0,0,0) - datetime.datetime.now() # 计算2023年元旦距今还有多长时间,返回 timedelta 类型
dt2.days, dt2.seconds, dt2.microseconds # 返回相差的天数、秒数和毫秒数
dt2.total_seconds() # 返回相差的总的秒数
datetime.datetime.today() - datetime.timedelta(days=7, hours=12, minutes=30) # 计算当前时间下7天又12小时30分钟前的时间
对日期时间常用的格式化字符串有:
在 Pandas 中处理日期时间序列经常用到的类型是 Timestamp 时间戳,它既可以转换成上面介绍的 datetime.datetime 类型,也可以转换成 numpy.datetime64 类型,其创建方法如下。对 DataFrame 数据进行处理时,既可以使用这两个函数,也可以使用 astype 函数直接进行转换成 datetime64 类型。
pd.Timestamp(ts_input, freq, tz, unit, year, month, day, hour, minute, second, microsecond, tzinfo, offset)
ts_input:一个 datetime-like/str/int/float,被转换成 Timestamp
freq:一个字符串或者 DateOffset,给出了偏移量
tz:一个字符串或者pytz.timezone对象,给出了时区
unit:一个字符串。当 ts_input 为整数或者浮点数时,给出转换单位
其他参数来自 datetime.datetime
pd.to_datetime(arg, errors='raise', dayfirst=False, yearfirst=False, utc, format, exact=True, unit, infer_datetime_format=False, origin='unix', cache=True)
arg:可转换为时间戳的字符串等数据
errors:为’raise’时,传入数据格式不符合会报错;为’ignore’时,忽略报错返回原数据
dayfirst:表示传入数据的前两位数是天,如:‘030820’ 代表 2020-03-08
yearfirst:表示传入数据的前两位数为年份,如:‘030820’ 代表 2003-08-20
format:自定义输出格式,如“%Y-%m-%d”.
unit:单位,可以为[‘D’, ‘h’ ,‘m’, ‘ms’ ,‘s’, ‘ns’]
infer_datetime_format:加速计算
origin:自定义开始时间,默认为1990-01-01
返回一个 DatetimeIndex / Series / DatetimeScalar / NaTType / None。
示例如下:
import numpy as np
import pandas as pd
t4 = pd.Timestamp('2021-05-07 08:09:17') # 创建一个 Timestamp 时间戳对象
t4 = pd.to_datetime('2021-05-07 08:09:17', format='%Y-%m-%d %H:%M:%S') # 同上
t4.year, t4.month, t4.day, t4.hour, t4.minute, t4.second, t4.quarter, t4.dayofweek # 获取时间戳对象的年月日等属性
t4.day_name() # 获取星期全称,如:'Monday'
t4.to_pydatetime() # 转换成 datetime.datetime 类型
t4.to_datetime64() # 转换成 numpy.datetime64 类型
t4 - datetime.timedelta(days=1, hours=6, minutes=30) # t4 时间基础上减去1天又6小时30分,返回新的 Timestamp
df = pd.DataFrame({'date':['2022-01-20','2021-03-21','2020-11-09'],
'datetime':['2022-01-20 12:10:21','2021-03-21 09:36:09','2020-11-09 23:45:01'],
'time':['12:10:21','09:36:09','23:45:01']})
pd.to_datetime(df['date'], format='%Y-%m-%d') # 返回 numpy.datetime64 类型的 Series
pd.to_datetime(df['datetime'], format='%Y-%m-%d %H:%M:%S') # 返回同上
df['date'].astype('datetime64') # 直接用 astype 函数进行类型转换,返回 numpy.datetime64 类型的 Series
x = df['datetime'].astype('datetime64').dt # 获得日期时间的 DatetimeProperties 类型
x.year, x.month, x.day, x.hour, x.minute, x.second # 分别获取 'date' 列的年、月、日、时、分、秒数据
x.date, x.time, x.dayofweek # 分别获取 'date' 列的日期、时间、星期数据
df['datetime'].astype('datetime64[Y]') # 转换成 datetime64[Y] 类型,仅保留年份
df['datetime'].astype('datetime64[M]') # 同上,仅保留年、月
df['datetime'].astype('datetime64[D]') # 同上,仅保留年、月、日
df['datetime'].astype('datetime64[h]') # 同上,仅保留年、月、日、时
df['datetime'].astype('datetime64[m]') # 同上,仅保留年、月、日、时、分
df['datetime'].astype('datetime64[s]') # 同上,仅保留年、月、日、时、分、秒
# 在 'datetime' 列的时间上加7天12小时30分,返回一个新的'datetime64'型Series:
df['datetime'].astype('datetime64') + datetime.timedelta(days=7, hours=12, minutes=30)
# 'datetime' 列与 'date' 列相差的天数,返回一整型Series:
(df['datetime'].astype('datetime64') - df['date'].astype('datetime64')).dt.days
# 判断 'datetime' 列日期时间是否比 t4 日期时间大,返回一布尔型Series:
df['datetime'].astype('datetime64') > t4
以上。