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
sport | date | |
---|---|---|
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
sport | date | datestr | |
---|---|---|---|
0 | 青岛 | 2021-05-04 07:30:00 | 2021-05-04 |
1 | 哈尔滨 | 2021-08-29 07:30:00 | 2021-08-29 |
2 | 北京 | 2021-10-31 07:30:00 | 2021-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
sport | date | datestr | |
---|---|---|---|
0 | 青岛 | 2021-05-04 07:30:00 | 2021-05-04 07:30:00 |
1 | 哈尔滨 | 2021-08-29 07:30:00 | 2021-08-29 07:30:00 |
2 | 北京 | 2021-10-31 07:30:00 | 2021-10-31 07:30:00 |
使用str方法截断字符串。
df['datestr'] = df['datestr'].str[0:10]
df
sport | date | datestr | |
---|---|---|---|
0 | 青岛 | 2021-05-04 07:30:00 | 2021-05-04 |
1 | 哈尔滨 | 2021-08-29 07:30:00 | 2021-08-29 |
2 | 北京 | 2021-10-31 07:30:00 | 2021-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
sport | date | datestr | days | daytime | |
---|---|---|---|---|---|
0 | 青岛 | 2021-05-04 07:30:00 | 2021-05-04 | 2021-11-17 | 2021-11-17 12:00:00 |
1 | 哈尔滨 | 2021-08-29 07:30:00 | 2021-08-29 | 2021-11-17 | 2021-11-17 12:00:00 |
2 | 北京 | 2021-10-31 07:30:00 | 2021-10-31 | 2021-11-17 | 2021-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。
sport | date | year | month | day | quarter | week | weekday | yearmonth | initdate | |
---|---|---|---|---|---|---|---|---|---|---|
0 | 青岛 | 2021-05-04 07:30:00 | 2021 | 5 | 4 | 2 | 18 | 1 | 202105 | 1620113400000000000 |
1 | 哈尔滨 | 2021-08-29 07:30:00 | 2021 | 8 | 29 | 3 | 34 | 6 | 202108 | 1630222200000000000 |
2 | 北京 | 2021-10-31 07:30:00 | 2021 | 10 | 31 | 4 | 43 | 6 | 202110 | 1635665400000000000 |
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
sport | date | datestr | days | daytime | |
---|---|---|---|---|---|
0 | 青岛 | 2021-05-04 07:30:00 | 2021-06-04 | 2021-11-22 | 2022-11-02 12:00:00 |
1 | 哈尔滨 | 2021-08-29 07:30:00 | 2021-09-29 | 2021-11-22 | 2022-11-02 12:00:00 |
2 | 北京 | 2021-10-31 07:30:00 | 2021-11-30 | 2021-11-22 | 2022-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
sport | date | datestr | days | daytime | |
---|---|---|---|---|---|
0 | 青岛 | 2021-05-04 07:30:00 | 2021-05-04 | 2021-11-12 | 2021-11-02 12:00:00 |
1 | 哈尔滨 | 2021-08-29 07:30:00 | 2021-08-29 | 2021-11-12 | 2021-11-02 12:00:00 |
2 | 北京 | 2021-10-31 07:30:00 | 2021-10-31 | 2021-11-12 | 2021-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
sport | date | datestr | days | daytime | |
---|---|---|---|---|---|
0 | 青岛 | 2021-05-04 07:30:00 | 2021-06-04 | NaN | 2022-11-02 12:00:00 |
1 | 哈尔滨 | 2021-08-29 07:30:00 | 2021-09-29 | 117.0 | 2022-11-02 12:00:00 |
2 | 北京 | 2021-10-31 07:30:00 | 2021-11-30 | 63.0 | 2022-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_time | date | intday | |
---|---|---|---|
0 | 2020-10-01 | 2019-01-31 | 2021-11-18 |
1 | 2020-10-02 | 2019-02-28 | 2021-11-18 |
2 | 2020-10-03 | 2019-03-31 | 2021-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
Alias | Description | Alias | Description |
---|---|---|---|
B | business day frequency | BQS | business quarter start frequency |
D | calendar day frequency | A | annual(Year) end frequency |
W | weekly frequency | BA | business year end frequency |
M | month end frequency | BAS | business year start frequency |
SM | semi-month end frequency | BH | business hour frequency |
BM | business month end frequency | H | hourly frequency |
MS | month start frequency | T, min | minutely frequency |
SMS | SMS semi month start frequency | S | secondly frequency |
BMS | business month start frequency | L, ms | milliseconds |
Q | quarter end frequency | U, us | microseconds |
BQ | business quarter end frequency | N | nanoseconds |
QS | quarter 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_time | date | |
---|---|---|
0 | 2020-10-01 | 2019-01-31 |
1 | 2020-10-02 | 2019-02-28 |
2 | 2020-10-03 | 2019-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时间类型数据处理常用方法小结的主要内容,如果未能解决你的问题,请参考以下文章