Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Count instances of each unique integer in a vector in 1 line of code?

Tags:

julia

Is there a slick way to rewrite this Julia function, perhaps using just 1 line of code, without making it much slower? (I just started using Julia. It's great!) K is a positive integer and zd is a vector of positive integers no greater than K. Thanks!

function tally(zd)
    ret = zeros(Int64, K)
    for k in zd
        ret[k] += 1
    end
    return ret 
end

Example:

julia> K = 5
julia> zd = [1,2,2,2,2,3];
julia> tally(zd)
5-element Array{Float64,1}:
 1
 4
 1
 0
 0
like image 379
Jeff Avatar asked Jan 16 '14 20:01

Jeff


5 Answers

I know its old but how about

[sum(zd .== i) for i in unique(zd)]

in a short test it performed better than your initial function (time and memory wise).

Caution: result not sorted!

like image 163
niko Avatar answered Dec 09 '22 20:12

niko


Any alternative probably will not be faster. Your loop already does only one pass through the array. Julia loops are fast, and there is no speed advantage to vectorized code, as there is in other languages.

Have a look at Julia's implementation of the hist function. This is taken directly from the Julia Standard Library:

function hist(v::AbstractVector, edg::AbstractVector)
    n = length(edg)-1
    h = zeros(Int, n)
    for x in v
        i = searchsortedfirst(edg, x)-1
        if 1 <= i <= n
            h[i] += 1
        end
    end
    edg,h
end

The "edg" parameter contains the edges of the bins. If we remove that feature, we get exactly the function you wrote.

EDIT hist has not been available in Julia Base since v0.5.0

like image 38
DanielC Avatar answered Dec 09 '22 20:12

DanielC


Here http://statsbasejl.readthedocs.org/en/latest/counts.html#countmap

countmap(x[, wv])
Return a dictionary that maps distinct values in x to their counts (or total weights).
like image 25
Bogdan Ruzhitskiy Avatar answered Dec 09 '22 19:12

Bogdan Ruzhitskiy


I haven't tested the performance, but using the hist function should work:

hist(zd,0.5:K+0.5)[2]

gives:

5-element Array{Int64,1}: 1 4 1 0 0

or, if the zeros are unimportant, just use

hist(zd)[2]
3-element Array{Int64,1}:
 1
 4
 1
like image 45
meggart Avatar answered Dec 09 '22 20:12

meggart


There are a bunch of counting functions included in the StatsBase.jl package. Your tally function is equivalent to counts(zd, 1:K).

There are also methods for counting unique elements of types other than integer, too, such as countmap, which returns a dictionary mapping unique values to their number of occurrences.

like image 38
mbauman Avatar answered Dec 09 '22 20:12

mbauman