Performance optimization of a custom binning function

Turns out, I had only to give up on using clever BlockedArrays, and the compact function actually benchmarked faster than bin5:

function bin4(x, y, b, f = mean)
    p = sortperm(vcat(x,b))
    bins = findall(p.>length(x))
    x_binned = [f(x[p[k]] for k in bins[i]+1:bins[i+1]-1)
                  for i in 1:length(b)-1]
    y_binned = [f(y[p[k],t] for k in bins[i]+1:bins[i+1]-1)
                  for i in 1:length(b)-1, t in 1:size(y,2)]
    return x_binned, y_binned, diff(bins).-1
end

(and it doesn’t need sorted bin_edges)

julia> @btime bin4($x, $y, $xbin_edges);
  41.895 μs (14 allocations: 21.52 KiB)

julia> @btime bin5($x, $y, $xbin_edges);
  46.254 μs (118 allocations: 40.41 KiB)

Edit: Sacrificing clarity, the function can be made to fit into the 7-line category of this thread https://discourse.julialang.org/t/seven-lines-of-julia-examples-sought/50416/1 :

function bin6line(x, y, b, f = mean)
    p = sortperm(vcat(x,b))
    bins = findall(p.>length(x))
    aggr = @views [f(z[p[bins[i]+1:bins[i+1]-1]]) for i in 1:length(b)-1, z in (x, eachcol(y)...) ]
    return @view(aggr[:,1]), @view(aggr[:,2:end]), diff(bins).-1
end
2 Likes