对计数器进行排序(并提取最常见的值)

时间:2014-09-03 04:34:12

标签: julia

DataStructures.jl提供了一组很棒的工具,其中一个是counter。相应的Python对象Counter提供了most_common方法。如何在朱莉娅实施?

2 个答案:

答案 0 :(得分:3)

可以通过select!完成繁重的工作。以下内容应该重现Python中most_common的行为:

using DataStructures

most_common(c::Accumulator)    = most_common(c, length(c))
most_common(c::Accumulator, k) = select!(collect(c), 1:k, by=kv->kv[2], rev=true)

直到Julia获得专注于函数参数by=kv->kv[2](计划中)的能力,并且直到索引到返回视图(也是计划的),它将会有性能影响,它将执行不必要的复制以创建正确长度的输出向量。但只要它不是性能关键,上面应该可以正常工作。

性能问题当然可以通过更谨慎,低级别的实现来处理。我不知道现有的功能,但它可能是DataStructures.jl或Julia本身的一个有价值的补充。对于不是计数器或累加器的关联集合也是有意义的,但是应该将其命名为其他东西。

答案 1 :(得分:0)

要更新此问题,我正在使用Julia v1.2.1,并且没有select! afaik。

这是我使用的@Toivo实现的一个小修改:

using DataStructures

most_common(c::Accumulator) = most_common(c, length(c))
most_common(c::Accumulator, k) = sort(collect(c), by=kv->kv[2], rev=true)[1:k]

这将返回一个具有::Array{Pair{String,Int}},1个成员的k,类似于Python Counter.most_common(k),该Python返回一个由k组成的元组对的列表。

示例:

使用Python Counter和Julia DataStructures.counter在“哈姆雷特”中找到十个最常见的单词。

Python:

>>> import re
>>> words = re.findall(r'\w+', open('hamlet.txt').read().lower())
>>> Counter(words).most_common(10)
[('the', 1143), ('and', 966), ('to', 762), ('of', 669), ('i', 631),
 ('you', 554),  ('a', 546), ('my', 514), ('hamlet', 471), ('in', 451)]

朱莉娅:

> import DataStructures: counter
> open("hamlet.txt") do f
>     words = matchall(r"\w+", read(f, String))
>     counter(words)|> most_common
> end
10-element Array{Pair{Any,Int64},1}:
"the" => 1143
"and" => 966
"to" => 762
 ...

我没有足够的经验来评论效率,但是很想听听专家的意见。