Python Pandas 时间数据处理与分析:读取、创建与时区转换
本文详细介绍了如何使用 pandas 处理和分析时间数据,包括时间序列的读取与格式化、自定义时间序列的创建、时间运算、特定时间段的数据获取和时区转换。通过 pd.to_datetime()
、pd.date_range()
等方法,开发者可以轻松读取日志或文件中的时间数据,创建自定义时间序列,并对时间进行加减运算。此外,文章还展示了如何利用 tz_localize()
和 tz_convert()
进行时区设置和转换,以便实现多时区数据的管理与分析。图表展示与代码示例直观易懂,适合数据分析的入门学习。
文章目录
引入第三方库
import numpy as np
import pandas as pd
import datetime
import matplotlib.pyplot as plt
import pytz
一 主要功能
pandas 处理时间序列的常用方法
功能描述 | 方法1 | 方法2 | 方法3 |
---|---|---|---|
读时间序列数据 | pd.to_datetime() | - | - |
自建时间序列 | pd.date_range() | - | - |
时间运算 | pd.Timedelta() | dt.dayofyear; dt.dayofweek | dt.weekofyear; dt.weekday |
格式化时间 | dt.strftime() | dt.day_name() | dt.month_name() |
时区 | tz_localize() | tz_convert() | pytz.country_timezones() |
二 时序列数据读取
从日志文件或者其他文件中读取出的时间序列数据通常为 dtype: object
。可以使用 pd.to_datetime()
将其转换为 datetime64
类型。
# 创建示例数据框
df = pd.DataFrame({
"time": ["2022/03/12", "2022/03/13", "2022/03/14"],
"value": [1, 2, 3]
})
print(df)
print("\n\ntime:\n", df["time"])
将时间列 dtype: object
转换为 datetime64
:
# 将时间列从 dtype:object 转换为 datetime64 类型
print(pd.to_datetime(df["time"]))
格式化字符串转换为日期格式
pd.to_datetime()
可以处理格式不统一的日期字符串,并通过 format
参数来指定复杂的自定义格式:
# 转换多种格式的日期字符串
print(pd.to_datetime(
["2022/03/12", "2022.03.13", "14/03/2022"], format='mixed'))
# 自定义格式转换
print(pd.to_datetime(
[
"1@21@2022%%11|11|32",
"12@01@2022%%44|02|2",
"4@01@2022%%14|22|2"
],
format="%m@%d@%Y%%%%%S|%H|%M"))
注:时间格式化字符串 %m
, %d
, %Y
, %%
, %S
, %H
, %M
分别代表月、日、完整的年份、百分号%、秒、小时和分钟。可以随时查阅 Python 官方文档 以了解详细的用法。
三 自定义时间序列数据
可以使用 pd.date_range()
创建自定义时间序列数据
# 创建时间范围
start = datetime.datetime(2022, 3, 12)
end = datetime.datetime(2022, 3, 18)
index = pd.date_range(start, end)
print(index)
Python 中 range()
可以控制步长,类似地,pandas 中的 pd.date_range()
也支持通过 freq
参数来控制时间间隔:
# range 和 pd.date_range 示例
print("range(1, 10, 2)\n", list(range(1, 10, 2)))
print("\n\npd.date_range()\n", pd.date_range(start, end, freq="48h"))
Numpy 中 np.linspace()
可以在区间内均匀分割数据,类似地,pandas 中pd.date_range()
可以使用 periods
参数创建指定周期的数据:
# np.linspace 和 pd.date_range 示例
print("np.linspace(-1, 1, 5)\n", np.linspace(-1, 1, 5))
print("\n\nPd.date_range with periods\n", pd.date_range(start, end, periods=5))
四 时间序列数据获取
# 创建时间序列数据
start = datetime.datetime(2022, 3, 1)
end = datetime.datetime(2022, 5, 3)
rng = pd.date_range(start, end)
ts = pd.Series(np.random.randn(len(rng)), index=rng)
print(ts)
print(ts.index)
print(ts.plot())
plt.show()
时间分片可以用于获取特定时间段的数据,例如获取一周内的数据:
# 获取一周内的时间序列数据
ts[1:8].plot()
plt.show()
还可以通过指定时间范围获取时间片段:
# 获取特定时间范围的数据
t1 = datetime.datetime(2022, 3, 12)
t2 = datetime.datetime(2022, 3, 18)
# ts[t1: t2].plot()
# plt.show()
ts["2022-03-12": "2022-03-18"].plot()
plt.show()
按月获取数据:
# 获取特定月份的数据
ts["2022-03"].plot()
plt.show()
五 时间运算
时间序列数据支持时间运算,可以加减时间段(pd.Timedelta()
):
# 时间运算示例
rng = pd.date_range("2022-01-01", "2022-01-07")
print(rng + pd.Timedelta(weeks=1))
print(rng + 2 * pd.Timedelta(days=3))
rng = pd.date_range("2022-01-08", "2022-01-11")
print(rng.dayofyear)
# 格式化时间输出
print(rng.strftime("%m/%d/%Y"))
六 时区处理
处理时间序列数据时,可以使用 tz_localize()
和 tz_convert()
进行时区设置和转换:
# 时区处理示例
rng = pd.date_range("2022-01-08", "2022-01-11")
print(rng.tz is None)
# 将时间序列数据本地化为特定时区
s = pd.to_datetime(["2022/03/12 22:11", "2022/03/12 12:11", "2022/03/12 2:11"])
s_us = s.tz_localize("America/New_York")
print(s_us)
# 转换到其他时区
s_cn = s_us.tz_convert("Asia/Shanghai")
print(s_cn)
# 查看中国的所有时区
print(pytz.country_timezones('CN'))
# 创建包含时区的时间序列
rng = pd.date_range("2022-01-08", "2022-01-11", tz="America/New_York")
print(rng)
七 完整代码示例
# This is a sample Python script.
# Press ⌃R to execute it or replace it with your code.
# Press Double ⇧ to search everywhere for classes, files, tool windows, actions, and settings.
import numpy as np
import pandas as pd
import datetime
import matplotlib.pyplot as plt
import pytz
def print_hi(name):
# Use a breakpoint in the code line below to debug your script.
print(f'Hi, {name}') # Press ⌘F8 to toggle the breakpoint.
# 读时间序列数据
df = pd.DataFrame({
"time": ["2022/03/12", "2022/03/13", "2022/03/14"],
"value": [1, 2, 3]
})
print(df)
print("\n\ntime:\n", df["time"])
# dtype:object
# 转成 datetime64
print(pd.to_datetime(df["time"]))
print(pd.to_datetime(
["2022/03/12", "2022.03.13", "14/03/2022"], format='mixed'))
print(pd.to_datetime(
[
"1@21@2022%%11|11|32",
"12@01@2022%%44|02|2",
"4@01@2022%%14|22|2"
],
format="%m@%d@%Y%%%%%S|%H|%M"))
# https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior
# %m 月
# %d 日
# %Y 年的全称
# %% 比配一个 %
# %S 秒
# %H 时
# %M 分
# 自建时间序列
start = datetime.datetime(2022, 3, 12)
end = datetime.datetime(2022, 3, 18)
index = pd.date_range(start, end)
print(index)
print(
"range(1, 10, 2)\n",
list(range(1, 10, 2))
)
print(
"\n\npd.date_range()\n",
pd.date_range(start, end, freq="48h")
)
print(
"np.linspace(-1, 1, 5)\n",
np.linspace(-1, 1, 5)
)
# 均匀分布
print(
"\n\npd.date_range(start, end, periods=5)\n",
pd.date_range(start, end, periods=5)
)
# 选取时间
start = datetime.datetime(2022, 3, 1)
end = datetime.datetime(2022, 5, 3)
rng = pd.date_range(start, end)
ts = pd.Series(np.random.randn(len(rng)), index=rng)
print()
print(ts)
print()
print(ts.index)
print(ts.plot())
plt.show()
# 显示某一周时间数据
ts[1:8].plot()
plt.show()
# 时间本身分片
t1 = datetime.datetime(2022, 3, 12)
t2 = datetime.datetime(2022, 3, 18)
ts[t1: t2].plot()
plt.show()
ts["2022-03-12": "2022-03-18"].plot()
plt.show()
# 按月按年取
ts["2022-03"].plot()
plt.show()
print()
# 时间运算
# 加一周
rng = pd.date_range("2022-01-01", "2022-01-07")
print(rng + pd.Timedelta(weeks=1))
print(rng + 2 * pd.Timedelta(days=3))
rng = pd.date_range("2022-04-08", "2022-04-11")
print(rng.dayofyear)
print(rng.strftime("%m/%d/%Y"))
# https://pandas.pydata.org/docs/reference/arrays.html#datetime-data
# 时区
rng = pd.date_range("2022-01-08", "2022-01-11")
print(rng.tz is None)
s = pd.to_datetime(
["2022/03/12 22:11", "2022/03/12 12:11", "2022/03/12 2:11"]
)
s_us = s.tz_localize("America/New_York")
print(s_us)
s_cn = s_us.tz_convert("Asia/Shanghai")
print(s_cn)
print(pytz.country_timezones('CN'))
rng = pd.date_range(
"2022-01-08", "2022-01-11",
tz="America/New_York")
print(rng)
# https://pandas.pydata.org/docs/user_guide/timeseries.html
# Press the green button in the gutter to run the script.
if __name__ == '__main__':
print_hi('时间数据')
# See PyCharm help at https://www.jetbrains.com/help/pycharm/
复制粘贴并覆盖到你的 main.py 中运行,运行结果如下。
Hi, 时间数据
time value
0 2022/03/12 1
1 2022/03/13 2
2 2022/03/14 3
time:
0 2022/03/12
1 2022/03/13
2 2022/03/14
Name: time, dtype: object
0 2022-03-12
1 2022-03-13
2 2022-03-14
Name: time, dtype: datetime64[ns]
DatetimeIndex(['2022-03-12', '2022-03-13', '2022-03-14'], dtype='datetime64[ns]', freq=None)
DatetimeIndex(['2022-01-21 11:32:11', '2022-12-01 02:02:44',
'2022-04-01 22:02:14'],
dtype='datetime64[ns]', freq=None)
DatetimeIndex(['2022-03-12', '2022-03-13', '2022-03-14', '2022-03-15',
'2022-03-16', '2022-03-17', '2022-03-18'],
dtype='datetime64[ns]', freq='D')
range(1, 10, 2)
[1, 3, 5, 7, 9]
pd.date_range()
DatetimeIndex(['2022-03-12', '2022-03-14', '2022-03-16', '2022-03-18'], dtype='datetime64[ns]', freq='48h')
np.linspace(-1, 1, 5)
[-1. -0.5 0. 0.5 1. ]
pd.date_range(start, end, periods=5)
DatetimeIndex(['2022-03-12 00:00:00', '2022-03-13 12:00:00',
'2022-03-15 00:00:00', '2022-03-16 12:00:00',
'2022-03-18 00:00:00'],
dtype='datetime64[ns]', freq=None)
2022-03-01 1.481681
2022-03-02 -0.702829
2022-03-03 1.056303
2022-03-04 -0.466668
2022-03-05 1.025660
...
2022-04-29 -0.546073
2022-04-30 0.621919
2022-05-01 -3.192217
2022-05-02 1.493657
2022-05-03 1.082105
Freq: D, Length: 64, dtype: float64
DatetimeIndex(['2022-03-01', '2022-03-02', '2022-03-03', '2022-03-04',
'2022-03-05', '2022-03-06', '2022-03-07', '2022-03-08',
'2022-03-09', '2022-03-10', '2022-03-11', '2022-03-12',
'2022-03-13', '2022-03-14', '2022-03-15', '2022-03-16',
'2022-03-17', '2022-03-18', '2022-03-19', '2022-03-20',
'2022-03-21', '2022-03-22', '2022-03-23', '2022-03-24',
'2022-03-25', '2022-03-26', '2022-03-27', '2022-03-28',
'2022-03-29', '2022-03-30', '2022-03-31', '2022-04-01',
'2022-04-02', '2022-04-03', '2022-04-04', '2022-04-05',
'2022-04-06', '2022-04-07', '2022-04-08', '2022-04-09',
'2022-04-10', '2022-04-11', '2022-04-12', '2022-04-13',
'2022-04-14', '2022-04-15', '2022-04-16', '2022-04-17',
'2022-04-18', '2022-04-19', '2022-04-20', '2022-04-21',
'2022-04-22', '2022-04-23', '2022-04-24', '2022-04-25',
'2022-04-26', '2022-04-27', '2022-04-28', '2022-04-29',
'2022-04-30', '2022-05-01', '2022-05-02', '2022-05-03'],
dtype='datetime64[ns]', freq='D')
Axes(0.125,0.11;0.775x0.77)
DatetimeIndex(['2022-01-08', '2022-01-09', '2022-01-10', '2022-01-11',
'2022-01-12', '2022-01-13', '2022-01-14'],
dtype='datetime64[ns]', freq='D')
DatetimeIndex(['2022-01-07', '2022-01-08', '2022-01-09', '2022-01-10',
'2022-01-11', '2022-01-12', '2022-01-13'],
dtype='datetime64[ns]', freq='D')
Index([98, 99, 100, 101], dtype='int32')
Index(['04/08/2022', '04/09/2022', '04/10/2022', '04/11/2022'], dtype='object')
True
DatetimeIndex(['2022-03-12 22:11:00-05:00', '2022-03-12 12:11:00-05:00',
'2022-03-12 02:11:00-05:00'],
dtype='datetime64[ns, America/New_York]', freq=None)
DatetimeIndex(['2022-03-13 11:11:00+08:00', '2022-03-13 01:11:00+08:00',
'2022-03-12 15:11:00+08:00'],
dtype='datetime64[ns, Asia/Shanghai]', freq=None)
['Asia/Shanghai', 'Asia/Urumqi']
DatetimeIndex(['2022-01-08 00:00:00-05:00', '2022-01-09 00:00:00-05:00',
'2022-01-10 00:00:00-05:00', '2022-01-11 00:00:00-05:00'],
dtype='datetime64[ns, America/New_York]', freq='D')
八 源码地址
代码地址:
国内看 Gitee 之 pandas/时间数据.py
国外看 GitHub 之 pandas/时间数据.py
引用 莫烦 Python