Python 处理文件的性能优化

2014-08-03 23:00:47 +08:00
 wwttc
现在有一个list包含有1500个topic,另外一个文件包含一亿个微博数据,现在我想统计,1500个topic中每个topic分别有多少条微博包含它们,我写的代码如下,但是运行起来需要非常久的时间,有什么办法可以优化吗?

f = file("largefile.txt")
for line in f:
try:
tweet_time = line.split(',',3)[2].split()[0]
tweet = line.split(',',3)[-1]
for topic in topics:
topic_items = topic.split()
isContain = True
for item in topic_items:
if item not in tweet:
isContain = False
break
if isContain:
pass
except:
continue
f.close()
8819 次点击
所在节点    问与答
44 条回复
wwttc
2014-08-04 11:07:55 +08:00
@imn1
topic必须要拆的啊。比如说topic为“爸爸去哪儿 多多”,然后一条微博是“爸爸去哪儿节目中的多多”,这样如果不拆就统计不出来这条微博了
wwttc
2014-08-04 11:08:35 +08:00
@takato
其实也不是题目,是自己需要处理数据和Hadoop进行对比
captainhcg
2014-08-04 11:13:32 +08:00
另外一点很重要,推特是中文的还是英文的。中文的用 in 就可以(分词先不讨论),英文务必用正则的 \b (否则java和javascript就会混淆)。这一题推荐用正则,但我不认为在这里用正则和用all有本质区别。
imn1
2014-08-04 11:21:11 +08:00
@wwttc 没说不拆啊
你在外面拆啊,干嘛for微博信息每行拆一次,那不重复执行上亿次么?
sleeperqp
2014-08-04 11:22:34 +08:00
我觉得这是个建立倒排索引的过程 你可以查查相关的资料
你的处理过程的时间复杂度是O(nml) n是文件数 m是topics 数 l是文件的平均长度
你可以试试怎么把m 去掉或者l去掉
wwttc
2014-08-04 11:23:47 +08:00
@imn1 哦~明白了
wwttc
2014-08-04 11:24:18 +08:00
@captainhcg 中文的
clino
2014-08-04 11:25:36 +08:00
@sleeperqp 虽然对倒排索引不是很了解,但我想如果用倒排索引这种是不是就要先分词?
sleeperqp
2014-08-04 11:27:02 +08:00
突然想到两种方法:
一种是直接对源文本建立倒排索引,然后对这些索引最后与topics求交
另外一种是对元文本建立倒排索引的过程中,用hash之类的判断在不在topics里
这样就可以去掉m
efen
2014-08-04 11:31:28 +08:00
@wwttc
topics是固定的吧?

为什么要放在第一个for里面?

topics分片成topic的语句放for外面,做成set,可能会好一点
sleeperqp
2014-08-04 11:31:54 +08:00
@clino 后面看到是中文,如果这样我觉得分词还是有必要的 就算纯文本匹配也是有误差的
所以我觉得还是先分词下然后再做处理比较好~
imn1
2014-08-04 11:32:54 +08:00
@wwttc 还有,用表达式或map套函数要比for快不是一般的多,尤其适合这种各项无关联的列表
hahastudio
2014-08-04 11:43:21 +08:00
也许你可以试试把文件切成几片
然后使用 multiprocessing.Pool 里面带的 map

from multiprocessing import Pool
pool = Pool()
pool.map(func, iter) #just like map
shoumu
2014-08-04 11:50:52 +08:00
................isContain = True
................for item in topic_items:
....................if item not in tweet:
........................isContain = False
........................break
....................if isContain:

楼主你这段代码是不是有点问题?最后一个if的缩进是不是多了?
wwttc
2014-08-04 12:36:51 +08:00
@shoumu 嗯,是啊。多缩进了。。。
binux
2014-08-04 13:01:56 +08:00
我觉得大的数量级上优化空间不多,只好改进下常数时间了

* 不要 split 多次
* item 按照出现概率排序
* 先对 tweet 进行单字过滤(如果 topic 中的某个单字不存在,就不会匹配了)
* 用 topic 建词表,用这个词表对 tweet 切词,倒排或者怎么地都行

但是,这些改进都是 一亿 * (1500 * n) 后面这部分的效率。
它取决于 topic 平均长度,重复单词概率等特征。
frankzeng
2014-08-04 13:40:11 +08:00
1,把topic放在循环外拆开,必须的。
2,把这1亿条微博数据拆成10或是100个文件,放到不同机器上,再开多线程。
3,把微博的数据读到内容放到内存里,成为hash的键值,全部读完再来做比较。

空间换时间,简单暴力。
lookhi
2014-08-04 13:51:33 +08:00
@wwttc 数据放出来 需求放出来 做成一个测试题吧。就叫大家一起来优化. :D
josephok
2014-08-04 15:05:35 +08:00
为什么不用github gist?
answeror
2014-08-04 15:09:04 +08:00
在不使用hash的前提下, 对所有topic item建立AC自动机. 然后针对每条微博在AC自动机上做多串匹配, 其时间复杂度渐进上界为O(n+km), 其中n是所有微博的字符总数, k是微博条数(即一亿), m是所有topic的字符总数.

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/125941

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX