小编们最近参加了数据城堡举办的“大学生助学金精准资助预测”比赛,分组第19名的成绩进入了复赛,很激动有木有!在上一篇文章中,小编带你使用pandas并结合官方给出的一卡通消费数据一步步计算得到了每个同学的恩格尔系数,主要介绍了groupby()和pivot_table()两个方法。虽然有些地方写的不成熟,但是仍然收获了很多的肯定和鼓励,这也是小编再接再厉继续完成本系列的动力,谢谢大家!本篇,小编文文将带你探讨pandas在数据去重中的应用。
groupby用于对pandas数据进行分组,使用示例如下:
card_group=card_df.groupby(['id','how'])['amount'].sum()
首先我们根据id和how两列对数据进行分组,并对分组结果中的amount列进行求和运算,返回最后的结果。
pivot_table是pandas提供的透视表函数,它根据一个或多个键对数据进行聚合,并根据行列上的分组键将数据分配到各个矩形区域中。使用示例如下:
card_df.pivot_table('amount',index=['id'],columns=['how'],aggfunc=sum)
这里,我们指定行索引为id列,列索引为how列,并返回amount列按照aggfunc参数指定的聚合方法的聚合结果值,这样描述起来可能有些拗口,举个简单的例子,比如原使数据是下面这个样子:
id how amount
01 食堂 200
01 淋浴 10
01 食堂 20
02 食堂 300
02 淋浴 50
02 淋浴 30
02 食堂 150
则按照上面的方式生成的透视表如下所示:
食堂 淋浴
01 220 10
02 450 80
这里,小编将介绍官方给出的图书馆数据的处理过程,首先回顾一下图书馆数据样例:
图书馆的开放时间为早上7点到晚上22点,门禁编号数据在2014/02/23之前只有“编号”信息,之后引入了“进门、出门”信息,还有些异常信息为null,请参赛者自行处理。 字段描述和示例如下: 学生id,门禁编号,具体时间 3684,"5","2013/09/01 08:42:50" 7434,"5","2013/09/01 08:50:08" 8000,"进门2","2014/03/31 18:20:31" 5332,"小门","2014/04/03 20:11:06" 7397,"出门4","2014/09/04 16:50:51"
根据官方给出的数据,我们想要得到每位同学去过图书馆的天数统计信息,结果如下:
id times
0 13
1 1
10 3
19 10
20 13
21 3
22 9
23 7
28 32
29 38
下面开始介绍小编的数据处理过程,首先是从读入数据,很简单,使用read_csv的方法读入数据并指定其columns列表:
library_df=pd.read_csv('library_train.txt',header=None)
library_df.columns=['id','gate','time_stamp']
print (library_df.head(10))
读入的数据示例如下:
id gate time_stamp
0 3684 5 2013/09/01 08:42:50
1 14314 6 2013/09/01 08:42:59
2 5108 9 2013/09/01 08:43:32
3 5826 7 2013/09/01 08:44:06
4 7730 5 2013/09/01 08:44:25
5 6668 7 2013/09/01 08:47:24
6 11636 8 2013/09/01 08:48:24
7 4036 6 2013/09/01 08:49:53
8 4050 5 2013/09/01 08:50:01
9 7434 5 2013/09/01 08:50:08
我们可以注意到,time_stamp列记录的是每次进或出图书馆的具体时间,精确到了秒,那么如果想要得到在该段时间内每位同学去图书馆的天数统计,下面的两条数据其实只能算作一天:
id gate time_stamp
14878 0 7 2013/10/15 14:55:48
14925 0 7 2013/10/15 18:04:36
这时候很自然的想到对数据进行去重,但是上面两条数据的time_stamp是不一样的呀,无法进行去重,但我们注意到二者在精确到天时数据是一样的,因此我们只需要截取其中的年月日信息,二者就会变成两条重复数据。我们使用pandas的str提供的方法,对字符串进行截取,代码如下:
library_df['time_stamp']=library_df['time_stamp'].str[:10]
在pandas中操作字符串是必须使用.str,其它用法举例如下:
data.str.split(';')
data.str.replace('a','b')
关于pandas中字符串的操作不是本文的重点,此处不再赘述。
经过对字符串的截取操作,我们得到了如下的数据:
id gate time_stamp
14878 0 7 2013/10/15
14925 0 7 2013/10/15
接下来我们就可以进行数据去重了,使用pandas中的drop_duplicates()方法,示例如下:
library_df.drop_duplicates(['id','time_stamp'],keep='last',inplace=True)
可以看到我们指定了三个参数,第一个参数是根据哪几列进行去重的列表,这里我们指定了id和time_stamp两列,如果两条数据的这两列值相同,则会被当成重复列对待。第二个参数是keep参数,pandas默认在去重时是去掉所有重复数据,使用keep参数可以让我们保留重复数据中的一条而删掉其他的数据,keep='last'表明保留重复数据中的最后一条,当然你也可以使用keep='first'来保留第一条数据。最后一个参数时inplace参数,我们直接替换library_df的数据,而无需赋值给另一个新的DataFrame。
我们来看看此时id为0的同学的所有记录,代码如下:
print (library_df[library_df['id']==0])
输出结果如下:
id gate time_stamp
14925 0 7 2013/10/15
15790 0 7 2013/10/17
17394 0 6 2013/10/21
17838 0 8 2013/10/22
20000 0 6 2013/10/27
23869 0 4 2013/11/04
24550 0 5 2013/11/05
33365 0 7 2013/11/20
44954 0 5 2013/12/10
49583 0 7 2013/12/17
70052 0 5 2014/01/03
79702 0 6 2014/01/09
161664 0 进门1 2014/03/25
可以看到,结果中已经不存在id和time_stamp均相同的数据了。
接下来的工作就简单了,按照上一节提到的groupby方法,按照id列进行分组聚合就可以了,代码如下:
library_count_df=library_df.groupby(['id'])['time_stamp'].count()
这里,我们按照id列进行分组,并对返回结果中的time_stamp列进行计数处理,最终结果如下:
id
0 13
1 1
10 3
19 10
20 13
21 3
22 9
23 7
28 32
29 38
最后,使用to_csv方法写入到文件中即可。
library_count_df.to_csv('library.csv',encoding='gbk')
本文,小编主要介绍了对官方给出的图书馆数据的处理过程,图书馆借阅数据的处理过程类似,同样得到每位同学的借书数量。这里主要运用了groupby()对数据进行分组,以及运用drop_duplicates()去除重复数据。现在,所有的数据都已经初步处理完毕,接下来需要对数据进行归总。那么,下一篇,小编将带你探索利用pandas合并数据的奥秘,敬请期待!