I'm attempting to use findall to get an index of which elements of one 1d array are greater than those of a second 1d array, and then use those indexes to set corresponding values of a third 1d array to 0.
MWE:
# create 3d array
a, b = [3;2;2], [4;3;2];
c = transpose(cat(a,b, dims = 2));
d, e = [1;2;3], [2;3;4];
f = transpose(cat(d,e, dims = 2));
g = cat(c, f, dims = 3);
g
2×3×2 Array{Int64,3}:
[:, :, 1] =
3 2 2
4 3 2
[:, :, 2] =
1 2 3
2 3 4
findall.(g[end,:,1] >= g[end-1,:,1])
and use indexes to reset elements of g[end,:,2] such that I end up with
g
2×3×2 Array{Int64,3}:
[:, :, 1] =
3 2 2
4 3 2
[:, :, 2] =
1 2 3
0 0 4
Thx. J
The code below gives the answer you request. You just have the . in the wrong spot. You want to compare the > operation element by element, and then apply findall to the entire resulting array (not element by element).
julia> g[end, findall(g[end,:,1] .> g[end-1,:,1]), 2] .= 0
2-element view(::Array{Int64,3}, 2, [1, 2], 2) with eltype Int64:
0
0
julia> g
2×3×2 Array{Int64,3}:
[:, :, 1] =
3 2 2
4 3 2
[:, :, 2] =
1 2 3
0 0 4
However, I wouldn't try to compile all your data into one big array like that. It would be easier to use three separate 1D array variables than three dimensions in one variable. Again using your variables above:
julia> e[b .> a] .= 0
2-element view(::Array{Int64,1}, [1, 2]) with eltype Int64:
0
0
julia> e
3-element Array{Int64,1}:
0
0
4
Related
I am trying to access elements of the previous columns than first column.
For example in python if i try to access elements before the first column 0 it will return an empty array.
import numpy as np
x = np.matrix([[ 1, 2, 10],
[ 1, 4, 2],
[ 2, 3, 2],
[ 2, 3, 6]])
a = x[:, 0]
print('\n a is \n', a)
b = x[:, :0]
print('\n b is \n',b)
Output: -->
a is
[[1]
[1]
[2]
[2]]
b is
[]
But julia does not behave in such manner.
My trial in julia:
array = [1 2 3;3 4 5;2 3 4;1 2 3]
a = array[:, 1]
b = array[:, 1-1]
Output :-->
BoundsError: attempt to access 4×3 Array{Int64,2} at index [1:4, 0]
Stacktrace:
[1] throw_boundserror(::Array{Int64,2}, ::Tuple{Base.Slice{Base.OneTo{Int64}},Int64}) at .\abstractarray.jl:541
[2] checkbounds at .\abstractarray.jl:506 [inlined]
[3] _getindex at .\multidimensional.jl:742 [inlined]
[4] getindex(::Array{Int64,2}, ::Function, ::Int64) at .\abstractarray.jl:1060
[5] top-level scope at In[1166]:1
[6] include_string(::Function, ::Module, ::String, ::String) at .\loading.jl:1091
However, to replicate such operation I tried to implement try and catch method and use it over the loop to see what happens when i try accessing different columns. The output is always an empty array.
for i in 1:3
try
b = array[:, :i-1]
catch
b = []
end
println("\b b in $i is $b")
end
Output :--->
b in 1 is Any[]
b in 2 is Any[]
b in 3 is Any[]
May I know how can I access row elements from first_column - 1 to last_column - 1, where first_column - 1 returns an empty array but rest returns data from the matrix.
The answer to my question is provided by #ettersi on julia discourse, I am posting it here for reference. Please follow the link mentioned in the comment to access the discourse page.
ANSWER!
julia> array = [1 2 3;3 4 5;2 3 4;1 2 3]
4×3 Matrix{Int64}:
1 2 3
3 4 5
2 3 4
1 2 3
julia> array[:, 1:0]
4×0 Matrix{Int64}
My old friend the 3d array called Pop, I want to remove columns (d2), across all of d3 when the value in the end of d1 == 1, so I have this code:
Pop[end, :, 1] .!=1
I thought adding #view in front of this would write the changes back to Pop, outwith producing an additional copy in memory. This code works fine
#view(Pop[ :, Pop[end, :, 1] .!=1, :])
but it does not alter the original 3d array called Pop. I could do
Pop = #view(Pop[ :, Pop[end, :, 1] .!=1, :])
but I believe this will create another copy in memory which I'm trying to avoid. What simple syntax have I missed? Thx. J
#view does not modify the size of the original array, it provides a "view" into it, (e.g., omitting some columns in your case). I don't think there is anything wrong with
Pop = view(Pop, :, Pop[end, :, 1] .≠ 1, :)
since now Pop is a view into your old, full Pop, but it behaves like an array, so you can modify its entries, e.g., you could then do things like
julia> using Random # using a fixed seed for reproducibility
julia> Random.seed!(0) ;
julia> Pop = rand(1:5, (2,4,2)) # original Pop
2×4×2 Array{Int64,3}:
[:, :, 1] =
4 3 5 5
1 1 3 5
[:, :, 2] =
2 2 3 1
2 5 1 1
julia> Pop[end,:,1] .≠ 1 # columns to keep
4-element BitArray{1}:
0
0
1
1
julia> Pop = view(Pop, :, Pop[end, :, 1] .≠ 1, :) # make it a view
2×2×2 view(::Array{Int64,3}, :, [3, 4], :) with eltype Int64:
[:, :, 1] =
5 5
3 5
[:, :, 2] =
3 1
1 1
julia> Pop[end,:,1] .= 1 ; # use your new view to manipulate data
julia> Pop # view of the modified Pop
2×2×2 view(::Array{Int64,3}, :, [3, 4], :) with eltype Int64:
[:, :, 1] =
5 5
1 1
[:, :, 2] =
3 1
1 1
julia> Pop.parent # original full Pop (now Pop.parent) has been modified
2×4×2 Array{Int64,3}:
[:, :, 1] =
4 3 5 5
1 1 1 1
[:, :, 2] =
2 2 3 1
2 5 1 1
I have a 3D array, and based on the values in one "row" using the or operator "|", I would like to substitute values in a different row. I've attempted to build a mwe, here goes:
# create new array
Pop = fill(Int8(3), 1, 3, 4)
# change values in one row of array
Pop[:,:,2] = [5,6,7]
# change values in second row of array
Pop[:,:,4] = [9,10,11]
# attempt conditional substitution, if element-wise value of Pop[:,:,2] equals either 6 or 7, then substitute the corresponding element wise (across row in dimension 3) for 8
Pop[:,:,2] == 6|7 Pop[:,:,3] .= 8
# to produce this end result
Pop[:,:,3] = [3,8,8]
Pop
I'm missing something in the syntax for the substitution. Thx. J
This works, but requires a temporary variable.
julia> temp = Pop[:,:,3]
1×3 Array{Int8,2}:
3 3 3
julia> temp[(Pop[:,:,2] .== 6) .| (Pop[:,:,2] .== 7)] .= 8
2-element view(::Array{Int8,1}, [2, 3]) with eltype Int8:
8
8
julia> Pop[:,:,3] = temp
1×3 Array{Int8,2}:
3 8 8
I think it's clearer to separate the stages:
julia> Pop = fill(Int8(3), 1, 3, 4);
julia> Pop[:,:,2] .= [5 6 7];
julia> ind = findall(x -> x==6 || x==7, Pop[:,:,2])
2-element Vector{CartesianIndex{2}}:
CartesianIndex(1, 2)
CartesianIndex(1, 3)
julia> Pop[ind, 3] .= 8;
julia> Pop[:, :, 3]
1×3 Matrix{Int8}:
3 8 8
You could also write ind == findall(in((6,7)), #view Pop[:,:,2]). You can write ind_bool = (Pop[:,:,2] .== 6) .| (Pop[:,:,2] .== 7) but I'm not sure Pop[ind_bool, 3] .= 8 will work on all versions of Julia.
Another way is just to write an explicit loop. We could loop separately over for i in axes(Pop,1), j in axes(Pop,2) but we can also use these multi-dimensional CartesianIndex things again:
julia> Pop = fill(Int8(3), 1, 3, 4);
julia> Pop[:,:,2] .= [5 6 7];
julia> for i in CartesianIndices(#view Pop[:,:,2])
x = Pop[i,2]
if x==6 | x==7
Pop[i,3] = 8
end
end
julia> Pop[:, :, 3]
1×3 Matrix{Int8}:
3 3 8
Thanks to help from #mcabbott and #Nathan Boyer, I've got a solution that works, even managed to add more conditions and it seems to work. I'll post the mwe solution.
# create new array
Pop = fill(Int8(3), 1, 3, 4)
# change some values
Pop[:,:,2] = [5,6,7]
Pop[:,:,4] = [9,10,9]
# what does it look like
Pop
# code to check condition values
# create temp array to be altered if conditions met
temp = Pop[:,:,3]
# see which indexes meet conditions, in this case
# array "Pop[:,:,2]" contains either 6 or 7 ... and ...
# array "Pop[:,:,4]" contains values >= 10
temp[(Pop[:,:,2] .== 6) .|
(Pop[:,:,2] .== 7) .&
(Pop[:,:,4] .>= 10)] .= 8
# make changes to original array based on temp
Pop[:,:,3] = temp
# check if it did the job correctly
Pop
I can't seem to replicate this numpy arithmetic. I'm using Julia, but want to know the mathematical explanation for this code. It seems to break what I know about Linear Algebra.
X = np.arange(-5, 5, 0.2).reshape(-1, 1)
X.shape ## (50, 1)
test = np.sum(X**2, 1).reshape(-1, 1) + np.sum(X**2, 1)
test.shape ## (50, 50)
In Julia, I would write
X = reshape(collect(range(-5, stop=5, length=N)), :, 1);
size(X) ## (50, 1)
test = sum(X.^2, dims=2) + vec(sum(X.^2, dims=2));
size(test) ## (50, 1)
I'm trying to think how a 50x50 matrix would be the result of adding two vectors? I know numpy uses a lot of broadcasting under the hood, but it doesn't seem clear to me what this is doing.
What is the mathematical notation or Julia equivalent for what numpy is doing here?
Your are doing a lot of stuff that really obscures your point, which, I believe, concerns how to add arrays of different shapes.
Python:
In [21]: x = np.random.rand(5, 1)
In [22]: x.shape
Out[22]: (5, 1)
In [23]: y = np.random.rand(1, 4)
In [24]: y.shape
Out[24]: (1, 4)
In [25]: (x + y).shape
Out[25]: (5, 4)
Julia:
julia> x = rand(5);
julia> y = rand(1, 4);
julia> x + y
ERROR: DimensionMismatch("dimensions must match")
julia> x .+ y
5×4 Array{Float64,2}:
1.95779 1.31897 1.23345 1.32423
1.78126 1.14244 1.05692 1.14771
1.08306 0.444243 0.35872 0.449509
1.69756 1.05874 0.97322 1.06401
1.18661 0.547789 0.462265 0.553054
julia> size(x .+ y)
(5, 4)
As you can tell, Python broadcasts arrays by default, while Julia requires that you specifically ask for it, by using the dot operator, ..
It is exactly because it does not make sense to add two arrays of different shapes, that Julia does not broadcast by default. Similarly, with multiplication, * and .* differ:
julia> A = [1 2; 3 4]
2×2 Array{Int64,2}:
1 2
3 4
julia> B = [4 5; 6 7]
2×2 Array{Int64,2}:
4 5
6 7
julia> A * B
2×2 Array{Int64,2}:
16 19
36 43
julia> A .* B
2×2 Array{Int64,2}:
4 10
18 28
The ordinary * is matrix multiplication, while the latter is elementwise array multiplication.
Another example:
julia> A = [1 2 3; 4 5 6]
2×3 Array{Int64,2}:
1 2 3
4 5 6
julia> b = [7, 8]
2-element Array{Int64,1}:
7
8
julia> A * b
ERROR: DimensionMismatch("matrix A has dimensions (2,3), vector B has length 2")
julia> A .* b
2×3 Array{Int64,2}:
7 14 21
32 40 48
I've 2 values and I would like to find them in a array.
This values have the same index
Example:
0 0
1 2
2 3
4 5
I'm looking for (1,2) so the index is 2
M = [[0 0]; [1 2]; [2 3]; 4 5]
ex = [1, 2]
[~ r] = ismember(ex,M, 'rows')
I think this is what you're after.
If you're not looking to match the whole row but just columns 2 and 3 then:
[~, r] = ismember(ex, M(:,2:3), 'rows')
find(example(1:end-1)==val(1) & example(2:end) ==val(2))
or if you have the right tool box (econ?) use lagmatrix and bsxfun to compare entire rows.