时间序列
在数据处理过程中,难免会遇到日期格式,特别是从外部读取数据到jupyter或其他python编译器中,用于数据处理分析时。若读取excel文档时还能保留原本日期时间格式,但有时却差强人意,读取后为字符串格式,尤其是以csv格式存储的数据。此时就需要用到字符串转日期格式。
这里介绍比较常用的字符串与日期格式互转的方法,是属于时间序列中部分内容。
datetime.datetime
datetime以毫秒形式存储日期和时间。
Python标准库包含用于日期(date)和时间(time)数据的数据类型,而且还有日历方面的功能。主要会用到datetime、time以及calendar模块。datetime.datetime(也可以简写为datetime)是用得最多的数据类型。
>>> from datetime import datetime>>> now = datetime.now()>>> nowdatetime.datetime(2020, 2, 6, 19, 15, 6, 617163)>>> now.year2020>>> now.month2>>> now.day6
timedelta
timedelta表示两个datetime对象之间的时间差
>>> delta = datetime.now() - datetime(2016, 4, 3)>>> deltadatetime.timedelta(days=1404, seconds=69929, microseconds=636512)>>> delta.days1404
可以给datetime对象加上(或减去)一个或多个timedelta,这样会产生一个新对象
>>> from datetime import timedelta>>> start = datetime(2016,4,3)>>> start + timedelta(1404)datetime.datetime(2020, 2, 6, 0, 0)>>> start - 2* timedelta(1404)datetime.datetime(2008, 7, 26, 0, 0)
datetime模块中的数据类型
| 类型 | 说明 |
|---|---|
| date | 以公历形式存储日期(年、月、日) |
| time | 将时间存储为时、分、秒、毫秒 |
| datetime | 存储日期和时间日、秒、毫秒 |
| timedelta | 表示两个datetime 值之间的差 |
datetime 转换为字符串
datetime.strftime()
利用str或strftime方法(传入一个格式化字符串),datetime对象和pandas的Timestamp对象可以被格式化为字符串:
>>> tamp = datetime(2020,5,20)>>> str(tamp)'2020-05-20 00:00:00'>>> tamp.strftime('%Y-%m-%d')'2020-05-20'>>> datetime.strftime(tamp, '%Y-%m-%d')'2020-05-20'
datetime格式定义(兼容ISO C89)
| 代码 | 说明 |
|---|---|
| %Y | 4位数的年 |
| %y | 2位数的年 |
| %m | 2位数的月 [01,12] |
| %d | 2位数的日 [01, 31] |
| %H | 时(24小时制) [00, 23] |
| %I | 时(12小时制) [01, 12] |
| %M | 2位数的分[00, 59] |
| %S | 秒[0,61] (秒60和61用于闰秒) |
| %w | 用整数表示的星期几 [0(星期天), 6] |
| %U | 每年的第几周[00, 53]。星期天被认为是每周的第一天,每年第一个星期天之前的那几天被认为是”第0周” |
| %W | 每年的第几周[00, 53]。星期一被认为是每周的第一天,每年第一个星期一之前的那几天被认为是”第0周” |
| %z | 以+HHMM或-HHMM表示UTC的时区偏移量,如果时区为naive,则返回空字符串 |
| %F | %Y-%m-%d 简写形式,例如 2020-05-25 |
| %D | %m/%d/%y 简写形式,例如 05/25/20 |
格式化编码将字符串转换为 datetime
datetime.strptime()
>>> value = '2020-05-20'>>> datetime.strptime(value,'%Y-%m-%d')datetime.datetime(2020, 5, 20, 0, 0)
dateutil.parser.parse
datetime.strptime()是通过已知格式进行日期解析的最佳方式。但是每次都要编写格式定义是很麻烦的事情,尤其是对于一些常见的日期格式。这种情况下,可以用dateutil这个第三方包中的parser.parse方法(pandas中已经自动安装好了):
>>> from dateutil.parser import parse>>> parse('2020-02-06')datetime.datetime(2020, 2, 6, 0, 0)
dateutil可以解析几乎所有人类能够理解的日期表示形式
>>> parse('Jan 31, 1997 10:45 PM')datetime.datetime(1997, 1, 31, 22, 45)
在国际通用的格式中,日出现在月的前面很普遍,传入**dayfirst=True**即可解决这个 问题:
>>> a = parse('02/06/2020',dayfirst = True)>>> print(a)2020-06-02 00:00:00>>> a = parse('02/06/2020')>>> print(a)2020-02-06 00:00:00
pandas.to_datetime() —转换成DatetimeIndex
pandas通常是用于处理成组日期的,不管这些日期是DataFrame的轴索引还是列。to_datetime方法可以解析多种不同的日期表示形式。对标准日期格式(如ISO8601)的解析非常快:
>>> import pandas as pd>>> datestrs = ['2011-07-06 12:00:00', '2011-08-06 00:00:00']>>> pd.to_datetime(datestrs)DatetimeIndex(['2011-07-06 12:00:00', '2011-08-06 00:00:00'], dtype='datetime64[ns]', freq=None)
它还可以处理缺失值(None、空字符串等)
>>> import numpy as np>>> idx = datestrs + [np.nan]>>> pd.to_datetime(idx) # NaT(Not a Time)是pandas中时间戳数据的null值。DatetimeIndex(['2011-07-06 12:00:00', '2011-08-06 00:00:00', 'NaT'], dtype='datetime64[ns]', freq=None)
注意:dateutil.parser是一个实用但不完美的工具。比如说,它会把一些原本不是日期的字符串认作是日期(比如”42”会被解析为2042年的今天)。
NaT(Not a Time)是pandas中时间戳数据的null值。
pandas Timestamp 转 datetime
利用str或datetime.strftime()方法(传入一个格式化字符串),可将datetime对象和pandas的Timestamp对象可以被格式化为字符串。也知道了将字符串转化为datetime对象。
在数据处理过程中,特别是在处理时间序列过程中,常常会出现pandas._libs.tslibs.timestamps.Timestamp格式的日期类型,这与希望的datetime.datetime格式的日期格式不相同。
to_pydatetime()方法转化
转换直接创建的pd.Timestamp对象
>>> ts = pd.Timestamp('2020-05-20 00:00:00', tz=None)>>> type(ts)pandas._libs.tslibs.timestamps.Timestamp>>> ts.to_pydatetime()datetime.datetime(2020, 5, 20, 0, 0)>>> type(ts.to_pydatetime())datetime.datetime
转换由 pandas.to_datetime() 生成的 DatetimeIndex 的单个元素
>>> datestrs = ['2011-07-06 12:00:00', '2011-08-06 00:00:00']>>> pd.to_datetime(datestrs)DatetimeIndex(['2011-07-06 12:00:00', '2011-08-06 00:00:00'], dtype='datetime64[ns]', freq=None)>>> type(pd.to_datetime(datestrs))pandas.core.indexes.datetimes.DatetimeIndex# 取其中一个元素>>> pd.to_datetime(datestrs)[0]Timestamp('2011-07-06 12:00:00')>>> type(pd.to_datetime(datestrs)[0])pandas._libs.tslibs.timestamps.Timestamp>>> ts = pd.to_datetime(datestrs)[0]>>> ts.to_pydatetime()datetime.datetime(2011, 7, 6, 12, 0)
直接将DatetimeIndex整体转换
>>> rng = pd.date_range('20/05/2020', periods=3, freq='D')>>> rngDatetimeIndex(['2020-05-20', '2020-05-21', '2020-05-22'], dtype='datetime64[ns]', freq='D')>>> rng.to_pydatetime()array([datetime.datetime(2020, 5, 20, 0, 0),datetime.datetime(2020, 5, 21, 0, 0),datetime.datetime(2020, 5, 22, 0, 0)], dtype=object)
time 与日期互转
字符串转time类型
>>> import time>>> timestr = "2020-05-25">>> t = time.strptime(timestr, "%Y-%m-%d")>>> ttime.struct_time(tm_year=2020, tm_mon=5, tm_mday=25, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=0, tm_yday=146, tm_isdst=-1)>>> type(t)time.struct_time
time类型与datetime类型的转换
还是需要datetime模块将其转换为日期格式
>>> from datetime import datetime>>> y,m,d = t[0:3]>>> datetime(y,m,d)datetime.datetime(2020, 5, 20, 0, 0)>>> print(datetime(y,m,d))2020-05-20 00:00:00
time类型转字符串
>>> time.strftime("%Y-%m-%d %X", time.localtime())'2020-5-20 20:05:20'
time格式定义
| 代码 | 说明 |
|---|---|
| %a | 星期几的简写 Weekday name, abbr. |
| %A | 星期几的全称 Weekday name, full |
| %b | 月分的简写 Month name, abbr |
| %B | 月份的全称 Month name, full |
| %c | 标准的日期的时间串 Complete date and time representation |
| %d | 十进制表示的每月的第几天 Day of the month |
| %H | 24小时制的小时 Hour (24-hour clock) |
| %I | 12小时制的小时 Hour (12-hour clock) |
| %j | 十进制表示的每年的第几天 Day of the year |
| %m | 十进制表示的月份 Month number |
| %M | 十时制表示的分钟数 Minute number |
| %S | 十进制的秒数 Second number |
| %U | 第年的第几周,把星期日做为第一天(值从0到53)Week number (Sunday first weekday) |
| %w | 十进制表示的星期几(值从0到6,星期天为0)weekday number |
| %W | 每年的第几周,把星期一做为第一天(值从0到53) Week number (Monday first weekday) |
| %x | 标准的日期串 Complete date representation (e.g. 13/01/08) |
| %X | 标准的时间串 Complete time representation (e.g. 17:02:10) |
| %y | 不带世纪的十进制年份(值从0到99)Year number within century |
| %Y | 带世纪部分的十制年份 Year number |
| %z,%Z | 时区名称,如果不能得到时区名称则返回空字符。Name of time zone |
