列表中的Python计数发生:如何使其更快?
我有一个包含大约6百万个项目的字符串列表,并且我正在计算每个唯一值的发生次数。列表中的Python计数发生:如何使其更快?
这里是我的代码:
lines = [6 million strings]
unique_val = list(set(lines)) # contains around 500k items
mydict = {}
for val in unique_val:
mydict[val] = lines.count(val)
我发现上面的代码工作非常缓慢因为我指望名单是巨大的。
我想知道是否有办法让它更快?
非常感谢
如果你不想使用collections
模块。
counts = dict()
for line in lines:
counts[line] = counts.get(line,0) + 1
或者,如果你只是不想使用Counter
from collection import defaultdict
counts = defaultdict(int)
for line in lines:
counts[line] += 1
嗨迈克尔,那第一个工作怎么样?它看起来像计数没有初始化任何东西,所以我不知道它是如何得到更新? (当我运行它时,它似乎也不工作...)。 “get”函数查找一个键并返回0,如果该键不存在,但由于我们从不添加任何键,它不会总是0吗? –
@en_Knight,:)它显然不起作用。最后我错过了'+ 1'。我现在编辑它 –
这个怎么样,
from collections import defaultdict
import collections
lines = [600 million strings]
d = defaultdict(int)
for line in lines:
for word, count in collections.Counter(line).items():
d[word] += count
为什么你会在DeepSpace的时候这样做,当他看起来更简洁的结果呢? (当然,我认为他不应该打电话给他) –
@en_Knight,thx指出这一点。我刚刚编辑了我的答案。 – SparkAndShine
嗯,我还是不明白这比'd = Counter(lines)'更好。为什么我们循环,多次调用Counter和字典拷贝?有没有你正在做的内存优化? –
numpy的解决方案
我认为numpy的给你最快的答案,使用unique:
result = dict(zip(*np.unique(lines, return_counts=True)))
numpy在引擎盖下非常严格优化。每个链接的文档,在魔术界围绕return_counts
标志:
return_counts
:BOOL,可选如果真,也返回的次数每一个独特的价值AR出现。
定时
我计时你原来的做法,柜台办法
result = Counter(lines)
和
N = 1000000
lines = [chr(i%100) for i in range(N) ]
Obviousl生成一组的numpy的方法这个测试不是很好的报道,但这是一个开始。
你正在0.584s操作的方法; DeepSpace的计数器在0.162(3.5x加速)和0.0861(7x加速)的numpy。再次,这可能取决于很多因素,包括您拥有的数据类型:结论可能是numpy或Counter会提供加速,不需要外部库的计数器
调用list.count
非常昂贵。字典访问(O(1)摊销时间)和in
运营商,但是相对便宜。以下片段显示了更好的时间复杂度。
def stats(lines):
histogram = {}
for s in lines:
if s in histogram:
histogram[s] += 1
else:
histogram[s] = 1
return histogram
这对于'pyspark'来说可能足够大了,它将非常适合这类问题。 –
是否愿意使用非纯Python包(如numpy或pyspark?)。 –
另外,我编辑了你的代码,以便它可以通过使用正确的大括号正确运行 - 我知道编辑代码通常不被看好(它看起来像是一个非常明显的错字),但是如果你的意思是由于某种原因,原始回退编辑 –