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

xiaoxiao2021-02-28  87

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

from collections import defaultdict as defdict f = 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]) #为了输出数据方便,存了uid key_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. 完结

转载请注明原文地址: https://www.6miu.com/read-29392.html

最新回复(0)