I have a matrix of zeros A which has dimension (m x n). I have another matrix of some integer values b. b has length n. I want to have A be set to the identity wherever b has values greater than 5. So basically, for every row of A where b has value greater than 5, set it to the identity.
I tried to do this, but it's not working. Does anyone have an idea of how to do this in Julia?
using LinearAlgebra
usable_values = filter((x) -> x > 5, b)
# A[:, usable_values] = I
A[:, b .> 5] = I
I'm not certain I understand what you mean by "set to the identity": the identity matrix must be square, and hence a row or column of a matrix can't be equal to the identity matrix. I'll operate under the assumption that you want the entries to have value 1. In that case,
A[:, findall(b .> 5)] .= 1
is a simple one-liner. Let's discuss the elements here:
As proposed above, filter will select out the elements of b bigger than 5. But you want the indices of those elements, for which findall is the appropriate function.
Note the use of broadcasted assignment, .=. This means to assign the RHS to each element of the left side. That way you don't need to create a matrix on the RHS.
The loop approach is fine too, but for reasons of performance I'd put that in a function. See the performance tips.
If what you need is for every row of A where b has value greater than 5, set it to the identity this might be helpful to you, while you wait that for some of the gurus here can write the same in one line of code :)
n = 2
m = 5
A = zeros(m, n)
b = rand(1:10, m)
println(b)
for (cnt, value) in enumerate(b)
if value > 5
A[cnt, :] = ones(1, n)
end
end
A
The result I get is:
b = [4, 2, 6, 8, 1]
5×2 Array{Float64,2}:
0.0 0.0
0.0 0.0
1.0 1.0
1.0 1.0
0.0 0.0
I am fairly new to the language, this is the best I can do to help, for now.
Related
Coming from R I am used to do something like this to get the first element of vector a:
a <- c(1:3, 5)
a[1]
[1] 1
H can I get the 1 in Julia? The first element of a is now a range.
a = [1:3, 5]
a[1]
1-element Array{UnitRange{Int64},1}:
1:3
The core problem here is that c(1:3, 5) in R and [1:3, 5] in Julia do not do the same thing. The R code concatenates a vector with an integer producing a vector of four integers:
> c(1:3, 5)
[1] 1 2 3 5
The Julia code constructs a two-element vector whose elements are the range 1:3 and the integer 5:
julia> [1:3, 5]
2-element Vector{Any}:
1:3
5
julia> map(typeof, ans)
2-element Vector{DataType}:
UnitRange{Int64}
Int64
This vector has element type Any because there's no smaller useful common supertype of a range and an integer. If you want to concatenate 1:3 and 5 together into a vector you can use ; inside of the brackets instead of ,:
julia> a = [1:3; 5]
4-element Vector{Int64}:
1
2
3
5
Once you've defined a correctly, you can get its first element with a[1] just like in R. In general inside of square brackets in Julia:
Comma (,) is only for constructing vectors of the exact elements given, much like in Python, Ruby, Perl or JavaScript.
If you want block concatenation like in R or Matlab, then you need to use semicolons/newlines (; or \n) for vertical concatenation and spaces for horizontal concatenation.
The given example of [1:3; 5] is a very simple instance of block concatenation, but there are significantly more complex ones possible. Here's a fancy example of constructing a block matrix:
julia> using LinearAlgebra
julia> A = rand(2, 3)
2×3 Matrix{Float64}:
0.895017 0.442896 0.0488714
0.750572 0.797464 0.765322
julia> [A' I
0I A]
5×5 Matrix{Float64}:
0.895017 0.750572 1.0 0.0 0.0
0.442896 0.797464 0.0 1.0 0.0
0.0488714 0.765322 0.0 0.0 1.0
0.0 0.0 0.895017 0.442896 0.0488714
0.0 0.0 0.750572 0.797464 0.765322
Apologies for StackOverflow's lousy syntax highlighting here: it seems to get confused by the postfix ', interpreting it as a neverending character literal. To explain this example a bit:
A is a 2×3 random matrix of Float64 elements
A' is the adjoint (conjugate transpose) of A
I is a variable size unit diagonal operator
0I is similar but the diagonal scalar is zero
These are concatenated together to form a single 5×5 matrix of Float64 elements where the upper left and lower right parts are filled from A' and A, respectively, while the lower left is filled with zeros and the upper left is filled with the 3×3 identity matrix (i.e. zeros with diagonal ones).
In this case, your a[1] is a UnitRange collection. If you want to access an individual element of it, you can use collect
For example for the first element,
collect(a[1])[1]
I want to find the index of the first value in each row of a matrix that satisfies some condition. I want to figure out how to do this without using array comprehensions.
This is how I would do it with an array comprehension:
# let's say we want to find the first column index, per row, where a number in that row is below some threshold.
threshold = 0.5;
data = randn(50,100);
first_threshold_crossings = [findfirst(data[i,:]<threshold) for i in 1:size(data,1)];
Yielding a list of indices that tells you where (column-wise) each row has a value that first drops below the threshold, going from left to right.
Any faster way you can imagine doing this?
Here's how you can do it:
julia> using Random # For RNG reproducability
julia> A = rand(Random.MersenneTwister(0), 3, 3)
3×3 Array{Float64,2}:
0.823648 0.177329 0.0423017
0.910357 0.27888 0.0682693
0.164566 0.203477 0.361828
julia> findfirst.(x < 0.1, eachrow(A))
3-element Array{Union{Nothing, Int64},1}:
3
3
nothing
Note that findfirst returns nothing if no index satisfies the condition.
3/[2;2] gives
1×2 LinearAlgebra.Transpose{Float64,Array{Float64,1}}:
0.75 0.75
while 3 ./[2;2] gives
2-element Array{Float64,1}:
1.5
1.5
The second one is easy to comprehend. It broadcasts 3 and performs element wise division. But what is the reasoning behind having the first operation behave as it did? I assume it took the sum of the vector, which was 2x1, performed division of 3 by 4 and broadcast it to a 1x2 transposed vector. I can accept taking the sum of the vector to perform division, but why the transpose? Or why not just return a scalar?
It simply gives the right hand side operand's pseudo-inverse.
julia> ?/
...
Right division operator: multiplication of x by the inverse of y on the right.
Although it seems surprising at first sight, it is actually the natural behavior. A rowvector*columnvector gives a scalar and hence a scalar divided by a column vector should give a row vector, which is the case. Note that RowVector has been removed in 1.0 and what you get is actually a row vector represented with Transpose.
You can write #less 1 / [2;2] to see what actually happens.
Also take a look at this GitHub issue to understand the behaviour a bit more and this discourse topic for some use cases.
It seems it is calculating the pseudoinverse of the vector and then multiplying by 3.
Using #which 3/[2;2] and so on to see what actually happens, I found that it is eventually calling the following method in stdlib/LinearAlgebra/generic.jl:
function _vectorpinv(dualfn::Tf, v::AbstractVector{Tv}, tol) where {Tv,Tf}
res = dualfn(similar(v, typeof(zero(Tv) / (abs2(one(Tv)) + abs2(one(Tv))))))
den = sum(abs2, v)
# as tol is the threshold relative to the maximum singular value, for a vector with
# single singular value σ=√den, σ ≦ tol*σ is equivalent to den=0 ∨ tol≥1
if iszero(den) || tol >= one(tol)
fill!(res, zero(eltype(res)))
else
res .= dualfn(v) ./ den
end
return res
end
which in the given case effectively becomes transpose([2;2])/sum(abs2, [2;2]) which is the pseudoinverse.
However, this is a bit above my head. So someone more qualified might prove me wrong.
I am solving a constrained optimization problem in R iteratively where the problem if of the following form:
min f(x)
s.t. g(x) < 0
I am doing the optimization iteratively and so I have a variable called f that holds the current value of the function f and vector g of 1's and 0's that tells me if the constraint was met for the ith iteration. To help, here is an example
#Imagine there are 6 time points
f = c(7,10,6,3,-1,-9)
g = c(1,1,0,1,1,0)
And so I want to keep track of the best minimum value found at the ith iteration such that the constraint was satisfied. Thus I want to be able to calculate a vector like
h = c(7,7,7,3,-1,-1)
Where h records the minimum value found in time such that the constraint was met. Is there an easy way to do this in R either in loops or not?
Given your f and g, I would do it like this:
cummin(zoo::na.locf(ifelse(g == 1, f, NA)))
# [1] 7 7 7 3 -1 -1
Or, perhaps more simply:
cummin((ifelse(g == 1, f, Inf)))
# [1] 7 7 7 3 -1 -1
Let X be an N by D matrix. Selecting a submatrix of size n by d returns a matrix of those dimensions unless at least one of n and d equals 1, in which case we get a vector instead. Interestingly, R still returns a matrix of the correct dimensions even if one of n and d are 0, and the other not 1.
Now, if we are certain that n!=1, then executing cbind(X[row.subset,col.subset]) will return a matrix of the correct dimensions regardless of whether d==1 or not (here n=length(row.subset) and d=length(col.subset)). If we are certain that d!=1, then we can use rbind(...). But if both n and d can be 1, neither approach will work since we could accidentally turn a row into a column or vice versa.
As far as I can tell, one way to always get a matrix of the right dimensions is to call matrix(X[row.subset,col.subset],nrow=n,ncol=d). However, it doesn't feel like that should be the right way to go about it, plus I'm not confident that there is no performance penalty. Is there a more "native" solution?
Here's a working example:
N <- 6
D <- 3
X <- matrix(rnorm(N*D),ncol=D)
dim(X[1:2,1:2]) #returns 2 2
dim(X[1:2,1]) #returns NULL, this is a vector
dim(cbind(X[1:2,1])) #returns 2 1
dim(cbind(X[1,1:2])) #returns 2 1, but we'd like it to be 1 2
dim(rbind(X[1,1:2])) #returns 1 2
dim(rbind(X[1:2,1])) #returns 1 2, but we'd like it to be 2 1
row.subset <- 1:4
col.subset <- 2
#I _think_ this is always correct, but it's verbose:
matrix(X[row.subset,col.subset],nrow=length(row.subset),ncol=length(col.subset))
Thanks in advance.
If you don't want to simplify matrix subsets to vectors just tell [ not to drop dimensions:
> dim(X[1:2,1, drop=FALSE])
[1] 2 1
> dim(X[1,1:2, drop=FALSE])
[1] 1 2
See ?"[" for details.