# Finding row index of matrix

Hi,
I have two matrices :

``````b =
6×2 Array{Int64,2}:
0  2
1  4
0  7
1  4
1  5
2  4
``````

and

``````a =
6×2 Array{Int64,2}:
0  2
0  7
1  4
1  4
1  5
2  4
``````

I need to find row index, i of matrix b with respect to a. i.e. a = b(i)

``````and get output as array:
1
3
2
5
4
``````

I tried using functions like findall but haven’t got this desired output

I will not give you a solution but I will at least share that what you are after is (row) permutation. Either represented by a permutation vector (the one that you call row indices) or a permutation matrix.

For convenience I reenter your matrices here (please next time make it easier for others to help you by putting such code here)

``````B = [0  2; 1  4; 0  7; 1  4; 1  5; 2  4]
A = [0  2; 0  7; 1  4; 1  4; 1  5; 2  4]
``````

The permutation vector is

``````p = [1,3,2,4,5,6]
``````

There is a fuction called permute! in Julia, but it only works for vectors and not matrices. We could perhaps reformat the matrix into a vector of row vectors but I will not do it here. Instead, I will form a permutation matrix

``````julia> using LinearAlgebra

julia> P = 1I(6)[p,:]
6×6 SparseArrays.SparseMatrixCSC{Int64, Int64} with 6 stored entries:
1  ⋅  ⋅  ⋅  ⋅  ⋅
⋅  ⋅  1  ⋅  ⋅  ⋅
⋅  1  ⋅  ⋅  ⋅  ⋅
⋅  ⋅  ⋅  1  ⋅  ⋅
⋅  ⋅  ⋅  ⋅  1  ⋅
⋅  ⋅  ⋅  ⋅  ⋅  1
``````

and use it to permute the rows of the matrix `B` just by premultiplication.

``````julia> A == P*B
true
``````

Well, I did not help solve the problem (I did not show how to find the vector `p` or the matrix `P`, I only interpreted them) but at least you may have another keyword to search for. Your are trying to find a permutation matrix (or the corresponding vector) to transform one matrix into another by premultiplication. I am afraid you would just have to loop over the rows of the matrices.

3 Likes

Thanks

This one almost works, although it does not increment for duplicate row entries:

``````map(eachrow(b)) do r
findfirst(i->view(a,i,:)==r, 1:size(a,1))
end
``````
``````6-element Vector{Int64}:
1
3
2
3
5
6
``````

To fix this for repeated elements, something like this works:

``````a = [0 2; 0 7; 1 4; 1 4; 1 5; 2 4]
b = [0 2; 1 4; 0 7; 1 4; 1 5; 2 4]

# Build up a dict mapping each row to the row numbers where the row occurs
l = Dict{Vector{Int}, Vector{Int}}()
foreach(1:size(a,1)) do i
r = a[i,:]
push!(l[r], i)
else
l[r] = [i]
end
end
# And collect the values according to their occurences
map(eachrow(b)) do r
popfirst!(l[r])
end
``````
``````6-element Vector{Int64}:
1
3
2
4
5
6
``````
4 Likes

Another take:

``````function findrowindex(a,b)
c = fill(0,size(a,1))
for i in axes(a,1)
for j in axes(b,1)
@views if (b[j,:] == a[i,:]) & !(j in c)
c[i] = j
@goto outerloop
end
end
@label outerloop
end
return c
end
``````

NB: the goto is not needed but aims at speeding up function

``````c = findrowindex(a,b)
6-element Vector{Int64}:
1
3
2
4
5
6
b[c,:] == a     # true
``````
1 Like

Is this correct? The original question has 6 rows, but a 5-vector answer. Some rows are repeated.

My guess from the words was `indexin`, and possibly `unique`, but…

``````julia> q = indexin(collect(eachrow(A)), collect(eachrow(B)))
6-element Vector{Union{Nothing, Int64}}:
1
3
2
2
5
6

julia> A == B[q, :]
true

julia> res = [1, 3, 2, 5, 4];  # from question

julia> B[res, :]  # not the same shape as A
5×2 Matrix{Int64}:
0  2
0  7
1  4
1  5
1  4

julia> B[unique(q), :]
5×2 Matrix{Int64}:
0  2
0  7
1  4
1  5
2  4

julia> indexin(collect(eachrow(B)), collect(eachrow(A))) # reversed, matches @fabiangans's map(eachrow(b))
6-element Vector{Union{Nothing, Int64}}:
1
3
2
3
5
6
``````
2 Likes