Python大数据分析2:时间索引

在数据分析中,时间信息不仅常常是一种被分析的对象,比如上次我们谈到的学生的生日,更多的可能往往表现在时间信息往往是一种分析的依据,比如我们按照时间统计分析各种流水记录。在这种情况下,我们常常把时间信息作为数据的索引,由此还可以利用很多专门的时间分析途径来对数据进行更多角度的时间分析。

比如我们假设目前的7条学生记录是分别在各个时间点上加入到我们的数据中来的,我们可以利用索引来表示:

# coding:utf-8
import pandas as pd
from pandas import DataFrame
from datetime import datetime

data = {'ID': ['000001', '000002', '000003', '000004', '000005', '000006', '000007'],
        'name': ['黎明', '赵怡春', '张富平', '白丽', '牛玉德', '姚华', '李南'],
        'gender': [True, False, True, False, True, False, True],
        'age': [16, 20, 18, 18, 17, 18, 16],
        'height': [1.88, 1.78, 1.81, 1.86, 1.74, 1.75, 1.76]
        }
dates = [datetime(2019, 11, 29), datetime(2019, 12, 5), datetime(2019, 12, 17),
         datetime(2019, 12, 30), datetime(2020, 1, 1), datetime(2020, 1, 3),
         datetime(2020, 1, 4)]
frame = pd.DataFrame(data, index=dates)
print(frame)

这里要注意几个问题:

第一,为了处理时间更为方便些,我们还是使用标准的时间类型来表示时间,而不是字符串,因此需要先导入必要的datetime。

第二,我们得到一个时间类型的列表,并将其设定为当前数据的索引。

此时我们可能感觉不到,这种时间类型的索引和一般的序号索引有什么区别,其实,采用时间类型的索引具有很多传统一般索引所不具备的特殊功能,我们分别给大家介绍下:

我们先看看数据的选择。一般而言,索引最大的作用就是提供一种选择行的依据,时间类型的索引可以按照适应时间处理的方式来进行数据选择。

比如我们选择特定时间的记录,如2019年11月29日的记录:

最为完美的就是直接使用时间类型来选择:

print(frame.loc[datetime(2019, 11, 29)])

这里我们使用了loc函数,其中的时间类型索引正好对应具体的行记录。

不过更为方便的方法是我们可以直接在loc函数中使用字符串表示来定位。

print(frame.loc[‘20191129’])

这个写法相对比较灵活,即使写成不同的格式,只要常见和对应原有的表示,就可以使用。

print(frame.loc[‘2019-11-29’])

甚至还可以利用不同粒度的时间单位来选择,比如我们以月份来选择:

print(frame.loc[‘2019-12’])

这就表示选择所有19年12月的全部记录,都没问题。

也可以进行切片的范围选择,比如我们选择19年12月到2020年1月的全部记录:

print(frame.loc[‘2019-12′:’2020-1’])

注意loc函数含有下界时间。

有一个等价的函数也可以实现同样的效果,就是truncate,它表示剪除,比如选择什么时间段的内容其实等价于剪除其他时间的数据。比如还是刚才这个例子,我们只需剪除12月之前的记录即可:

print(frame.truncate(before=’2019-12-1′))

这里的before参数就说明在此之前的全部要剪除

我们再看看对时间类型索引的分组问题。一般而言,索引元素都是不一样的,因此对索引分组意义并不大,但是对于时间类型的索引,往往存在着时间相同或者不同时间粒度单位相同的可能性,也具有分组的实际意义。

假设存在着相同的时间索引值,我们可以直接对索引进行分组。这里有两种方法都可以:

第一种是在groupby参数中指定level=0参数数值,即表示对索引分组,不论是什么类型,都可以按照数值是否一样分组:

print(frame[‘ID’].groupby(level=0).count())

第二种是在groupby参数中说明按照索引分组,更为直观简单:

print(frame[‘ID’].groupby(frame.index).count())

不过这里我们需要对时间索引中的年份进行分组,因此可以继续去大胆的取索引中的年份:

print(frame[‘ID’].groupby(frame.index.year).count())

居然是可以的,还是老话,在很多情况下,大家只要经常练习,你就会发现你的很多想法就是它应该的写法。不过细心的同学可能也会说,不对啊,应该有个dt然后才是year,这里的主要原因在于时间索引类型其实并不是datetime类型,pandas自动转换为了更适合索引处理的DatetimeIndex类型,因此有些不一样

如果你真的加了dt你就会发现系统告诉你这个秘密了!

当然,既然能按照年,那一定也能按照月,甚至星期:

print(frame[‘ID’].groupby(frame.index.week).count())

显然这些对于时间分析很有价值。

发表评论

邮箱地址不会被公开。 必填项已用*标注