Foursquare数据集处理之利用defaultdict进行主次关键字排序

来源:互联网 发布:阿里云 短信 编辑:程序博客网 时间:2024/06/09 17:26

1.背景
在做poi recommendation评估的工作,用到了Foursquare数据集,发现check_in文件内数据是按时间排序的,user杂乱无章,如下图所示,而我需要用到按user与主关键字,time为次关键字的排序数据做train_data,也就是说,需要先对第一列排序,在每个user内对第三列排序。
原check_in数据,三列分别为user poi time
2.思考
考虑到这里user是可重复的,(另一个时间又check_in了),需要user的poi与time信息,自然而然想到用字典,字典的value需要是个seq,包含至少后两列的信息,很明显普通的字典难以实现,这里想到用defaultdict,具体用法不再赘述,直接上代码理解。
3.代码

from collections import defaultdict as defdictf = open('Foursquare_checkins.txt')check_in = defdict(list)for line in f:    uid, poi_id, t = line.strip().split()    uid, poi_id, t = int(uid), int(poi_id), float(t)    check_in[uid].append([uid, poi_id, t]) #为了输出数据方便,存了uidkey_lst = sorted(check_in.keys())for idx in key_lst:    lst = check_in[idx] #value list    order_lst = sorted(lst, key = lambda lst : lst[2])     #字典并不保证输出有序,所以即使原文件时间有序,这里也要做下对时间的排序处理    for i in range(len(order_lst)):        content = []        for j in range(3):            content.append(str(order_lst[i][j]))        out = open('check_in.txt', 'a')        out.write('\t'.join(content) + '\n')        out.close()f.close()

4.结果
这里写图片描述
这里还有个对齐问题,一次tab四个字符,如果第二列小于4个字符就按第二列第一个字符来tab的,目前还未解决(主要是没意义),之后再说吧。
5.总结
使用defaultdict可以极大的优化代码,但是写入字典需要遍历一次文件,输出又要遍历,这样会很慢,对时间没有要求的可以这样使用,否则我的办法是使用flag判断新user_id,添加temp.txt来暂存已读文件,这样随着第一次对文件的遍历,所需的排序文件也输出完毕。
第一次写博客,再说个最近发现的问题,记录一下。
大家知道,写入文件的时候,会先把内容存到缓冲区,不执行close,是不会真正写入的。但有一次我发现,一个程序,没有写close,文件内却有结果了,遂百度之。
结论:当所存内容超过缓冲区存储空间的时候,会强制写入。
这里,我用追加的方式,每次都close,便于检查结果,不必等到最后才看到。事实上,这个数据集也是很大的,即使不这样也会有结果的。
6.补充
水平有限,在后续的学习时无意中看到了,一个对主次关键字排序的方法,在这里做一下补充。

a = [(1, 2, 3), (1, 3, 2), (3, 5, 3), (3, 2, 1), (2, 1, 5), (2, 4, 3)]b = sorted(a, key = lambda l : (l[0], l[1])) #主:第0列, 次:第1列c = sorted(a, key = lambda l : (-l[0], l[1])) #加负号即表示由大到小排

结果
这里写图片描述

这点小东西不值得另开一贴,既然原博提到了主次关键字排序,就做此补充吧。
文件内的数据都是字符串,按字典来做还是很不错的。如果直接对有效数据进行排序,可以用括号选择多个排序参数,不必多次sorted.
完结

原创粉丝点击