Remove a value in an array and decrease the size of it - arrays

I have an array filled with some values. After running this code:
array = zeros(10)
for i in 1:10
array[i] = 2*i + 3
end
The array looks like:
10-element Array{Float64,1}:
5.0
7.0
9.0
11.0
13.0
15.0
17.0
19.0
21.0
23.0
I would like to obtain, for example, the following array by removing the third value:
9-element Array{Float64,1}:
5.0
7.0
11.0
13.0
15.0
17.0
19.0
21.0
23.0
How to do that?
EDIT
If I have an array (and not a vector), like here:
a = [1 2 3 4 5]
1×5 Array{Int64,2}:
1 2 3 4 5
The deleteat! proposed is not working:
a = deleteat!([1 2 3 4 5], 1)
ERROR: MethodError: no method matching deleteat!(::Array{Int64,2}, ::Int64)
You might have used a 2d row vector where a 1d column vector was required.
Note the difference between 1d column vector [1,2,3] and 2d row vector [1 2 3].
You can convert to a column vector with the vec() function.
Closest candidates are:
deleteat!(::Array{T,1} where T, ::Integer) at array.jl:875
deleteat!(::Array{T,1} where T, ::Any) at array.jl:913
deleteat!(::BitArray{1}, ::Integer) at bitarray.jl:961
I don't want a column vector. I would want:
1×4 Array{Int64,2}:
2 3 4 5
Is it possible ?

To make that clear: Vector{T} in Julia is just a synonym for Array{T, 1}, unless you're talking about something else... we call Arrays of all ranks arrays.
But this seems to be a Matlab-inherited misconception. In Julia, you construct a Matrix{T}, ie., an Array{T, 2}, by using spaces in the literal:
julia> a = [1 2 3 4 5]
1×5 Array{Int64,2}:
1 2 3 4 5
Deleting from a matrix does not make sense in general, since you can't trivially "fix the shape" in a rectangular layout.
A Vector or Array{T, 1} can be written using commas:
julia> a = [1, 2, 3, 4, 5]
5-element Array{Int64,1}:
1
2
3
4
5
And on this, deleteat! works:
julia> deleteat!(a, 1)
4-element Array{Int64,1}:
2
3
4
5
For completeness, there's also a third variant, the RowVector, which results of a transposition:
julia> a'
1×4 RowVector{Int64,Array{Int64,1}}:
2 3 4 5
From this you also can't delete.

Deleteat! is only defined for:
Fully implemented by:
Vector (a.k.a. 1-dimensional Array)
BitVector (a.k.a. 1-dimensional BitArray)
A Row Vector (2 Dimensions) won't work.
But ... there is a workaround by this trick:
julia> deleteat!(a[1,:], 1)' # mind the ' -> transposes it back to a row vector.
1×4 RowVector{Int64,Array{Int64,1}}:
2 3 4 5
Ofcourse this wouldn't work for an Array with 2 or more rows.

Related

Julia accessing specific Matrix elements using vectors as indexes

Suppose I have a 4*2 matrix as follows:
a = [1 2; 3 4; 5 6; 7 8]
4×2 Matrix{Int64}:
1 2
3 4
5 6
7 8
I want to access the matrix using a vector specifying which element I want to access in each column. In NumPy from python, I would do the following command:
a[[1,3], [1,2]]
# expected output:
1×2 Matrix{Int64}:
1(as a[1,1]) 6(as a[3,2])
but in Julia, I got the following matrix:
2×2 Matrix{Int64}:
1 2
5 6
How can I do it in an julia way?
UPDATE: Inspired by DNF answer:
julia> a[CartesianIndex.([1 3], [1 2])]
1×2 Matrix{Int64}:
1 6
seems to me the right balance of clarity and similarity to OP.
ORIGINAL answer:
Maybe not the optimal way, but:
[a[x...] for x in [[[1,1]] [[3,2]]]]
works.
Note that this returns a row vector, like in the OP. In Julia there is a difference between a vector and a matrix. A matrix with one row or one column is not the same as a vector.
The [[]] notation is to let hcat handle vector elements correctly. If a vector output is good enough, then: [[1,1],[3,2]] is enough.
The syntax a[i, j] is syntax sugar for getindex(a, i, j). You can broadcast getindex to get the desired behavior (unfortunately, you cannot broadcast the [] syntax itself):
getindex.(Ref(a), [1,3], [1,2])
You must protect a itself against being broadcasted, by wrapping it in a Ref.

How to concatenate differently sized vectors in Julia?

How can I concatenate arrays of different size with a "filler" value where the arrays don't line up?
a = [1,2,3]
b = [1,2]
And I would like:
[1 2 3
1 2 missing]
Or
[1 2 3
1 2 nothing]
One way, using rstack which is "ragged stack". It always places arrays along one new dimension, thus given vectors, they form the columns of a matrix. (The original question may want the transpose of this result.)
julia> using LazyStack
julia> rstack(a, b; fill=missing)
3×2 Matrix{Union{Missing, Int64}}:
1 1
2 2
3 missing
julia> rstack(a, b, reverse(a), reverse(b); fill=NaN)
3×4 Matrix{Real}:
1 1 3 2
2 2 2 1
3 NaN 1 NaN

Converting Array of CartesianIndex to 2D-Matrix in Julia

let's say we have an array of cartesian indices in Julia
julia> typeof(indx)
Array{CartesianIndex{2},1}
Now we want to plot them as a scatter-plot using PyPlot. so we should convert the indx-Array of Cartesian to a 2D-Matrix so we can plot it like this:
PyPlot.scatter(indx[:, 1], indx[:, 2])
How can i convert an Array of type Array{CartesianIndex{2},1} to a 2D-Matrix of type Array{Int,2}
By the way here is a code snippet how to produce a dummy Array of cartesianindex:
A = rand(1:10, 5, 5)
indx = findall(a -> a .> 5, A)
typeof(indx) # this is an Array{CartesianIndex{2},1}
Thanks
An easy and generic way is
julia> as_ints(a::AbstractArray{CartesianIndex{L}}) where L = reshape(reinterpret(Int, a), (L, size(a)...))
as_ints (generic function with 1 method)
julia> as_ints(indx)
2×9 reshape(reinterpret(Int64, ::Array{CartesianIndex{2},1}), 2, 9) with eltype Int64:
1 3 4 1 2 4 1 1 4
2 2 2 3 3 3 4 5 5
This works for any dimensionality, making the first dimension the index into the CartesianIndex.
One possible way is hcat(getindex.(indx, 1), getindex.(indx,2))
julia> #btime hcat(getindex.($indx, 1), getindex.($indx,2))
167.372 ns (6 allocations: 656 bytes)
10×2 Array{Int64,2}:
4 1
3 2
4 2
1 3
4 3
5 3
2 4
5 4
1 5
4 5
However, note that you don't need to - and therefore probably shouldn't - bring your indices to 2D-Matrix form. You could simply do
PyPlot.scatter(getindex.(indx, 1), getindex.(indx, 2))

How to multiply multi-dimensional arrays/matrices in Julia

Multiplying two multi-dimensional arrays, say, a 1-dimensional with a 3-dimensional array:
[1 2] * reshape(1:8,2,2,2)
gives me the error message:
LoadError: MethodError: `*` has no method matching *(::Array{Int64,2}, ::Array{Int64,3})
Closest candidates are:
*(::Any, ::Any, !Matched::Any, !Matched::Any...)
*{TA,TB}(::Union{DenseArray{TA,1},DenseArray{TA,2},SubArray{TA,1,A<:DenseArray{T,N},I<:Tuple{Vararg{Union{Colon,Int64,Range{Int64}}}},LD},SubArray{TA,2,A<:DenseArray{T,N},I<:Tuple{Vararg{Union{Colon,Int64,Range{Int64}}}},LD}}, !Matched::Base.LinAlg.AbstractTriangular{TB,S<:AbstractArray{T,2}})
*{TA,TQ,N}(::Union{DenseArray{TA,N},SubArray{TA,N,A<:DenseArray{T,N},I<:Tuple{Vararg{Union{Colon,Int64,Range{Int64}}}},LD}}, !Matched::Union{Base.LinAlg.QRCompactWYQ{TQ,M<:AbstractArray{T,2}},Base.LinAlg.QRPackedQ{TQ,S<:AbstractArray{T,2}}})
...
while loading In[167], in expression starting on line 1
in Ac_mul_B at operators.jl:157
using the math definition of multi-dimensional matrix algebra for a (1 by 2) * (2 by 2 by 2) multiplication of matrices/arrays.
A somewhat more general example can be A*B = C meaning sum_k A_{i,j,k} B_{k,l,m} = C_{i,j,l,m}, where A is a 3-index matrix, or tensor if you like, B is a 3-index one, and the resulting C is a four index matrix/tensor, but, in general, there can be any number of dimensions and a dimension can have any size (within reason). See more info on the definition of a matrix product or tensor contraction.
What is the right syntax of this multiplication in Julia?
You can use reshape to convert the multi-dimensional arrays into matrices,
multiply them, and convert the result back to a multi-dimensional array.
A = [1 2]
B = reshape(1:8,2,2,2)
reshape( reshape(A,2,1)' * reshape(B,2,4), 2, 2 )
(In this example, since A is already a matrix, there is actually no need to reshape it.)
Matrices multiplication: use *
Matrices element-wise multiplication: use .*
If you want to multiply two matrices A*B, the size of both must much: e.g.
size of A (a1,a2),
size of B (b1, b2);
in order to make the multiplication feasible a2 must be the same as b1
In your case:
julia> A=[1 2]
1x2 Array{Int64,2}:
1 2
julia> size(A) #remember that size(A') is (2,1)
(1,2)
julia> B=reshape(1:8,2,2,2)
2x2x2 Array{Int64,3}:
[:, :, 1] =
1 3
2 4
[:, :, 2] =
5 7
6 8
julia> size(B)
(2,2,2)
julia> size(B[:,:,1])
(2,2)
julia> A*B[:,:,1]
1x2 Array{Int64,2}:
5 11
julia> A*B[:,:,2]
1x2 Array{Int64,2}:
17 23
Edit: Multiplication in "one shot" (separated for clarity):
julia> A*B[:,:,1]
1x2 Array{Int64,2}:
5 11
julia> A*B[:,:,2]
1x2 Array{Int64,2}:
17 23
julia> C=A*B[:,:]
1x4 Array{Int64,2}:
5 11 17 23
julia> size(C)
(1,4)
julia> D1 = reshape(C, 2,2)
2x2 Array{Int64,2}:
5 17
11 23
julia> D2 = reshape(C, 2,2)'
2x2 Array{Int64,2}:
5 11
17 23
Truly in one shot:
julia> D = reshape(A*B[:,:], 2,2)
2x2 Array{Int64,2}:
5 17
11 23

Julia Reverse N-dimensional arrays

In Python, Numpy arrays can be reversed using the standard [::-1] i.e.
A = np.diag(np.arange(1,3))
A[::, ::-1]
A[::-1]
A[::-1, ::-1]
Julia does not support [::-1] and the reverse method only works on 1D arrays and only 1D columns (where as rows are 2D by default).
Is there an alternative I'm missing?
Try the following, which is essentially the same as the numpy version:
julia> X = rand(3,3)
3x3 Array{Float64,2}:
0.782622 0.996359 0.335781
0.719058 0.188848 0.985693
0.455355 0.910717 0.870187
julia> X[end:-1:1,end:-1:1]
3x3 Array{Float64,2}:
0.870187 0.910717 0.455355
0.985693 0.188848 0.719058
0.335781 0.996359 0.782622
In Julia 1.0, to reverse a (column) vector:
julia> reverse([1, 2, 3])
3-element Array{Int64,1}:
3
2
1
For reversing rows, just state that you want to flip the second dimension:
julia> reverse([1 2 3], dims=2)
1×3 Array{Int64,2}:
3 2 1
EDIT: Alternatively, you can also index in reverse using end:-1:1, and that way also allows you to request a view instead of a copy:
julia> a = reshape(randperm(9), 3, 3)
3×3 Matrix{Int64}:
4 7 9
5 2 1
3 6 8
julia> #view a[:, end:-1:1]
3×3 view(::Matrix{Int64}, :, 3:-1:1) with eltype Int64:
9 7 4
1 2 5
8 6 3
Following up #IainDunning's answer, an important difference between numpy and Julia here is that X[:,end:-1:1] in Julia returns a copy and in numpy X[:,::-1] will return a view of the same data (no copy is made).
I'm just learning Julia myself, but it seems like you can accomplish something similar in Julia using sub(X, :, size(X)[2]:-1:1), which returns Julia's equivalent of a view (SubArray). Interestingly, you can't use the end keyword in this construct as far as I can see, and instead you must pass in the actual end index in the dimension.
You can use the function flipdim(mat, d).
Ref: http://docs.julialang.org/en/release-0.4/stdlib/arrays/
Try this set of functions:
function reverser(x::AbstractArray, dims::AbstractVector{<:Integer})
y = copy(x)
for d in dims
y = reverse(y, dims=d)
end
return y
end
reverser(x::AbstractArray) = reverser(x, 1:ndims(x)) # all dimensions
reverser(x::AbstractArray, d::Integer) = reverser(x, [1])
Julia 1.6 supports reversing any or all of the dimensions of an arbitrary multidimensional array (implemented here). To reverse all of the dimensions, you can simply do reverse(X).

Resources