let indexing return a matrix instead of a vector in julia - matrix

When you index a matrix in Julia, and your selection is a single column or row the result will be represented as a vector. similarly, when you index a single point you get the value of that point, not a 1x1 matrix.
However, for my use case I want my answer to be a matrix as well, because the orientation of the vector has meaning, that I don't want to lose.
So given the following example matrix:
julia> A = [1 2; 3 4]
2×2 Matrix{Int64}:
1 2
3 4
I get:
julia> A[:, 1]
2-element Vector{Int64}:
1
3
julia> A[1, :]
2-element Vector{Int64}:
1
2
julia> A[1, 1]
1
but I want:
julia> A[:, 1]
2×1 Matrix{Int64}:
1
3
julia> A[1, :]
1×2 Matrix{Int64}:
1 2
julia> A[1, 1]
1×1 Matrix{Int64}:
1
Is there an easy way to achieve this?
Right now I do something like:
function getindex_asmatrix(A::Matrix, i, j)
# If i & j are Integers convert point to 1x1 Matrix
# If only j == Integer make a nx1 Matrix
# If only i == Integer make a 1xm Matrix
# else do A[i, j]
end
But I feel there might be an more elegant solution.

Just use 1:1 (range) instead of 1, e.g.:
julia> A[:, 1:1]
2×1 Matrix{Int64}:
1
3
julia> A[1:1, :]
1×2 Matrix{Int64}:
1 2
julia> A[1:1, 1:1]
1×1 Matrix{Int64}:
1
You could also use [1] instead, but it will allocate, while 1:1 does not allocate.

Related

Intersection of two matrices in Julia?

Is there any function or method in Julia that would allow one to compute the intersection of two matrices A and B?
There are many possible definitions for intersection.
Suppose that you have:
julia> a=[1 2 3;4 5 6;3 2 1]
3×3 Matrix{Int64}:
1 2 3
4 5 6
3 2 1
julia> b = a'
3×3 adjoint(::Matrix{Int64}) with eltype Int64:
1 4 3
2 5 2
3 6 1
and if you mean by intersection you mean matrix with elements who have the same values in both matrices and zero otherwise you could do:
julia> (a .== b) .* a
3×3 Matrix{Int64}:
1 0 3
0 5 0
3 0 1

Julia: find row in matrix

Using Julia, I'd like to determine if a row is located in a matrix and (if applicable) where in the matrix the row is located. For example, in Matlab this can done with ismember:
a = [1 2 3];
B = [3 1 2; 2 1 3; 1 2 3; 2 3 1]
B =
3 1 2
2 1 3
1 2 3
2 3 1
ismember(B, a, 'rows')
ans =
0
0
1
0
From this, we can see a is located in row 3 of B. Is there a similar function to accomplish this in Julia?
You can also make use of array broadcasting by simply testing for equality (.==) without the use of comprehensions:
all(B .== a, dims=2)
Which gives you:
4x1 BitMatrix:
0
0
1
0
You can then use findall on this array:
findall(all(B .== a, 2))
However, this gives you a vector of CartesianIndex objects:
1-element Vector{CartesianIndex{2}}:
CartesianIndex(3, 1)
So if you expect to find multiple rows with the value defined in a you can either:
simplify this Vector by taking only the row index from each CartesianIndex:
[cart_idx[1] for cart_idx in findall(all(B .== a, 2))]
or pass one dimensional BitMatrix to findall (as suggested by Shep Bryan in the comment):
findall(all(B .== a, dims=2)[:, 1])
Either way you get an integer vector of column indices:
1-element Vector{Int64}:
3
Another pattern is using array comprehension:
julia> Bool[ a == B[i,:] for i=1:size(B,1) ]
4-element Array{Bool,1}:
false
false
true
false
julia> Int[ a == B[i,:] for i=1:size(B,1) ]
4-element Array{Int64,1}:
0
0
1
0
how about:
matchrow(a,B) = findfirst(i->all(j->a[j] == B[i,j],1:size(B,2)),1:size(B,1))
returns 0 when no matching row, or first row number when there is one.
matchrow(a,B)
3
should be as "fast as possible" and pretty simple too.
Though Julia doesn't have a built-in function, its easy enough as a one-liner.
a = [1 2 3];
B = [3 1 2; 2 1 3; 1 2 3; 2 3 1]
ismember(mat, x, dims) = mapslices(elem -> elem == vec(x), mat, dims)
ismember(B, a, 2) # Returns booleans instead of ints

Function or operator for matrix exponential in Julia

I am looking for a function or operator
that computes the n-th matrix exponential in Julia
where n is a non-negative integer.
For example, in MATLAB I would write expm(A, 3) for A * A * A.
I could just call the product using * multiple times,
but is there a way to compute the matrix exponential
without doing this?
julia> A = [1 -1; 0 2]
2x2 Array{Int64,2}:
1 -1
0 2
julia> A * A
2x2 Array{Int64,2}:
1 -3
0 4
julia> A * A * A
2x2 Array{Int64,2}:
1 -7
0 8
Simply use the exponentiation operator.
julia> A = [1 -1; 0 2]
2x2 Array{Int64,2}:
1 -1
0 2
julia> A^2
2x2 Array{Int64,2}:
1 -3
0 4
julia> A^3
2x2 Array{Int64,2}:
1 -7
0 8
To find out where it's implemented, you can use the function methods
julia> methods(^)
# 45 methods for generic function "^":
...
^(A::Array{T,2}, p::Integer) at linalg/dense.jl:170
^(x, p::Integer) at intfuncs.jl:108
^(A::Array{T,2}, p::Number) at linalg/dense.jl:173
Given that information, you can find it in the Julia repository.

julia find in matrix with (row,col) instead of index

In Julia you can find the coordinates of elements in a matrix via:
julia> find( x -> x == 2, [ 1 2 3; 2 3 4; 1 0 2] )
3-element Array{Int64,1}:
2
4
9
These values are correct but I would prefer that I would get the (row,col) tuples instead.
(1,2)
(2,1)
(3,3)
What is the easiest way to achieve this in Julia?
I don't believe there is an inbuilt way to do it, but here is a function to do it
function findmat(f, A::AbstractMatrix)
m,n = size(A)
out = (Int,Int)[]
for i in 1:m, j in 1:n
f(A[i,j]) && push!(out,(i,j))
end
out
end
e.g.
julia> findmat(x->x==2, [ 1 2 3; 2 3 4; 1 0 2] )
3-element Array{(Int64,Int64),1}:
(1,2)
(2,1)
(3,3)
If a large number of items satisfy the condition it might be more efficient to do it in two passes, but I doubt it.
Edit:
For newer versions of Julia replace
out = (Int,Int)[]
with
out = Tuple{Int, Int}[]
In case anyone else finds this you can now use:
ind2sub(a, index)
It returns a tuple of subscripts into array a corresponding to the linear index index
The closest thing that I can find in the Julia standard library is findn :
julia> A = [1 2 3; 2 3 4; 1 0 2]
3x3 Array{Int64,2}:
1 2 3
2 3 4
1 0 2
julia> findn(A .== 2)
([2,1,3],[1,2,3])
This gives a tuple of vectors instead of a vector of tuples, though.
Another thing to note is that the match at (2,1) is reported before the one at (1,2). This is because arrays in Julia are stored in column major order, so scanning the array A in storage order will look at the position (2,1) before (1,2).
if you wish to avoid defining "new" functions, perhaps:
collect(zip(ind2sub((3,3),find( x -> x == 2, [ 1 2 3; 2 3 4; 1 0 2] ))...))
is what you are looking for. the (3,3) is implicit in the size of the matrix. if the matrix was given by a variable it would look more natural with a size(M)
on julia 1.7, find does not exist (it was deprecated on julia 1.0), findall is the equivalent that gives the same result as the original question.
On matrices, findall will return CartesianIndex locations:
julia> idx = findall( x -> x == 2, [ 1 2 3; 2 3 4; 1 0 2])
3-element Vector{CartesianIndex{2}}:
CartesianIndex(2, 1)
CartesianIndex(1, 2)
CartesianIndex(3, 3)
julia> ans[1][1]
2

Tiling or repeating n-dimensional arrays in Julia

I am looking for a general function to tile or repeat matrices along an arbitrary number of dimensions an arbitrary number of times. Python and Matlab have these features in NumPy's tile and Matlab's repmat functions. Julia's repmat function only seems to support up to 2-dimensional arrays.
The function should look like repmatnd(a, (n1,n2,...,nk)). a is an array of arbitrary dimension. And the second argument is a tuple specifying the number of times the array is repeated for each dimension k.
Any idea how to tile a Julia array on greater than 2 dimensions? In Python I would use np.tile and in matlab repmat, but the repmat function in Julia only supports 2 dimensions.
For instance,
x = [1 2 3]
repmatnd(x, 3, 1, 3)
Would result in:
1 2 3
1 2 3
1 2 3
1 2 3
1 2 3
1 2 3
1 2 3
1 2 3
1 2 3
And for
x = [1 2 3; 1 2 3; 1 2 3]
repmatnd(x, (1, 1, 3))
would result in the same thing as before. I imagine the Julia developers will implement something like this in the standard library, but until then, it would be nice to have a fix.
Use repeat:
julia> X = [1 2 3]
1x3 Array{Int64,2}:
1 2 3
julia> repeat(X, outer = [3, 1, 3])
3x3x3 Array{Int64,3}:
[:, :, 1] =
1 2 3
1 2 3
1 2 3
[:, :, 2] =
1 2 3
1 2 3
1 2 3
[:, :, 3] =
1 2 3
1 2 3
1 2 3

Resources