Pandas时间类型数据处理常用方法小结

Posted 肖永威

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Pandas时间类型数据处理常用方法小结相关的知识,希望对你有一定的参考价值。

在数据处理、特征工程时,往往需要按照时间段来统计特征,例如计算间隔天数、最近一个月、最近3个月、最近半年、最近一年某用户的行为数据,那么如何计算筛选这些时间点呢?下面就来介绍一些常用的方法。

首先,创建个模拟数据集。

import pandas as pd
import datetime

df = pd.DataFrame('sport':['青岛','哈尔滨','北京'],
                   'date':pd.to_datetime(['2021-05-04 07:30:00','2021-08-29 07:30:00','2021-10-31 07:30:00']))
df
sportdate
0青岛2021-05-04 07:30:00
1哈尔滨2021-08-29 07:30:00
2北京2021-10-31 07:30:00

1. 常用时间基本操作

1.1. 时间转字符串

1.1.1. 使用dt,按“yyyy-mm-dd”格式转换为字符串。

df['datestr']=df['date'].dt.strftime('%Y-%m-%d')
print(df.dtypes)
df
sport              object
date       datetime64[ns]
datestr            object
dtype: object
sportdatedatestr
0青岛2021-05-04 07:30:002021-05-04
1哈尔滨2021-08-29 07:30:002021-08-29
2北京2021-10-31 07:30:002021-10-31

dt.year、dt.month、dt.day、dt.hour、dt.minute、dt.second、dt.week (dt.weekofyear和dt.week一样)分别返回日期的年、月、日、小时、分、秒及一年中的第几周

1.1.2. 列(字段)数据做类型强制转换为字符串

首先,通过DataFrame的astype,直接把日期转换为字符串。

df['datestr']=df['date'].astype(str)
df
sportdatedatestr
0青岛2021-05-04 07:30:002021-05-04 07:30:00
1哈尔滨2021-08-29 07:30:002021-08-29 07:30:00
2北京2021-10-31 07:30:002021-10-31 07:30:00

使用str方法截断字符串。

df['datestr'] = df['datestr'].str[0:10]
df
sportdatedatestr
0青岛2021-05-04 07:30:002021-05-04
1哈尔滨2021-08-29 07:30:002021-08-29
2北京2021-10-31 07:30:002021-10-31

1.2. 时间字符串转为时间格式

使用“astype”,把字符串类型强制转换为时间数据。

DataFrame.astype(dtype, copy=True, errors=‘raise’)[source]

常见的时间格式字符串有:yyyy-mm-dd、yyyy-mm-dd HH:mm:ss、yyyymmdd、yyyymmdd HHmmss、yyyy/mm/dd等。

df['days'] = '20211117'
df['daytime'] = '20211117 12'
df['datestr'] = df['datestr'].astype('datetime64')
df['days'] = df['days'].astype('datetime64')
df['daytime'] = df['daytime'].astype('datetime64')

df
sportdatedatestrdaysdaytime
0青岛2021-05-04 07:30:002021-05-042021-11-172021-11-17 12:00:00
1哈尔滨2021-08-29 07:30:002021-08-292021-11-172021-11-17 12:00:00
2北京2021-10-31 07:30:002021-10-312021-11-172021-11-17 12:00:00

1.3. 使用dt分别取年、季度、月、日、周等

df = df.drop(['datestr','days','daytime'],axis=1)
df['year']= df['date'].dt.year
df['month'] = df['date'].dt.month
df['day'] = df['date'].dt.day
df['quarter'] = df['date'].dt.quarter  # 季度
df['week'] = df['date'].dt.isocalendar().week     # 周
df['weekday'] = df['date'].dt.weekday       # 周几,0为周一
df['yearmonth'] = df['date'].dt.strftime('%Y%m')
df['initdate']=df['date'].astype('int64')
df

注:周一为数字0。

sportdateyearmonthdayquarterweekweekdayyearmonthinitdate
0青岛2021-05-04 07:30:0020215421812021051620113400000000000
1哈尔滨2021-08-29 07:30:00202182933462021081630222200000000000
2北京2021-10-31 07:30:002021103144362021101635665400000000000

1.4. 时间的加减计算

1.4.1. 使用DateOffset方法加减计算年、月、日

DateOffset 基础操作类似于 dateutil.relativedelta(relativedelta 文档),可按指定的日历日时间段偏移日期时间。可用算数运算符(+)或 apply 方法执行日期偏移操作。

Parameters that add to the offset (like Timedelta):

  • years
  • months
  • weeks
  • days
  • hours
  • minutes
  • seconds
  • microseconds
  • nanoseconds
from pandas.tseries.offsets import *

df['datestr'] = df['datestr'] + DateOffset(months=1)
# 增加天数
df['days'] = df['days'] + DateOffset(days=10)
df['daytime'] = df['daytime'] + DateOffset(years=1)
df
sportdatedatestrdaysdaytime
0青岛2021-05-04 07:30:002021-06-042021-11-222022-11-02 12:00:00
1哈尔滨2021-08-29 07:30:002021-09-292021-11-222022-11-02 12:00:00
2北京2021-10-31 07:30:002021-11-302021-11-222022-11-02 12:00:00

1.4.2. 使用python的datetime.timedelta实现时间计算

datetime.timedelta对象代表两个时间之间的时间差,两个date或datetime对象相减就可以返回一个timedelta对象。

datetime.timedelta(weeks=0, days=0, hours=0, minutes=0, second=0, microsecond=0, milliseconas=0)
参数默认为0。

# 减少、增加天数
df['days'] = df['days'] - datetime.timedelta(days=5)
df['daytime'] = df['daytime'] + datetime.timedelta(days=-15)
df
sportdatedatestrdaysdaytime
0青岛2021-05-04 07:30:002021-05-042021-11-122021-11-02 12:00:00
1哈尔滨2021-08-29 07:30:002021-08-292021-11-122021-11-02 12:00:00
2北京2021-10-31 07:30:002021-10-312021-11-122021-11-02 12:00:00

1.5. DataFrame两行间的时间差

计算一列中相邻上下两行的差值,使用diff函数,元素的第一离散差分。计算Dataframe元素与Dataframe中另一个元素的差异(默认值为前一行中的元素)。

DataFrame.diff(periods=1, axis=0)

df['days'] = df['date'].diff().dt.days
df
sportdatedatestrdaysdaytime
0青岛2021-05-04 07:30:002021-06-04NaN2022-11-02 12:00:00
1哈尔滨2021-08-29 07:30:002021-09-29117.02022-11-02 12:00:00
2北京2021-10-31 07:30:002021-11-3063.02022-11-02 12:00:00

1.6. 整型数字转时间

由于某种原因,把时间保存为yyyymmdd格式的数值,例如:20211119等,转换为时间的方法:

# 如果时间被存在整数,可以通过中间转字符串,再转时间
data['intday'] = 20211118
data['intday'] =data['intday'].astype('str')
print(data)
data['intday'] =data['intday'].astype('datetime64[ns]')
data
   data_time       date    intday
0 2020-10-01 2019-01-31  20211118
1 2020-10-02 2019-02-28  20211118
2 2020-10-03 2019-03-31  20211118
data_timedateintday
02020-10-012019-01-312021-11-18
12020-10-022019-02-282021-11-18
22020-10-032019-03-312021-11-18

2. 时间数据批量初始化

pandas 时间序列之pd.date_range()。用于生成一个固定频率的DatetimeIndex时间索引。原型:
date_range(start=None, end=None, periods=None, freq=None, tz=None, normalize=False, name=None, closed=None, **kwargs)

  • 常用参数为start、end、periods、freq。
    start:指定生成时间序列的开始时间
    end:指定生成时间序列的结束时间
    periods:指定生成时间序列的数量
    freq:生成频率,默认‘D’,可以是’H’、‘D’、‘M’、‘5H’、‘10D’、…
    还可以根据closed参数选择是否包含开始和结束时间,left包含开始时间,不包含结束时间,right与之相反。默认同时包含开始时间和结束时间。
  • 函数调用时至少要指定参数start、end、periods中的两个。

https://www.tutorialspoint.com/python_pandas/python_pandas_date_functionality.htm

AliasDescriptionAliasDescription
Bbusiness day frequencyBQSbusiness quarter start frequency
Dcalendar day frequencyAannual(Year) end frequency
Wweekly frequencyBAbusiness year end frequency
Mmonth end frequencyBASbusiness year start frequency
SMsemi-month end frequencyBHbusiness hour frequency
BMbusiness month end frequencyHhourly frequency
MSmonth start frequencyT, minminutely frequency
SMSSMS semi month start frequencySsecondly frequency
BMSbusiness month start frequencyL, msmilliseconds
Qquarter end frequencyU, usmicroseconds
BQbusiness quarter end frequencyNnanoseconds
QSquarter start frequency
data = pd.DataFrame('data_time':pd.date_range('2020-10-01 00:00:00',periods = 3,freq = 'D'),
                     'date':pd.date_range('2019-01-01',periods = 3,freq = 'M'))
data
data_timedate
02020-10-012019-01-31
12020-10-022019-02-28
22020-10-032019-03-31

初始化起止时间应用案例:

# 取月初、月末及月份
def init_date_rage(startday='2019-01-01',endday = '2019-01-31', period = 3):
    data = pd.DataFrame('startday':pd.date_range(startday,periods = period,freq = 'MS'),
                         'endday':pd.date_range(endday,periods = period,freq = 'M'))
    data['yearmonth'] = data['startday'].dt.strftime('%Y%m')
    data['startday'] = data['startday'].dt.strftime('%Y-%m-%d')
    data['endday'] = data['endday'].dt.strftime('%Y-%m-%d')

    params = data[['startday','endday','yearmonth']].values.tolist()

    return params
input_params = init_date_rage()
input_params
[['2019-01-01', '2019-01-31', '201901'],
 ['2019-02-01', '2019-02-28', '201902'],
 ['2019-03-01', '2019-03-31', '201903']]

timedelta 对象表示两个 date 或者 time 的时间间隔。

class datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0)

https://docs.python.org/zh-cn/3/library/datetime.html

3. python的datetime 模块提供用于处理日期和时间的类。

在支持日期时间数学运算的同时,实现的关注点更着重于如何能够更有效地解析其属性用于格式化输出和数据操作。

  • class datetime.date
    一个理想化的简单型日期,它假设当今的公历在过去和未来永远有效。 属性: year, month, and day。

  • class datetime.time
    一个独立于任何特定日期的理想化时间,它假设每一天都恰好等于 246060 秒。 (这里没有“闰秒”的概念。) 包含属性: hour, minute, second, microsecond 和 tzinfo。

  • class datetime.datetime
    日期和时间的结合。属性:year, month, day, hour, minute, second, microsecond, and tzinfo.

  • class datetime.timedelta
    表示两个 date 对象或 time 对象,或者 datetime 对象之间的时间间隔,精确到微秒。

  • class datetime.tzinfo
    一个描述时区信息对象的抽象基类。 用来给 datetime 和 time 类提供自定义的时间调整概念(例如处理时区和/或夏令时)。

  • class datetime.timezone
    一个实现了 tzinfo 抽象基类的子类,用于表示相对于 世界标准时间(UTC)的偏移量。

  • Python 日历模块calendar.monthrange 获取某一个月有多少天
    输出的是一个元组;
    第一个元素,数字0是这个月第一天的星期码(0星期一,6星期天);
    第二个元素,数字31是这个月的天数;

3.1. 取月末最后一天

import calendar
# 取月末最后一天
last_day = calendar.monthrange(2020, 5)
print(last_day)
last_day = calendar.monthrange(2020, 5)[1]
print(last_day)
(4, 31)
31
#获取月初与月末时间
from datetime import datetime,date
import calendar

today = date.today()
print(today)
today = str(today)
month_first=datetime.strptime(today[:8]+'01','%Y-%m-%d')
print(month_first)
year = int(today[:4])
month = int(today[5:7])
month_end=datetime.strptime(today[:8]+str(calendar.monthrange(year, month)[1]),'%Y-%m-%d')

print(month_end)
2021-11-18
2021-11-01 00:00:00
2021-11-30 00:00:00

3.2. 取今天时间

# 取今天时间
to_day = str(datetime.date.today())[:10]
to_day
'2021-11-18'

3.3. 写操作日志应用,记录时间

由于前文,以及使用了date.today(),接下来换成time.localtime()。

import time
# 按时间写日志
def writelog(fielname,env,msg):
    # 取当前时间
    logtime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
    fp = open(fielname,'a+')
    fp.write(logtime + ' : '+ env + '\\n')
    fp.write('  '+ msg + '\\n')
    fp.close()
writelog('log.txt','test','hello2')

以上是关于Pandas时间类型数据处理常用方法小结的主要内容,如果未能解决你的问题,请参考以下文章

将字符串转换为日期 [带年份和季度]

Pandas 按季度转换为每日,同时牢记不同的代码

下采样到季度级别并在 Pandas 中获取季度结束日期值

Java常用类小结

pandas 日期数据处理大全,按照年、季度、月、周、日筛选数据

pandas group 日期到季度和总销售额列