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