Accessing pair of row elements in array in Julia - julia

Suppose I have a following Array
A = [1 2; 1 3; 1 5; 2 1; 2 3; 2 4; 3 1; 3 3; 3 4; 3 1; 4 2; 4 3; 4 5; 5 2; 5 3; 5 5]
What is one liner in Julia to find if a pair of row elements exist in given array A. For example, one liner must return false for [1 4] as [1 4] row does not exist in A, and return true for [3 4]. I gave it a try in following manner where
[3 4] .== A
returns
0 1
1 0
1 0
1 1
1 0
whereas I want my output to be only "true" for
1 1

eachrow allows iterating on the rows of a matrix, which you can simply combine with in, which checks whether an element is in a collection:
julia> A = [1 2; 1 3; 1 5; 2 1; 2 3; 2 4; 3 1; 3 3; 3 4; 3 1; 4 2; 4 3; 4 5; 5 2; ];
julia> [1, 4] in eachrow(A)
false
julia> [3, 4] in eachrow(A)
true
Another solution, more in line with your initial attempt would be something along the lines of:
julia> Ref([3, 4]) .== eachrow(A)
16-element BitArray{1}:
0
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
julia> any(Ref([3,4]) .== eachrow(A))
true

Related

Efficient way to copy a matrix except for one column

Consider a matrix where you don't need the third column:
X = zeros(Int64, (4, 3));
X[:, 1] = [0, 0, 1, 1];
X[:, 2] = [1, 2, 1, 2];
julia> X
4×3 Matrix{Int64}:
0 1 0
0 2 0
1 1 0
1 2 0
So you want to select (copy) everything except column 3:
4×2 Matrix{Int64}:
0 1
0 2
1 1
1 2
Is there a shorthand way to express this?
These work, but feel impractical when you have a large number of columns:
X[:, [1, 2]]
X[:, sort(collect(setdiff(Set([1, 2, 3]), Set([3]))))]
There are plenty of ways to do this. Below is a solution in which you express which ranges of column numbers to include:
X = zeros(Int64, (8, 3));
X[:, 1] = [0, 0, 0, 0, 1, 1, 1, 1];
X[:, 2] = [1, 1, 2, 2, 1, 1, 2, 2];
return X[:,1:2] #Columns 1 through 2 are being directly included.
Alternatively, you could express which you would like to exclude, which is perhaps a more widely useful version of the code:
return X[:, 1:end .!= 3] #column number 3 is being directly excluded.
Both of which would return:
8×2 Matrix{Int64}:
0 1
0 1
0 2
0 2
1 1
1 1
1 2
1 2
If it is some column in the middle you can get perhaps get most elegant code by using InvertedIndices. (This also gets loaded by other packages such as DataFrames).:
julia> A = collect(reshape(1:16,4,4))
4×4 Matrix{Int64}:
1 5 9 13
2 6 10 14
3 7 11 15
4 8 12 16
julia> A[:, Not(3)]
4×3 Matrix{Int64}:
1 5 13
2 6 14
3 7 15
4 8 16

Assignement in matrixes using double indexes

I can't figure out how to obtain this behavior:
From this matrix:
julia> a = [1 1 1; 1 1 1; 1 1 2]
3×3 Array{Int64,2}:
1 1 1
1 1 1
1 1 2
I want to change all the 1s to 5s but only in the last row.
What I did is a[3, :][a[3, :] .== 1] .= 5 but the value of a isn't changed.
I've noticed that with:
foo[foo .== 1] .= 5
a[3, :] = foo
It works, but I'm trying to reduce allocations and this should be removed.
Thanks in advance
You can use #view and replace!:
julia> a = [1 1 1
1 1 1
1 1 2]
3×3 Array{Int64,2}:
1 1 1
1 1 1
1 1 2
julia> replace!(#view(a[end, :]), 1 => 5)
3-element view(::Array{Int64,2}, 3, :) with eltype Int64:
5
5
2
julia> a
3×3 Array{Int64,2}:
1 1 1
1 1 1
5 5 2
The problem is
a[3, :][a[3, :] .== 1] .= 5
is the same as getindex(a, 3, :)[a[3, :] .== 1] .=5
getindex returns a copy of that part of a
You are mutating the copy, not the original a
You want to use a view
view(a, 3, :)[a[3, :] .== 1] .=5
You can also do this with the #view or #views macro.

Create a mask array, where `1` are at max value index of given array

Given a matrix A = [1 5 3; 4 2 6]. How to create a new mask matrix where 1 values are at column-wise maximum value index mask = [0 1 0; 1 0 1]. How to do this in julia without mutating any created arrays.
With mutation I'm doing it the following way.
maxval, maxind = findmax(A, dims=1)
mask = zeros(size(A))
mask[maxind] .= 1
There's really nothing wrong with what you have (although I'd probably use falses instead of zeros). You could alternatively use broadcast, but I'd expect it to have similar performance:
julia> A = [1 5 3; 4 2 6]
2×3 Array{Int64,2}:
1 5 3
4 2 6
julia> A .== maximum(A, dims=1)
2×3 BitArray{2}:
0 1 0
1 0 1
(Note that unlike Python, we differentiate between matrices and vectors of vectors; you wrote them like the latter)

How to find the index of the column of the minimum nonzero element across rows in Julia?

I have an nxm Array{Int64,2} in Julia. I would like to find for each row, the index of the column of the minimum element that is not zero. If the row is zero then return 0.
For example, for n=10 and m=2 and
julia> A
10×2 Array{Int64,2}:
2 0
1 1
8 7
0 0
3 8
0 0
0 0
2 4
5 1
6 0
I would like to return
julia> B
10-element Array{Int64,1}:
1
1
2
1
1
1
1
1
2
1
What I did is this:
B = zeros(Int64, n);
for i in 1:n
B[i] = findmin(A[i, :])[2];
end
but this does not work when there is a zero in some row...
You can also use mapslices and specify your function that works for a single row.
First, set up a matrix:
julia> A = [2 1; 1 2; -1 -2; 0 0; 0 5; 10 0]
6×2 Array{Int64,2}:
2 1
1 2
-1 -2
0 0
0 5
10 0
Create a function that finds the index of the minimal non-zero elements per row:
function findmincol(row)
# handle the special case when all elements are 0
if all(row .== 0)
return 0
end
# check the number of zero elements
length_zero = sum(row .== 0)
# find the min among non-zero elements
filter!(x -> x != 0, row)
return findmin(row)[2] + length_zero
end
Then you can use mapslices to map the the findmincol function to each row of A:
mapslices(findmincol, A, dims=2)
This gives you (what I think is) the correct solution:
6×1 Array{Int64,2}:
2
1
2
0
2
1
Most functions (sum, minimum, find, findmin, etc) take a dims keyword argument to specify the axis along which to do said operation:
Ex
findmin(rand(3, 4), dims=1)
([0.15952 0.0289172 0.409214 0.195433], CartesianIndex{2}[CartesianIndex(3, 1)
CartesianIndex(2, 2) CartesianIndex(3, 3) CartesianIndex(3, 4)])
returns the actual minima and the locations, as Cartesian Indices, as two separate arrays
So:
v, i = findmin(randn(10, 2), dims=2)
i = map(t -> t[2], i)
i[v .== 0] .= 0
The Cartesian Index is a little weird, but apparently used frequently for multi-dimensional indexing

How to define a matrix using if and for loops in sagemath?

I am using sagemath for my computations.
Now, from R I have the codes to generate a matrix of size $2r\times 2r$ from the following codes..
n=10
k=10
r=5
x=matrix(data=NA, nrow=n, ncol=k)
for(j in 1:k){
for(i in 1:n){
if (i==j){x[i,j]=0}
if ((i<=r)&(i<j)&(j<=r)) {x[i,j]=2}
if ((i<=r)&(i>j)&(j<=r)) {x[i,j]=2}
if ((i<=r)&(j>r)){x[i,j]=1}
if ((i>r)&(j<=r)) {x[i,j]=1}
if ((i>r)&(j>r)){x[i,j]=0}
if ((i>r)& (i<j) &(j>r)){x[i,j]=2}
if ((i>r)& (i>j) &(j>r)){x[i,j]=2}
}
}
x
How can I do the same in SageMath?
When constructing a matrix in Sagemath, you can pass in a function that computes its entries, which eliminates the need for explicit (and generally inefficient) loops. This function is defined below as xentries: I used the same conditionals as in your post, but grouped them for readability.
def xentries(i, j, r):
if i == j or (i > r and j > r):
return 0
if (i <= r and j > r) or (i > r and j <= r):
return 1
return 2
n = 10
k = 10
r = 5
x = matrix(ZZ, n, k, lambda i, j: xentries(i, j, r))
Here, ZZ means the integers, and is used to indicate that the matrix has integer entries. It could be rational QQ or real RR. The other arguments are the size of the matrix, and the function that constructs its entries. The matrix x is now the following:
[0 2 2 2 2 2 1 1 1 1]
[2 0 2 2 2 2 1 1 1 1]
[2 2 0 2 2 2 1 1 1 1]
[2 2 2 0 2 2 1 1 1 1]
[2 2 2 2 0 2 1 1 1 1]
[2 2 2 2 2 0 1 1 1 1]
[1 1 1 1 1 1 0 0 0 0]
[1 1 1 1 1 1 0 0 0 0]
[1 1 1 1 1 1 0 0 0 0]
[1 1 1 1 1 1 0 0 0 0]

Resources