java中的接口是类吗
325
2022-11-06
【Python】数据分析.pandas.时间序列
文章目录
数据分析.pandas.时间序列
一、简单的了解生成一段时间范围二、转换与处理时间序列数据二、实际案例处理
2.1 案例一2.2 案例一解析2.3 案例二2.4 案例二解析
数据分析.pandas.时间序列
关于时间序列的一些基本知识点,本人了解不是太深入,介绍一篇文章:pandas–处理时间序列数据 数据分析的对象不仅仅限于数值型和类别型两种,常用的数据分析类型还包括时间类型。但时间类型数据在读入Python后常常以字符串的形式出现,无法实现大部分与时间相关的分析,多以pandas库提供了额外的模块来快速的实现时间字符串的转换、信息提取和时间运算。
一、简单的了解生成一段时间范围
import pandas as pdimport numpy as npdf = pd.date_range(start="20000101",end="20010101",freq="D")print(df)# DatetimeIndex(['2000-01-01', '2000-01-02', '2000-01-03', '2000-01-04',# '2000-01-05', '2000-01-06', '2000-01-07', '2000-01-08',# '2000-01-09', '2000-01-10',# ...# '2000-12-23', '2000-12-24', '2000-12-25', '2000-12-26',# '2000-12-27', '2000-12-28', '2000-12-29', '2000-12-30',# '2000-12-31', '2001-01-01'],# dtype='datetime64[ns]', length=367, freq='D')df = pd.date_range(start="2000-01-01",end="2001/01/01",freq="D")print(df)# DatetimeIndex(['2000-01-01', '2000-01-02', '2000-01-03', '2000-01-04',# '2000-01-05', '2000-01-06', '2000-01-07', '2000-01-08',# '2000-01-09', '2000-01-10',# ...# '2000-12-23', '2000-12-24', '2000-12-25', '2000-12-26',# '2000-12-27', '2000-12-28', '2000-12-29', '2000-12-30',# '2000-12-31', '2001-01-01'],# dtype='datetime64[ns]', length=367, freq='D')df = pd.date_range(start="20000101",end="20010101",freq="10D")print(df)# DatetimeIndex(['2000-01-01', '2000-01-11', '2000-01-21', '2000-01-31',# '2000-02-10', '2000-02-20', '2000-03-01', '2000-03-11',# '2000-03-21', '2000-03-31', '2000-04-10', '2000-04-20',# '2000-04-30', '2000-05-10', '2000-05-20', '2000-05-30',# '2000-06-09', '2000-06-19', '2000-06-29', '2000-07-09',# '2000-07-19', '2000-07-29', '2000-08-08', '2000-08-18',# '2000-08-28', '2000-09-07', '2000-09-17', '2000-09-27',# '2000-10-07', '2000-10-17', '2000-10-27', '2000-11-06',# '2000-11-16', '2000-11-26', '2000-12-06', '2000-12-16',# '2000-12-26'],# dtype='datetime64[ns]', freq='10D')df = pd.date_range(start="20000101",periods=12,freq="M")print(df)# DatetimeIndex(['2000-01-31', '2000-02-29', '2000-03-31', '2000-04-30',# '2000-05-31', '2000-06-30', '2000-07-31', '2000-08-31',# '2000-09-30', '2000-10-31', '2000-11-30', '2000-12-31'],# dtype='datetime64[ns]', freq='M')df = pd.date_range(start="20000101",periods=12,freq="H")print(df)# DatetimeIndex(['2000-01-01 00:00:00', '2000-01-01 01:00:00',# '2000-01-01 02:00:00', '2000-01-01 03:00:00',# '2000-01-01 04:00:00', '2000-01-01 05:00:00',# '2000-01-01 06:00:00', '2000-01-01 07:00:00',# '2000-01-01 08:00:00', '2000-01-01 09:00:00',# '2000-01-01 10:00:00', '2000-01-01 11:00:00'],# dtype='datetime64[ns]', freq='H')
返回顶部
二、转换与处理时间序列数据
在多数情况下,对时间类型数据进行分析的前提就是将原本为字符串的时间转换为标准时间。以下是pandas继承的相关时间类。
1.Timestamp是时间类中最基础的类,也是最为常用的。通常情况下,会将与时间有关的字符串转换成Timestamp。使用的方法为 to_datetime()
2.Timestamp类型的时间是有限的,计算机中目前的范围是1677.9.21-2262.4.11.
3.除了可以将数据直接转化为Timestamp类型外,还可以将数据单独提取出来转换为DatetimeIndex或者PeriodIndex.(这两种方法使用中并无太大区别,只是前者是指代一系列时间点的数据结构,后者是指代一系列时间段的数据结构。)
在用PeriodIndex转化数据类型时,需要添加freq参数来指定时间间隔。(常用的时间间隔有年-Y、月-M、日-D、小时-H、分钟-T、秒-S)
参数名称 | 说明 |
data | 接受array,表示DatetimeIndex的值 |
freq | 接受string ,表示时间的间隔频率 |
start | 接受string,表示生成规则时间数据的起始点 |
periods | 表示需要生成的周期数 |
end | 接受string,表示生成规则时间数据的终结点 |
tz | 接受timezone,表示数据的时区 |
name | 接受int、string,默认为空,指定DatetimeIndex的名字 |
4.提取时间序列数据信息
在涉及处理分析与时间相关的数据的时候,需要利用Timestamp的属性来实现对时间中的年份、月份的提取。
AttributeError: 'Timestamp' object has no attribute 'weekday_name' 对于该异常是由于当前pandas版本靠后,要退回到之前版本使用。
5.加减时间数据 Timedelta是时间相关类中的一个异类,它可以使用正负数来表示单位时间。使用Timedelta类可以实现对时间的运算。
周期名称 | 单位 | 说明 | 周期名称 | 单位 | 说明 |
weeks | 无 | 星期 | seconds | s | 秒 |
days | D | 天 | milliseconds | ms | 毫秒 |
hours | h | 小时 | microseconds | us | 微秒 |
minutes | m | 分钟 | nanoseconds | ns | 纳秒 |
# 将lock_time的时间加上一天time1 = order['lock_time']+pd.Timedelta(days=1)print('加上一天时间之前的数据:\n',order['lock_time'][:5])print('加上一天时间之后的数据:\n',time1[:5])#加上一天时间之前的数据: 0 2016-08-01 11:11:461 2016-08-01 11:31:552 2016-08-01 12:54:373 2016-08-01 13:08:204 2016-08-01 13:07:16Name: lock_time, dtype: datetime64[ns]#加上一天时间之后的数据: 0 2016-08-02 11:11:461 2016-08-02 11:31:552 2016-08-02 12:54:373 2016-08-02 13:08:204 2016-08-02 13:07:16Name: lock_time, dtype: datetime64[ns]timeDelta = order['lock_time']-pd.to_datetime('2017-1-1')print('lock_time减去2017年1月1日0点0时0分后的数据为:\n',timeDelta[:5])print('数据类型为:',timeDelta.dtypes)#lock_time减去2017年1月1日0点0时0分后的数据为: 0 -153 days +11:11:461 -153 days +11:31:552 -153 days +12:54:373 -153 days +13:08:204 -153 days +13:07:16Name: lock_time, dtype: timedelta64[ns]#数据类型为: timedelta64[ns]
任务实现:
import pandas as pd # 读取数据表order = pd.read_table('data/meal_order_info.csv',sep=',',encoding='gbk')# 转换数据类型order['use_start_time'] = pd.to_datetime(order['use_start_time'])order['lock_time'] = pd.to_datetime(order['lock_time'])# 提取相关的时间信息year = [i.year for i in order['lock_time']]month = [i.month for i in order['lock_time']]day = [i.day for i in order['lock_time']] week = [i.week for i in order['lock_time']]weekday = [i.weekday() for i in order['lock_time']]weekday_name = [i.weekday_name for i in order['lock_time']]print('年份信息:\n',year[:5])print('月份信息:\n',month[:5])print('日期信息:\n',day[:5])print('周信息:\n',week[:5])print('星期信息:\n',weekday[:5])print('星期名称信息:\n',weekday_name[:5])#年份信息: [2016, 2016, 2016, 2016, 2016]#月份信息: [8, 8, 8, 8, 8]#日期信息: [1, 1, 1, 1, 1]#周信息: [31, 31, 31, 31, 31]#星期信息: [0, 0, 0, 0, 0]#星期名称信息: ['Monday', 'Monday', 'Monday', 'Monday', 'Monday']
返回顶部
二、实际案例处理
2.1 案例一
需求:统计出911紧急拨号数据中不同月份的电话的次数的情况
import numpy as npimport pandas as pdfrom matplotlib import pyplot as pltfrom matplotlib import font_manager#设置中文my_font = font_manager.FontProperties(fname="C:\Windows\Fonts\STXINGKA.TTF",size=18)#读取csv文件file_path = "911-calls/911.csv"df = pd.read_csv(file_path)df["timeStamp"] = pd.to_datetime(df["timeStamp"]) #将timeStamp转化为时间戳df.set_index("timeStamp",inplace=True) #将timeStamp定义为索引print(df)# lat ... e# timeStamp ...# 2015-12-10 17:10:52 40.297876 ... 1# 2015-12-10 17:29:21 40.258061 ... 1# 2015-12-10 14:39:21 40.121182 ... 1# 2015-12-10 16:47:36 40.116153 ... 1# 2015-12-10 16:56:52 40.251492 ... 1# ... ... ..# 2020-06-08 13:07:24 40.136020 ... 1# 2020-06-08 13:10:11 40.172526 ... 1# 2020-06-08 13:10:41 40.125814 ... 1# 2020-06-08 13:11:45 40.197947 ... 1# 2020-06-08 13:14:43 40.140505 ... 1# [645716 rows x 8 columns]#统计出911紧急拨号数据中不同月份的电话的次数count_by_month = df.resample("M").count()["title"]print(count_by_month.head(4)# lat # timeStamp# 2015-12-31 7916 # 2016-01-31 13096 # 2016-02-29 11396 # 2016-03-31 11059 #画图_x = count_by_month.index_y = count_by_month.values#查看当前dataframe的方法for i in _x: print(dir(i)) break#格式化x轴_x = [i.strftime("%Y%m%d") for i in _x]#设置图像大小plt.figure(figsize=(20,8),dpi=80)#绘图plt.plot(range(len(_x)),_y)plt.xticks(range(len(_x)),_x,rotation=45)plt.xlabel("年/月/日",fontproperties=my_font)plt.ylabel("次数",fontproperties=my_font)plt.title("911紧急拨号数据中不同月份的电话的次数",fontproperties=my_font)#设置网格plt.grid(True,linestyle="-.",alpha=0.3)#展示plt.show()
返回顶部
2.2 案例一解析
这里我们运用to_datetime()函数将原来字符串类型的时间转化为了datetime类型的时间,并且制定该列数据作为索引,原有数据不保留。
pandas重采样;指的是将时间序列从一个频率转化为另一个频率进行处理的过程降采样:将高频率数据转化为低频率数据升采样:将低频率数据转化为高频数率据
这里将时间频率该定为按照月进行统计。
在之前图形输出时横坐标包含了时间,会显得坐标冗长,视觉冲击强烈。在这里对横坐标进行格式化,只包含年月日,清晰明了。
Python中strftime()函数的用法 在这里,strftime()函数可以用来变换时间格式,让时间更好的展现出来。strftime()函数可以把YYYY-MM-DD HH:MM:SS格式的日期字符串转换成其它形式的字符串。官方文档:strftime()
它可以用以下的符号对日期和时间进行格式化:
%d | 日期 | 01-31 |
%f | 小数形式的秒 | SS.SSS |
%H | 小时 | 00-23 |
%j | 算出某一天是该年的第几天 | 001-366 |
%m | 月份 | 00-12 |
%M | 分钟 | 00-59 |
%s | 从1970年1月1日到现在的秒数 | |
%S | 秒 | 00-59 |
%w | 星期 | 0-6 (0是星期天) |
%W | 算出某一天属于该年的第几周 | 01-53 |
%Y | 年 | YYYY |
%% | 百分号 |
返回顶部
2.3 案例二
需求:统计出不同月份的不同类型的拨号次数的情况
import numpy as npimport pandas as pdfrom matplotlib import pyplot as pltfrom matplotlib import font_manager#设置中文my_font = font_manager.FontProperties(fname="C:\Windows\Fonts\simfang.ttf",size=18)#读取csv文件file_path = "911-calls/911.csv"df = pd.read_csv(file_path)#把时间字符串转化为时间类型设置为索引df["timeStamp"] = pd.to_datetime(df["timeStamp"])#添加列,表示分类temp_list = df["title"].str.split(":").tolist()cate_list = [i[0] for i in temp_list]df["cate"] = pd.DataFrame(np.array(cate_list).reshape((df.shape[0]),1))df.set_index("timeStamp",inplace=True)# 设置图像大小plt.figure(figsize=(20, 8), dpi=80)#可以理解为对分组的数据表遍历,#设置变量group_name(分类),group_data(分组后的数据表)for group_name,group_data in df.groupby(by="cate"): #对不同的分类进行绘图 count_by_month = group_data.resample("M").count()["title"] _x = count_by_month.index _y = count_by_month.values _x = [i.strftime("%Y/%m/%d") for i in _x] # 绘图 plt.plot(range(len(_x)), _y, label=group_name)#设置坐标及图示plt.xticks(range(len(_x)),_x,rotation=45)plt.xlabel("年/月/日",fontproperties=my_font)plt.ylabel("911紧急拨号次数",fontproperties=my_font)plt.title("不同月份的不同类型的911紧急拨号次数的情况",fontproperties=my_font)plt.legend(loc="best")# 设置网格plt.grid(True, linestyle="-.", alpha=0.3)# 展示plt.show()
返回顶部
2.4 案例二解析
案例二的需求与案例一的需求相比较,可以发现都是对每月的数据进行统计,只是案例二具体到了每个911紧急拨号的类型.
基于以上的分析,以上的代码就很容易理解了。我们首先添加date一列,同时将字符串型时间转化为时间类型并设置为索引。(详细解析见博客:pandas-分组、聚合里的911案例)
注意:
这个地方在将时间类型列设置为索引时,必须放置在df["cate"] = pd.DataFrame(np.array(cate_list).reshape((df.shape[0]),1))之后,因为该行代码是添加一列,是在原来的dataframe结构基础上,它的索引标准还是从0开始的;若在之前就设置时间列为索引,后续添加date列时,索引不匹配,则会出现整列为NAN值。
在案例一中我们遍历的是统计好的每月数据,案例二我们要在此基础上,添加不同的类型。同样的我们在遍历每月数据的同时,遍历不同的类型。其中,每一次的遍历,就是对一种911紧急拨号类型的绘图处理。
以下是df.groupby(by=“cate”)的具体内容,由于它是个DataFrameGroupBy object(对象),所以只能遍历的去查看。它本身是一个包含两个元素的元组,前面是类型,后面是个dataframe类型的数据,这也是为什么我们设置两个变量的原因。
for i in df.groupby(by="cate"): print(i)
返回顶部
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~