@leon, your last question (What if A is a multiple column matrix?) requires pointing to the Matlab documentation for the accumarray()
function and specifying exactly what you need, as all the available features and options seem to be massive.
Here is a quick & dirty attempt that worked for 2 out of the 3 Matlab examples tried from the link above. The failure occured for the Int8
example. I tried to use reduce(+,...)
instead of sum()
to avoid auto-promotion but I got something else. Actually, I do not understand what Matlab is doing in that example.
function accumarray1(A::Matrix{Int64}, B::AbstractArray, fun::Function, T::Type)
N = size(A,2)
mx = maximum(A, dims=1)
C = zeros(T, mx[1], mx[2:N]...)
if fun == sum
Ci = vcat([reduce(+, B[i .β A[:,1],:], dims=1) for i in unique(A[:,1])]...)
else
Ci = vcat([fun(B[i .β A[:,1],:], dims=1) for i in unique(A[:,1])]...)
end
for ri in collect(eachrow(A))
C[ri...] = Ci[ri[1]]
end
return C
end
# Matlab example-1: OK
B = 1:6 # data input
A = [1 1; 2 2; 3 2; 1 1; 2 2; 4 1] # indices on first column, output to row N-d index
accumarray1(A, B, sum, Int64)
4Γ2 Matrix{Int64}:
5 0
0 7
0 3
6 0
# Matlab example-2: OK
using Statistics
B = [100.1, 101.2, 103.4, 102.8, 100.9, 101.5]
A = [1 1; 1 1; 2 2; 3 2; 2 2; 3 2]
accumarray1(A, B, var, Float64)
3Γ2 Matrix{Float64}:
0.605 0.0
0.0 3.125
0.0 0.845
# Matlab example-3: Not OK, but do not understand Matlab output with 4 different values?
B = Int8.(10:15)
A = [1 1 1; 1 1 1; 1 1 2; 1 1 2; 2 3 1; 2 3 2]
accumarray1(A, B, sum, Int8)
2Γ3Γ2 Array{Int8, 3}:
[:, :, 1] =
46 0 0
0 0 29
[:, :, 2] =
46 0 0
0 0 29