Pandas处理日期数据

Pandas时间官网文档:https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html

Pandas日期处理,可以将2018-01-01、1/1/2018等多种日期格式映射成统一的格式对象,在该对象上提供强大的功能支持。

几个概念:

  1. .to_datetime:pandas的一个函数,能将字符串、列表、series变成日期形式
  2. Timestamp:pandas表示日期的对象形式
  3. DatetimeIndex:pandas表示日期的对象列表形式

其中:

  • DatetimeIndex是Timestamp的列表形式
  • pd.to_datetime对单个日期字符串处理会得到Timestamp
  • pd.to_datetime对日期字符串列表处理会得到DatetimeIndex

在这里插入图片描述
此部分来源于B站up主https://space.bilibili.com/61036655

import pandas as pd
df = pd.read_csv('F:\\Temp\\datas\\Tianqi_2018.csv')
df['time_copy'] = pd.to_datetime(df['time'])
df.set_index(pd.to_datetime(df["time"]), inplace=True)
print(df.head())
df.head() df.info()

将索引设置成时间格式,是为了方便的对DatetimeIndex进行查询。下面开始演示。

依据前缀查询

# 下面的代码,哪怕索引不是datetime形式,也能查的出来
# 筛选固定的某一天
print(df.loc['2018-01-05'])
# 按月份前缀筛选(若索引不是datetime形式的,会报错)
print(df.loc['2018-03'])
# 若是 print(df.loc[df['time_copy']=='2018-03'])   虽然数据类型没问题,但只能输出3月1号这一行的数据
# 注意括号位置  符号&不能替换为and
# 它与 df.loc[(df['time_copy']>='2018-03-01') & (df['time_copy']<='2018-03-31')] 结果一样,所以对于逻辑判断来说,数据类型不影响结果
print(df.loc[(df['time']>='2018-03-01') & (df['time']<='2018-03-31')])

# 日期区间
print(df.loc['2018-01-05':'2018-01-10'])
print(df.loc[(df['time']>='2018-01-05') & (df['time']<='2018-01-10')])

# 按月份前缀筛选(若索引是字符串类型,那么只有2018-07-01到2018-08-31 62行)
print(df.loc["2018-07":"2018-09"])

# 按年份前缀筛选(若索引是字符串类型,直接报错)
print(df.loc["2018"])

获取月周季度(针对index)

# 获取州 月 季度数字列表(这只对index有用,time_copy列不行。而且输出的是本年的第几周,第几月,第几季度)
print(df.index.week)
print(df.index.month)
print(df.index.quarter)

统计每周、每月、每个季度的最高温度(也可以统计最低均值)

# 统计每周的最高温
print(df.groupby(df.index.week)["bWendu"].max())

# 统计每月的最高温
print(df.groupby(df.index.month)["bWendu"].max())

# 统计每个季度的最高温
print(df.groupby(df.index.quarter)["bWendu"].max())

获取年月日

API reference: https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.dt.year.html
User Guide: https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html#time-date-components
官网上很详细,这些整理几个有代表性的

import pandas as pd
df = pd.DataFrame({'id':range(1,7),
                   'name':['2021-6-1 12:22:12','2021-6-3 10:12:12',
                           '2021-6-7 08:23:40','2021-6-18 11:02:02',
                           '2021-7-1 15:30:00','2021-7-7 09:45:15'
                           ]})
df['name'] = pd.to_datetime(df['name'])

df['year'] = df['name'].dt.year
df['month'] = df['name'].dt.month
df['day'] = df['name'].dt.day
df['quarter'] = df['name'].dt.quarter
df['weeks'] = df['name'].dt.weekday
df['hour'] = df['name'].dt.hour
df['minute'] = df['name'].dt.minute
df['second'] = df['name'].dt.second
df['week'] = df['name'].dt.day_name()
print(df)

'''(week是调用函数,其他都是调用属性,结果是int64类型,可方便运算。)
   id                name  year  month  day  quarter  weeks  hour  minute  second       week
0   1 2021-06-01 12:22:12  2021      6    1        2      1    12      22      12    Tuesday
1   2 2021-06-03 10:12:12  2021      6    3        2      3    10      12      12   Thursday
2   3 2021-06-07 08:23:40  2021      6    7        2      0     8      23      40     Monday
3   4 2021-06-18 11:02:02  2021      6   18        2      4    11       2       2     Friday
4   5 2021-07-01 15:30:00  2021      7    1        3      3    15      30       0   Thursday
5   6 2021-07-07 09:45:15  2021      7    7        3      2     9      45      15  Wednesday
'''

to_period() 函数

import pandas as pd
df = pd.DataFrame({'id':range(1,7),
                   'name':['2021-6-1 12:22:12','2021-6-3 10:12:12',
                           '2021-6-7 08:23:40','2021-6-18 11:02:02',
                           '2021-7-1 15:30:00','2021-7-7 09:45:15'
                           ]})
# name列是object类型(其实也就是字符串),若不转为date,便不能用to_period函数
df['name'] = pd.to_datetime(df['name'])  

df["year"] = df["name"].dt.to_period("Y")
df["month"] = df["name"].dt.to_period("M")
df["day"] = df["name"].dt.to_period("D")
df["quarter"] = df["name"].dt.to_period("Q")
df["week"] = df["name"].dt.to_period("W")   # 输出日期在某一周的范围
df["hour"] = df["name"].dt.to_period("h")
df["min"] = df["name"].dt.to_period("min")
df["sen"] = df["name"].dt.to_period("s")
print(df)

'''
   id                name  year    month         day quarter                   week              hour               min                  sen
0   1 2021-06-01 12:22:12  2021  2021-06  2021-06-01  2021Q2  2021-05-31/2021-06-06  2021-06-01 12:00  2021-06-01 12:22  2021-06-01 12:22:12
1   2 2021-06-03 10:12:12  2021  2021-06  2021-06-03  2021Q2  2021-05-31/2021-06-06  2021-06-03 10:00  2021-06-03 10:12  2021-06-03 10:12:12
2   3 2021-06-07 08:23:40  2021  2021-06  2021-06-07  2021Q2  2021-06-07/2021-06-13  2021-06-07 08:00  2021-06-07 08:23  2021-06-07 08:23:40
3   4 2021-06-18 11:02:02  2021  2021-06  2021-06-18  2021Q2  2021-06-14/2021-06-20  2021-06-18 11:00  2021-06-18 11:02  2021-06-18 11:02:02
4   5 2021-07-01 15:30:00  2021  2021-07  2021-07-01  2021Q3  2021-06-28/2021-07-04  2021-07-01 15:00  2021-07-01 15:30  2021-07-01 15:30:00
5   6 2021-07-07 09:45:15  2021  2021-07  2021-07-07  2021Q3  2021-07-05/2021-07-11  2021-07-07 09:00  2021-07-07 09:45  2021-07-07 09:45:15
'''

date_range() 函数

注意freq=的参数,本节末有参数表。
date_range()起止参数包括其自身。 也可以像Python的range()一样,使用closed参数(closed=‘left’ or closed=‘right’)

连续日期 (连续日历日)

import pandas as pd
print(pd.date_range(start='2021-6-1',end='2021-6-10'))
print()
print(pd.date_range(start='2021-6-1',periods=10))
'''
DatetimeIndex(['2021-06-01', '2021-06-02', '2021-06-03', '2021-06-04',
               '2021-06-05', '2021-06-06', '2021-06-07', '2021-06-08',
               '2021-06-09', '2021-06-10'],
              dtype='datetime64[ns]', freq='D')
'''

中间隔一天

import pandas as pd
print(pd.date_range(start='2021-6-1',end='2021-6-10', freq='2D'))
'''
DatetimeIndex(['2021-06-01', '2021-06-03', '2021-06-05', '2021-06-07',
               '2021-06-09'],
              dtype='datetime64[ns]', freq='2D')
'''

工作日

import pandas as pd
print(pd.date_range(start='2021-6-1',end='2021-6-10', freq='B'))
'''
DatetimeIndex(['2021-06-01', '2021-06-02', '2021-06-03', '2021-06-04',
               '2021-06-07', '2021-06-08', '2021-06-09', '2021-06-10'],
              dtype='datetime64[ns]', freq='B')
'''

每月的第一天

import pandas as pd
print(pd.date_range(start='2020-1-1',end='2020-12-31',freq='MS'))
'''
DatetimeIndex(['2020-01-01', '2020-02-01', '2020-03-01', '2020-04-01',
               '2020-05-01', '2020-06-01', '2020-07-01', '2020-08-01',
               '2020-09-01', '2020-10-01', '2020-11-01', '2020-12-01'],
              dtype='datetime64[ns]', freq='MS')
'''

每月的最后一天

import pandas as pd
print(pd.date_range(start='2020-1-1',end='2020-12-31',freq='M'))
'''
DatetimeIndex(['2020-01-31', '2020-02-29', '2020-03-31', '2020-04-30',
               '2020-05-31', '2020-06-30', '2020-07-31', '2020-08-31',
               '2020-09-30', '2020-10-31', '2020-11-30', '2020-12-31'],
              dtype='datetime64[ns]', freq='M')
'''

季度末

import pandas as pd
print(pd.date_range(start='2020-1-1',end='2020-12-31', freq='Q'))
'''
DatetimeIndex(['2020-03-31', '2020-06-30', '2020-09-30', '2020-12-31'], dtype='datetime64[ns]', freq='Q-DEC')
'''

freq参数表

官网:https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html#offset-aliases

freq描述freq描述freq描述
B工作日频率SMS每半月第一个日历日(第 1 天和第 15 天)AS,YS每年的第一个日历日
C自定义工作日频率BMS每月第一个工作日BAS,BYS每年的第一个工作日
D日历日频率CBMS自定义每月第一个工作日BH工作日按“时”的频率
W每周频率Q季度最后一个月的最后一个日历日H每小时频率
M月末频率BQ季度最后一个月的最后一个工作日T,min每分钟频率
SM半月末频率(15 日和月末)QS季度最后一个月的第一个日历日S秒频率
BM每月最后一个工作日BQS季度最后一个月的第一个工作日L,ms毫秒频率
CBM自定义每月最后一个工作日A,Y每年的最后一个日历日U,us微秒频率
MS每月第一个日历日BA,BY每年的最后一个工作日N纳秒频率

时间戳与格式化时间

# 查看当前时间戳
import time
print(time.time())

时间戳转格式化时间

import datetime
import pandas as pd
data = pd.DataFrame({'timeStamp':[1638432171, 1638432181, 1638432231, 1638432232, 1638435832],'sui':list('abcde')})
data['time1'] = pd.to_datetime(data['timeStamp'], unit="s")
data['time2'] = pd.to_datetime(data['timeStamp'].apply(lambda i:i+8*3600), unit="s")
th34['time3'] = th34['timeStamp'].apply(lambda x:datetime.datetime.fromtimestamp(x))
print(data)
# 代码里的时间戳对应的是2021-12-02 16:02:51 ,但结果很显然差了八个小时。
# 因为to_datetime转换的是格林威治时间,比北京时间少八小时。所以要用的话要做个加法。
'''
    timeStamp  sui              time1                time2			time3
0  1638432171   a   2021-12-02 08:02:51   2021-12-02 16:02:51	2021-12-02 16:02:51
1  1638432181   b   2021-12-02 08:03:01   2021-12-02 16:03:01	2021-12-02 16:03:01
2  1638432231   c   2021-12-02 08:03:51   2021-12-02 16:03:51	2021-12-02 16:03:51
3  1638432232   d   2021-12-02 08:03:52   2021-12-02 16:03:52	2021-12-02 16:03:52
4  1638435832   e   2021-12-02 09:03:52   2021-12-02 17:03:52	2021-12-02 17:03:52
'''

格式化时间转时间戳

时间戳在线工具:https://tool.lu/timestamp/
从时间戳到纪元:https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html#from-timestamps-to-epoch

import pandas as pd
import time
data = pd.DataFrame({'time':['2021-12-02 16:10:30', '2021-12-02 16:10:31', '2021-12-02 16:11:31', '2021-12-02 16:11:30', '2021-12-02 17:10:30'],'sui':list('abcde')})
data['date'] = pd.to_datetime(data['time'])

# 普通的转换方法
data['zidingyi'] = data['time'].apply(lambda i:int(time.mktime(time.strptime(i, '%Y-%m-%d %H:%M:%S'))))

# 官网给了一个用格式化时间转时间戳的方式。但结果与下面的astype函数一致,都是快了8小时,所以用to_datetime转回来的时间就刚刚好
# 减去纪元(UTC 时间 1970 年 1 月 1 日午夜),然后除以“单位”(1 秒)。
data['guanwang'] = (data['date'] - pd.Timestamp("1970-01-01")) // pd.Timedelta("1s")

# 一种报警告的方法
data['FutureWarning'] = data['date'].astype('int64')//1e9
data['FutureWarning'] = data['FutureWarning'].astype('int32')

print(data)
'''这是一个让我动摇想法的结果。我一直认为普通方法转出来的时间戳是标准的,后面两个都快了28800秒(也即是8小时),虽然现在还是这么以为的。。。
                  time sui                date    zidingyi    guanwang  FutureWarning
0  2021-12-02 16:10:30   a 2021-12-02 16:10:30  1638432630  1638461430     1638461430
1  2021-12-02 16:10:31   b 2021-12-02 16:10:31  1638432631  1638461431     1638461431
2  2021-12-02 16:11:31   c 2021-12-02 16:11:31  1638432691  1638461491     1638461491
3  2021-12-02 16:11:30   d 2021-12-02 16:11:30  1638432690  1638461490     1638461490
4  2021-12-02 17:10:30   e 2021-12-02 17:10:30  1638436230  1638465030     1638465030
'''

计算时间差

# 时间格式可以是多样的。混用都行。是字符串就行。比如例子b,若参数是数字那结果都是0。
a = (pd.Timestamp('2019-1-17 9:36:12')-pd.Timestamp('2019-1-16 9:30:03'))//pd.Timedelta("1s")
b = (pd.Timestamp('20211208121234')-pd.Timestamp('20211208120000'))//pd.Timedelta("1s")

一个报错的样例。显然Timestamp函数里的参数只能是字符串,不能是Series。
df[‘shicha’] = (pd.Timestamp(df[‘time’])-pd.Timestamp(df[‘time_copy’]))//pd.Timedelta(“1s”)

进入正题

import pandas as pd
df = pd.DataFrame({'time':['20211208121234','20211208121314','20211208131314'],'asd':['A','B','C']},index=['x','y','z'])
df['base'] = '20211208120000'

# 直接用字符串,不需要to_datetime函数
df['cha_str'] = df.apply(lambda x: (pd.Timestamp(x['time'])-pd.Timestamp(x['base']))//pd.Timedelta("1s"),axis=1)

# 下面的这两个就需要用to_datetime函数,才能计算
df['time'] = pd.to_datetime(df['time'])
df['base'] = pd.to_datetime(df['base'])
df['cha_datetime'] = (df['time'] - df['base']) // pd.Timedelta("1s")
df['cha_c'] = (df['time'] - df['base'])#.apply(lambda i:str(i).split(':')[0].split(' ')+str(i).split(':')[1:])

# Timedelta里的参数可以换成这些 (天、小时、分钟、秒)
df['jia'] = df['time'] + pd.Timedelta("3 day")

print(df)

'''
                 time asd                base  cha_str  cha_datetime           cha_c                 jia
x 2021-12-08 12:12:34   A 2021-12-08 12:00:00      754           754 0 days 00:12:34 2021-12-11 12:12:34
y 2021-12-08 12:13:14   B 2021-12-08 12:00:00      794           794 0 days 00:13:14 2021-12-11 12:13:14
z 2021-12-08 13:13:14   C 2021-12-08 12:00:00     4394          4394 0 days 01:13:14 2021-12-11 13:13:14
'''
  • 3
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值