I am having trouble understanding what seems like an inconsistent behavior in Julia.
X = reshape(1:100, 10, 10)
b = [1 5 9]
X[2, :][b] # returns the correct array
X[2, :][1 5 9] # throws an error
Can someone explain why using the variable b works to index an array but not when I write the index myself?
Since x = X[2,:] is just a vector, we can simplify the example to just talking about indexing behavior on vectors.
x[v] where v is a collection of integers returns the subset of x. Thus x[(1,5,9)], or x[[1,5,9]] is thus using that getindex(x::Vector,i::AbstractArray) dispatch.
Note that x[[1 5 9]] works because v = [1 5 9] makes v a row vector. That's valid syntax, but x[1 5 9] just isn't even valid Julia syntax. That syntax means something else:
v = Float64[1 5 9]
returns a row vector with element type Float64.
I have figured out a solution.
Rather than write X[2, :][1 5 9] I should have written x[2, :][[1 5 9]]
I believe this makes sense when we imagine indexing on two dimensions the second time. This makes it possible to write more complicate indices, like X[2:4, :][[1 3],[1 3]]
Related
I have come accross a line code that actually works for the work I am doing but I do not understand it. I would like someone to please explain what it means.
b=(3,1,2,1)
a=2
q=np.zeros(b+(a,))
I would like to know why length of q is always the first entry of b.
for example len(q)=3
if b=(1,2,4,3) then len(q)=1
This is really confusing as I thought that the function 'len' returns the number of columns of a given array. Also, how do I get the number of rows of q. So far the only specifications I have found are len(q), q.size( which gives the total number of elements in q) and q.shape(which also I do not quite get the output, because in the latter case, q.shape=(b,a)=(1,2,4,3,2).
Is there function that could return the size of the array in terms of the numberof columns and rows? for example 24x2?
Thank you in advance.
In Python a array does only have one dimension, that's why len(array) returns a single number.
Assuming that you have a 'matrix' in form of array of arrays, like this:
1 2 3
4 5 6
7 8 9
declared like
mat = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
you can determine the 'number of columns and rows' by the following commands:
rows = len(mat)
columns = len(mat[0])
Note that it only works if number of elements in each row is constant
If you are using numpy to make the arrays, another way to get the column rows and columns is using the tuple from the np.shape() function. Here is a complete example:
import numpy as np
mat = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
rownum = np.shape(mat)[0]
colnum = np.shape(mat)[1]
In Julia vec reshapes multidimensional arrays into one-dimension arrays.
However it doesn't work for arrays of arrays or arrays of tuples.
A part from using array comprehension, is there another way to flatten arrays of arrays/tuples? Or arrays of arrays/tuples of arrays/tuples? Or ...
Iterators.flatten(x) creates a generator that iterates over each element of x. It can handle some of the cases you describe, eg
julia> collect(Iterators.flatten([(1,2,3),[4,5],6]))
6-element Array{Any,1}:
1
2
3
4
5
6
If you have arrays of arrays of arrays and tuples, you should probably reconsider your data structure because it doesn't sound type stable. However, you can use multiple calls to flatten, eg
julia> collect(Iterators.flatten([(1,2,[3,3,3,3]),[4,5],6]))
6-element Array{Any,1}:
1
2
[3, 3, 3, 3]
4
5
6
julia> collect(Iterators.flatten(Iterators.flatten([(1,2,[3,3,3,3]),[4,5],6])))
9-element Array{Any,1}:
1
2
3
3
3
3
4
5
6
Note how all of my example return an Array{Any,1}. That is a bad sign for performance, because it means the compiler could not determine a single concrete type for the elements of the output array. I chose these example because the way I read your question it sounded like you may have type unstable containers already.
In order to flatten an array of arrays, you can simply use vcat() like this:
julia> A = [[1,2,3],[4,5], [6,7]]
Vector{Int64}[3]
Int64[3]
Int64[2]
Int64[2]
julia> flat = vcat(A...)
Int64[7]
1
2
3
4
5
6
7
The simplest way is to apply the ellipsis ... twice.
A = [[1,2,3],[4,5], [6,7]]
flat = [(A...)...]
println(flat)
The output would be
[1, 2, 3, 4, 5, 6, 7].
If you use VectorOfArray from RecursiveArrayTools.jl, it uses the indexing fallback to provide convert(Array,A) for a VectorOfArray A.
julia> using RecursiveArrayTools
julia> A = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
3-element Array{Array{Int64,1},1}:
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
julia> VA = VectorOfArray(A)
3-element Array{Array{Int64,1},1}:
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
First of it acts as a lazy wrapper for doing the indexing without conversion:
julia> VA[1,3]
7
Note that columns are the separate arrays so that way it's still "column-major" (i.e. efficient to index down columns). But then it has a straight conversion:
julia> convert(Array,VA)
3×3 Array{Int64,2}:
1 4 7
2 5 8
3 6 9
The other way to handle this conversion is to do something like hcat(A...), but that's slow if you have a lot of arrays you're splatting!
Now, you may think: what about writing a function that pre-allocates the matrix, then loops through and fills it? That's almost what convert on the VectorOfArray works, except the fallback that convert uses here utilizes Tim Holy's Cartesian machinery. At one point, I wrote that function:
function vecvec_to_mat(vecvec)
mat = Matrix{eltype(eltype(vecvec))}(length(vecvec),length(vecvec[1]))
for i in 1:length(vecvec)
mat[i,:] .= vecvec[i]
end
mat
end
but I have since gotten rid of it because the fallback was much faster. So, YMMV but that's a few ways to solve your problem.
for Julia 0.7x:
for Arrays:
flat(arr::Array) = mapreduce(x -> isa(x, Array) ? flat(x) : x,
append!, arr,init=[])
for Tuples:
flat(arr::Tuple) = mapreduce(x -> isa(x, Tuple) ? flat(x) : x,
append!, arr,init=[])
Works for arbitrary depth.
see: https://rosettacode.org/wiki/Flatten_a_list#Julia
Code for Array/Tuple:
function flatten(arr)
rst = Any[]
grep(v) = for x in v
if isa(x, Tuple) || isa(x, Array)
grep(x)
else push!(rst, x) end
end
grep(arr)
rst
end
Let's say I want to iterate over a numpy array and print each item. I'm going to use this later on to manipulate the (i,j) entry in my array depending on some rules.
I've read the numpy docs and it seems like you can access individual elements in an array easily enough using similar indexing(or slicing) to lists. But it seems that I am unable to do anything with each (i,j) entry when I try to access it in a loop.
row= 3
column = 2
space = np.random.randint(2, size=(row, column))
print space, "\n"
print space[0,1]
print space[1,0] #test if I can access indiivdual elements
output:
[[1,1
[1,1
[0,0]]
1
1
for example, using the above I want to iterate over every row and column and print each entry. I would think to use something like the following:
for i in space[0:row,:]:
for j in space[:,0:column]:
print space[i,j]
the output I get is
[1,1]
[1,1]
[1,1]
[1,1]
[1,1]
[1,1]
[1,1]
[1,1]
[1,1]
Obviously this does not work. I believe the problem is that I'm accessing entire rows and columns instead of elements within any given row and column. I've been going over the numpy docs for a couple of hours and I am still unsure of how to go about this.
My main concern is I want to change each (i,j) entry by using a loop and some conditionals, for example (using the above loop):
for i in space[0:row,:]:
for j in space[:,0:column]:
if [i+1,j] + [i,j+1] == 2:
[i,j] = 1
Start with:
for i in range(row):
for j in range(column):
print space[i,j]
You are generating indices in your loops which index some element then!
The relevant numpy docs on indexing are here.
But it looks, that you should also read up basic python-loops.
Start simple and read some docs and tutorials. After i saw Praveen's comment, i felt a bit bad with this simple answer here which does not offer much more than his comment, but maybe the links above are just what you need.
A general remark on learning numpy by trying:
regularly use arr.shape to check the dimensions
regularly use arr.dtype to check the data-type
So in your case the following should have given you a warning (not a python one; one in your head) as you probably expected i to iterate over values of one dimension:
print((space[0:row,:]).shape)
# output: (3, 2)
There are many ways of iterating over a 2d array:
In [802]: x=np.array([[1,1],[1,0],[0,1]])
In [803]: print(x) # non-iteration
[[1 1]
[1 0]
[0 1]]
by rows:
In [805]: for row in x:
...: print(row)
[1 1]
[1 0]
[0 1]
add enumerate to get an index as well
In [806]: for i, row in enumerate(x):
...: row += i
In [807]: x
Out[807]:
array([[1, 1],
[2, 1],
[2, 3]])
double level iteration:
In [808]: for i, row in enumerate(x):
...: for j, v in enumerate(row):
...: print(i,j,v)
0 0 1
0 1 1
1 0 2
1 1 1
2 0 2
2 1 3
of course you could iterate on ranges:
for i in range(x.shape[0]):
for j in range(x.shape[1]):
x[i,j]...
for i,j in np.ndindex(x.shape):
print(i,j,x[i,j])
Which is best depends, in part, on whether you need to just use the values, or need to modify them. If modifying you need an understanding of whether the item is mutable or not.
But note that I can remove the +1 without explicit iteration:
In [814]: x-np.arange(3)[:,None]
Out[814]:
array([[1, 1],
[1, 0],
[0, 1]])
I know this is simple but am having a hard time finding the right function for this. I have a vector a = [1 2 3 4] and another vector b = [1 2 6 8]. I want to return all of the elements in a that aren't in b. In this case, it would be [3 4]. How do you do this?
did you try with setdiff?
c = setdiff(a,b)
I need to compare two different arrays in Matlab. It's going to be used for a Yahtzee game. If I have an array that contains [1 2 3 4] and an array that contains [1 2 3 4 5], how do I check if the first array is contained within the second array. I just need to know a T/F result, not anything about which elements are missing, etc.
ismember will do it. For example:
x = [1 2 3 4]
y = [1 2 3 4 5]
all(ismember(x,y))
You can also use setdiff. For example:
isempty(setdiff(x,y))
another option,
all(intersect(x,y)==x)
but ismember is probably more efficient....