3.6 时间数据的处理

Timestamp 是 pandas 对 datetime64 数据类型的一个封装。datetime64 是 NumPy 中的一种数据类型,用于表示日期和时间,而 pandas 基于 datetime64 构建了 Timestamp 类,以便更方便地在 pandas 的数据结构(如 DataFrame 和 Series)中处理日期时间数据。当 pd.to_datetime 接收单个日期时间值时,会返回 Timestamp 对象

1. 时间戳timestamp

d = pd.Timestamp( “2015-05-01 09:08:07.123456” )
# 属性
print(‘年:’,d.year)
print(‘月:’,d.month)
print(‘日:’,d.day)
print(‘小时:’,d.hour)
print(‘分钟:’,d.minute)
print(‘秒:’,d.second)
print(‘微秒:’,d.microsecond)
print(‘季度:’,d.quarter)
print(‘是否是月底:’,d.is_month_end)
print(‘是否是月初:’,d.is_month_start)
print(‘是否是年底:’,d.is_year_end)
print(‘是否是年初:’,d.is_year_start)
# 方法
print(‘星期几:’,d.day_name())
print(‘转换为年度:’,d.to_period(“Y”))
print(‘转换为季度:’,d.to_period(“Q”))
print(‘转换为月度:’,d.to_period(“M”))
print(‘转换为季度:’,d.to_period(“Q”))
print(‘转换为周维度:’,d.to_period(“W”))

to_period()获取统计周期

freq:这是 to_period() 方法最重要的参数,用于指定要转换的时间周期频率

常见的取值如下:

  • “D”:按天周期,例如 2024-01-01 会转换为 2024-01-01 这个天的周期。
  • “W”:按周周期,通常以周日作为一周的结束,比如日期落在某一周内,就会转换为该周的周期表示。
  • “M”:按月周期,像 2024-05-15 会转换为 2024-05。
  • “Q”:按季度周期,一年分为四个季度,日期会转换到对应的季度周期,例如 2024Q2 。
  • “A” 或 “Y”:按年周期,如 2024-07-20 会转换为 2024 。

2.  日期数据转换

# 字符串字段转换为日期类型
a = pd.to_datetime('2025-07-01')
a = pd.to_datetime('20250409')
a = pd.to_datetime('2025/04/13')
a = pd.to_datetime('2025-07')
print(a)
print(type(a))

# dateFrame中的日期转换
df = pd.DataFrame({
    'sales':[100,50,40],
    'date':['2025-01-01','2023-03-02','2025-03-09']
})
df['datetime'] = pd.to_datetime(df['date'])
print(type(df['datetime'].dt))
df['datetime'].dt.day_name()
# 导入数据日期的处理
  df   =   pd  .  read_csv  (  "data/weather.csv"  )
  print  (  df  [  "date"  ].  tail  ())
  # 1456    2015-12-27
  # 1457    2015-12-28
  # 1458    2015-12-29
  # 1459    2015-12-30
  # 1460    2015-12-31
  # Name: date, dtype: object
  print  (  pd  .  to_datetime  (  df  [  "date"  ]).  tail  ())
  # 1456   2015-12-27
  # 1457   2015-12-28
  # 1458   2015-12-29
  # 1459   2015-12-30
  # 1460   2015-12-31
  # Name: date, dtype: datetime64[ns]
  # 在加载数据时也可以通过parse_dates参数将指定列解析为datetime64。
  df   =   pd  .  read_csv  (  "data/weather.csv"  ,   parse_dates  =[  0  ])
  print  (  df  [  "date"  ].  tail  ())

3. 将日期数据作为索引

将datetime64类型的数据设置为索引,得到的就是DatetimeIndex。

df = pd.read_csv("data/weather.csv")
df["date"] = pd.to_datetime(df["date"])  # 将date列转换为datetime64类型
df.set_index("date", inplace=True)  # 将date列设置为索引,inplace=true直接修改原对象
df.info()
# <class 'pandas.core.frame.DataFrame'>
# DatetimeIndex: 1461 entries, 2012-01-01 to 2015-12-31

将时间作为索引后可以直接使用时间进行切片取值。

print(df.loc["2013-01":"2013-06"])  # 获取2013年1~6月的数据
#             precipitation  temp_max  temp_min  wind weather
# date
# 2013-01-01            0.0       5.0      -2.8   2.7     sun
# 2013-01-02            0.0       6.1      -1.1   3.2     sun
# ...                   ...       ...       ...   ...     ...
# 2013-06-29            0.0      30.0      18.3   1.7     sun
# 2013-06-30            0.0      33.9      17.2   2.5     sun
print  (  df  .  loc  [  "2015"  ])    # 获取2015年所有数据
#             precipitation  temp_max  temp_min  wind weather
# date
# 2015-01-01            0.0       5.6      -3.2   1.2     sun
# 2015-01-02            1.5       5.6       0.0   2.3    rain
# ...                   ...       ...       ...   ...     ...
# 2015-12-30            0.0       5.6      -1.0   3.4     sun
# 2015-12-31            0.0       5.6      -2.1   3.5     sun

也可以通过between_time()和at_time()获取某些时刻的数据。

df.between_time("9:00", "11:00")  # 获取9:00到11:00之间的数据
df.at_time("3:33")  # 获取3:33的数据

4. 时间间隔timedelta

当用一个日期减去另一个日期,返回的结果是timedelta64类型。

d1 = pd.Timestamp( "2015-05-01 09:08:07.123456" )
d2 = pd.Timestamp( "2015-05-31 09:23:07.123456" )
print(d2-d1)
print(type(d1))
print(type(d2-d1))

TimedeltaIndex

将timedelta64类型的数据设置为索引,得到的就是TimedeltaIndex。

df = pd.read_csv("data/weather.csv", parse_dates=[0])
df_date   =   pd  .  to_datetime  (  df  [  "date"  ])
df  [  "timedelta"  ] =   df_date     -     df_date  [  0  ]    # 得到timedelta64类型的数据
df  .  set_index  (  "timedelta"  ,   inplace  =  True  )    # 将timedelta列设置为索引
df  .  info  ()
# <class 'pandas.core.frame.DataFrame'>
# TimedeltaIndex: 1461 entries, 0 days to 1460 days

将时间作为索引后可以直接使用时间进行切片取值。

print(df.loc["0 days":"5 days"])
#                 date  precipitation  temp_max  temp_min  wind  weather
# timedelta
# 0 days    2012-01-01            0.0      12.8       5.0   4.7  drizzle
# 1 days    2012-01-02           10.9      10.6       2.8   4.5     rain
# 2 days    2012-01-03            0.8      11.7       7.2   2.3     rain
# 3 days    2012-01-04           20.3      12.2       5.6   4.7     rain
# 4 days    2012-01-05            1.3       8.9       2.8   6.1     rain
# 5 days    2012-01-06            2.5       4.4       2.2   2.2     rain

5. 时间序列

生成时间序列

为了能更简便地创建有规律的时间序列,pandas提供了date_range()方法。

date_range()通过开始日期、结束日期和频率代码(可选)创建一个有规律的日期序列,默认的频率是天。

print(pd.date_range("2015-07-03", "2015-07-10"))
# DatetimeIndex(['2015-07-03', '2015-07-04', '2015-07-05', '2015-07-06',
#                '2015-07-07', '2015-07-08', '2015-07-09', '2015-07-10'],
#               dtype='datetime64[ns]', freq='D')

此外,日期范围不一定非是开始时间与结束时间,也可以是开始时间与周期数periods。

print(pd.date_range("2015-07-03", periods=5))
  # DatetimeIndex(['2015-07-03', '2015-07-04', '2015-07-05', '2015-07-06',
  #                '2015-07-07'],
  #               dtype='datetime64[ns]', freq='D')

可以通过freq参数设置时间频率,默认值是D。此处改为h,按小时变化的时间戳。

print(pd.date_range("2015-07-03", periods=5, freq="h"))
  # DatetimeIndex(['2015-07-03 00:00:00', '2015-07-03 01:00:00',
  #                '2015-07-03 02:00:00', '2015-07-03 03:00:00',
  #                '2015-07-03 04:00:00'],
  #               dtype='datetime64[ns]', freq='h')

下表为常见时间频率代码与说明:

代码说明
D天(calendar day,按日历算,含双休日)
B天(business day,仅含工作日)
W周(weekly)
ME / M月末(month end)
BME月末(business month end,仅含工作日)
MS月初(month start)
BMS月初(business month start,仅含工作日)
QE / Q季末(quarter end)
BQE季末(business quarter end,仅含工作日)
QS季初(quarter start)
BQS季初(business quarter start,仅含工作日)
YE / Y年末(year end)
BYE年末(business year end,仅含工作日)
YS年初(year start)
BYS年初(business year start,仅含工作日)
h小时(hours)
bh小时(business hours,工作时间)
min分钟(minutes)
s秒(seconds)
ms毫秒(milliseonds)
us微秒(microseconds)
ns纳秒(nanoseconds)

偏移量

可以在频率代码后面加三位月份缩写字母来改变季、年频率的开始时间。

  • QE-JAN、BQE-FEB、QS-MAR、BQS-APR等
  • YE-JAN、BYE-FEB、YS-MAR、BYS-APR等
print  (  pd  .  date_range  (  "2015-07-03"  ,   periods  =  10  ,   freq  =  "QE-JAN"  ))    # 设置1月为季度末
  # DatetimeIndex(['2015-07-31', '2015-10-31', '2016-01-31', '2016-04-30',
  #                '2016-07-31', '2016-10-31', '2017-01-31', '2017-04-30',
  #                '2017-07-31', '2017-10-31'],
  #               dtype='datetime64[ns]', freq='QE-JAN')

同理,也可以在后面加三位星期缩写字母来改变一周的开始时间。

  • W-SUN、W-MON、W-TUE、W-WED等
print  (  pd  .  date_range  (  "2015-07-03"  ,   periods  =  10  ,   freq  =  "W-WED"  ))    # 设置周三为一周的第一天
  # DatetimeIndex(['2015-07-08', '2015-07-15', '2015-07-22', '2015-07-29',
  #                '2015-08-05', '2015-08-12', '2015-08-19', '2015-08-26',
  #                '2015-09-02', '2015-09-09'],
  #               dtype='datetime64[ns]', freq='W-WED')

在这些代码的基础上,还可以将频率组合起来创建的新的周期。例如,可以用小时(h)和分钟(min)的组合来实现2小时30分钟。

 print  (  pd  .  date_range  (  "2015-07-03"  ,   periods  =  10  ,   freq  =  "2h30min"  ))
  # DatetimeIndex(['2015-07-03 00:00:00', '2015-07-03 02:30:00',
  #                '2015-07-03 05:00:00', '2015-07-03 07:30:00',
  #                '2015-07-03 10:00:00', '2015-07-03 12:30:00',
  #                '2015-07-03 15:00:00', '2015-07-03 17:30:00',
  #                '2015-07-03 20:00:00', '2015-07-03 22:30:00'],
  #               dtype='datetime64[ns]', freq='150min')

6. 重新采样

处理时间序列数据时,经常需要按照新的频率(更高频率、更低频率)对数据进行重新采样。可以通过resample()方法解决这个问题。resample()方法以数据累计为基础,会将数据按指定的时间周期进行分组,之后可以对其使用聚合函数。

df   =   pd  .  read_csv  (  "data/weather.csv"  )
  df  [  "date"  ] =   pd  .  to_datetime  (  df  [  "date"  ])
  df  .  set_index  (  "date"  ,   inplace  =  True  )
  print  (  df  [[  "temp_max"  ,   "temp_min"  ]].  resample  (  "YE"  ).  mean  ())    # 将数据按年分组,并计算每年的平均最高最低温度
  #              temp_max  temp_min
  # date
  # 2012-12-31  15.276776  7.289617
  # 2013-12-31  16.058904  8.153973
  # 2014-12-31  16.995890  8.662466
  # 2015-12-31  17.427945  8.835616
© 版权声明
THE END
喜欢就支持一下吧
点赞12 分享
评论 抢沙发
头像-大赛人网
欢迎您留下宝贵的见解!
提交
头像-大赛人网

昵称

取消
昵称

    请登录后查看评论内容