在数据处理、特征工程时,往往需要按照时间段来统计特征,例如计算间隔天数、最近一个月、最近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')

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐