Tiling or repeating n-dimensional arrays in Julia - matrix

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

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

Language Julia: convert vector in matrix

Who can help.
To transform a vector into a one-dimensional matrix just run in Julia:
a = copy(permutedims([1,2,3]))
To transform the matrix "a" into a vector just use:
b = copy(vec(a))
If you have a matrix "[1 2 3; 4 5 6]" to transform it into a vector, just:
c = vec([1 2 3; 4 5 6])
Now how to make the vector have the form of the 2x3 matrix like:
2×3 Matrix{Int64}:
1 2 3
4 5 6
You can use reshape
julia> c = vec([1 2 3; 4 5 6])
6-element Vector{Int64}:
1
4
2
5
3
6
julia> M=reshape(c,2,3)
2×3 Matrix{Int64}:
1 2 3
4 5 6
Note that this operation does not reallocate memory, c and M share the same memory. By example:
julia> c[1]=10
10
julia> M
2×3 Matrix{Int64}:
10 2 3
4 5 6

Ranking over each matrix column's sort in julia

I have a matrix (m) of scores for 4 students on 3 different exams.
4 3 1
3 2 5
8 4 6
1 5 2
I want to know, for each student, the exams they did best to worse on. Desired output:
1 2 3
2 3 1
1 3 2
3 1 2
Now, I'm new to the language (and coding in general), so I read GeeksforGeeks' page on sorting in Julia and tried
mapslices(sortperm, -m; dims = 2)
However, this gives something subtly different: a matrix of each row being the index of the sorting.
1 2 3
3 1 2
1 3 2
2 3 1
Perhaps it was obvious, but I now realize this is not actually what I want, but I cannot find a built-in function/fast way to complete this operation. Any ideas? Preferably something which doesn't iterate through items in the matrix/row, as in reality my matrix is very, very large. Thanks!
Such functionality is provided by StatsBase.jl. Here is an example:
julia> using StatsBase
julia> m = [4 3 1
3 2 5
8 4 6
1 5 2]
4×3 Array{Int64,2}:
4 3 1
3 2 5
8 4 6
1 5 2
julia> mapslices(x -> ordinalrank(x, rev=true), m, dims = 2)
4×3 Array{Int64,2}:
1 2 3
2 3 1
1 3 2
3 1 2
You might want to use other rank, depending on how you want to split ties, see here for details.
Figured out something which works!
Run m_index_rank = mapslices(sortperm, -m; dims = 2) on the matrix and get a ranking for each row through index. Then, realizing this is, in each row, an inverse permutation away from the desired output, run mapslices(invperm, m_index_rank; dims = 2) for the desired result.
In one line, this is mapslices(r -> invperm(sortperm(r, rev=true)), m; dims=2) over the desired matrix m. dims = 2 is to carry out the operation row-wise.
I'm marking this resolved for now, but please let me know if there are cleaner/faster ways to do this.
Edit: Replaced my syntactically clunky mapslices(invperm, mapslices(sortperm, -m; dims = 2); dims = 2) with a more natural one, thanks to #phipsgabler

Matrices in Julia - Sorting and Sort Permutations

How can matrices be sorted in Julia.
Let's define a matrix:
a = [1 1 1;
1 3 1;
1 2 2;
1 2 1]
I'm looking for several things here:
Sort by multiple Columns
So, you can sort the matrix by all columns from left to right with
sortslices(a, dims = 1)
4×3 Array{Int64,2}:
1 1 1
1 2 1
1 2 2
1 3 1
Sort by particular Column Order
But what if want to sort by the 3rd then the 2nd and then the 1st column? Expected output:
4×3 Array{Int64,2}:
1 1 1
1 2 1
1 3 1
1 2 2
Sort permutation
Let's assume I had a Vector
b = ["a", "d", "c", "b"]
and I would like to sort its elements by the sort permutation of the matrix' columns. As seen above sortslices() let's me sort the matrix so I get the rows in the order [1,4,3,2]. How can I get this vector to sort b to
4-element Array{String,1}:
"a"
"b"
"c"
"d"
I know there are other similar questions, but they seem either address other issues or they seem to be outdated (e.g. Julia: Sort Matrix by column 2 then 3).
It isn't ideal to ask multiple questions within a single post. It makes searching for questions much harder.
Anyway, here we go:
Sort by multiple Columns
julia> a = [1 1 1;
1 3 1;
1 2 2;
1 2 1]
4×3 Matrix{Int64}:
1 1 1
1 3 1
1 2 2
1 2 1
julia> sortslices(a, dims = 1, by=x->(x[1], x[2], x[3]))
4×3 Matrix{Int64}:
1 1 1
1 2 1
1 2 2
1 3 1
Sort by particular Column Order
julia> a = [1 1 1;
1 3 1;
1 2 2;
1 2 1]
4×3 Matrix{Int64}:
1 1 1
1 3 1
1 2 2
1 2 1
julia> sortslices(a, dims = 1, by=x->(x[3], x[2], x[1]))
4×3 Matrix{Int64}:
1 1 1
1 2 1
1 3 1
1 2 2
Sort permutation
julia> b = ["a", "d", "c", "b"]
4-element Vector{String}:
"a"
"d"
"c"
"b"
julia> sortperm(b)
4-element Vector{Int64}:
1
4
3
2
julia> b[sortperm(b)]
4-element Vector{String}:
"a"
"b"
"c"
"d"
Building on #mcabbot's comment, I think that by clause is unnecessary. This suffices: p = sortperm(collect(eachrow(a))).
Whether this is the most performant solution, I don't know.

Example of compress column format for rank-deficient matrices

It is the first time I deal with column-compress storage (CCS) format to store matrices. After googling a bit, if I am right, in a matrix having n nonzero elements the CCS is as follows:
-we define a vector A_v of dimensions n x 1 storing the n non-zero elements
of the matrix
- we define a second vector A_ir of dimensions n x 1 storing the rows of the
non-zero elements of the matrix
-we finally define a third vector A_jc whose elements are the indices of the
elements of A_v which corresponds to the beginning of new column, plus a
final value which is by convention equal t0 n+1, and identifies the end of
the matrix (pointing theoretically to a virtual extra-column).
So for instance,
if
M = [1 0 4 0 0;
0 3 5 2 0;
2 0 0 4 6;
0 0 7 0 8]
we get
A_v = [1 2 3 4 5 7 2 4 6 8];
A_ir = [1 3 2 1 2 4 2 3 3 4];
A_jc = [1 3 4 7 9 11];
my questions are
I) is what I wrote correct, or I misunderstood anything?
II) what if I want to represent a matri with some columns which are zeroes, e.g.,
M2 = [0 1 0 0 4 0 0;
0 0 3 0 5 2 0;
0 2 0 0 0 4 6;
0 0 0 0 7 0 8]
wouldn't the representation of M2 in CCS be identical to the one of M?
Thanks for the help!
I) is what I wrote correct, or I misunderstood anything?
You are perfectly correct. However, you have to take care that if you use a C or C++ library offsets and indices should start at 0. Here, I guess you read some Fortran doc for which indices are starting at 1. To be clear, here is below the C version, which simply translates the indices of your Fortran-style correct answer:
A_v = unmodified
A_ir = [0 2 1 0 1 3 1 2 2 4] (in short [1 3 2 1 2 4 2 3 3 4] - 1)
A_jc = [0 2 3 6 8 10] (in short [1 3 4 7 9 11] - 1)
II) what if I want to represent a matri with some columns which are
zeroes, e.g., M2 = [0 1 0 0 4 0 0;
0 0 3 0 5 2 0;
0 2 0 0 0 4 6;
0 0 0 0 7 0 8]
wouldn't the representation of M2 in CCS be identical to the one of M?
I you have an empty column, simply add a new entry in the offset table A_jc. As this column contains no element this new entry value is simply the value of the previous entry. For instance for M2 (with index starting at 0) you have:
A_v = unmodified
A_ir = unmodified
A_jc = [0 0 2 3 6 8 10] (to be compared to [0 2 3 6 8 10])
Hence the two representations are differents.
If you just start learning about sparse matrices there is an excelllent free book here: http://www-users.cs.umn.edu/~saad/IterMethBook_2ndEd.pdf

Resources