I would like to understand how one goes about manipulating the elements of a 2D array.
If I have for example:
a= ( a11 a12 a13 ) and b = (b11 b12 b13)
a21 a22 a23 b21 b22 b23
I have defined them in python as for example:
a=[[1,1],[2,1],[3,1]]
b=[[1,2],[2,2],[3,2]]
I saw that I cannot refer to a[1][1] but to a[1] which gives me a result of [2,1].
So, I don't understand how do I access the second row of these arrays? That would be a21, a22, a23, b21, b22, b23?
And how would I do in order to multiply them as c1 = a21*b21, c2 = a22*b22, etc ?
If you have
a=[[1,1],[2,1],[3,1]]
b=[[1,2],[2,2],[3,2]]
Then
a[1][1]
Will work fine. It points to the second column, second row just like you wanted.
I'm not sure what you did wrong.
To multiply the cells in the third column you can just do
c = [a[2][i] * b[2][i] for i in range(len(a[2]))]
Which will work for any number of rows.
Edit: The first number is the column, the second number is the row, with your current layout. They are both numbered from zero. If you want to switch the order you can do
a = zip(*a)
or you can create it that way:
a=[[1, 2, 3], [1, 1, 1]]
If you want do many calculation with 2d array, you should use NumPy array instead of nest list.
for your question, you can use:zip(*a) to transpose it:
In [55]: a=[[1,1],[2,1],[3,1]]
In [56]: zip(*a)
Out[56]: [(1, 2, 3), (1, 1, 1)]
In [57]: zip(*a)[0]
Out[57]: (1, 2, 3)
Seems to work here:
>>> a=[[1,1],[2,1],[3,1]]
>>> a
[[1, 1], [2, 1], [3, 1]]
>>> a[1]
[2, 1]
>>> a[1][0]
2
>>> a[1][1]
1
Look carefully how many brackets does your array have. I met an example when function returned answer with extra bracket, like that:
>>>approx
array([[[1192, 391]],
[[1191, 409]],
[[1209, 438]],
[[1191, 409]]])
And this didn't work
>>> approx[1,1]
IndexError: index 1 is out of bounds for axis 1 with size 1
This could open the brackets:
>>> approx[:,0]
array([[1192, 391],
[1191, 409],
[1209, 438],
[1191, 409]])
Now it is possible to use an ordinary element access notation:
>>> approx[:,0][1,1]
409
If you have this :
a = [[1, 1], [2, 1],[3, 1]]
You can easily access this by using :
print(a[0][2])
a[0][1] = 7
print(a)
a[1][1] does work as expected. Do you mean a11 as the first element of the first row? Cause that would be a[0][0].
Related
Python: I have an Array A1 with 3 rows & 2 col and A2 with 1row & 2 columns. Now, I want to print the index of both elements in A2 with respect to A1
Example
A1 = np.array([[0, 6], [15, 1], [1, 15]]) #shape (3,2)
A2 = np.array([15, 1]) #shape(2,)
Expected output
(1,0) #Index(position) of array [15,1] in A1
I tried using
np.argwhere(A2 == A1).squeeze()
but its not working out as it is writing only A2[0] i.e, 15 instead of entire array [15,1]
Please help me with this in python.
Continuation:
Python: Extract the index value from the array
import numpy as np
A1 = np.array([[0, 6], [15, 1], [1, 15]]) #shape (3,2)
A2 = np.array([15, 1]) #shape(2,)
a = np.argwhere((A2 == A1).all(1)).squeeze()
print(a)
Output
(1,0)
This code works & checks all the elements in array A2 w.r.t A1 and prints its index thanks to #yann ziselman
Let's say I have a N-dimensionnal array, for example:
A = [ [ 1, 2] ,
[6, 10] ]
and another array B that defines an index associated with each value of A
B = [[0, 1], [1, 0]]
And I want to obtain a 1D list or array that for each index contains the sum of the values of A associated with that index. For our example, we would want
C = [11, 8]
Is there a way to do this efficiently, without looping over the arrays manually ?
Edit: To make it clearer what I want, if we now take A the same and B equal to :
B = [[1, 1], [1,1]]
Then I want all the values of A to sum into the index 1 of C, which yields
C = [0, 19]
Or I can write a code snippet :
C = np.zeros(np.max(B))
for i in range(...):
for j in range(...):
C[B[i,j]] += A[i,j]
return C
I think I found the best answer for now actually.
I can just use:
np.histogram(B, weights = A)
This code provides the solution I want.
Suppose I have the following DataArray
arr = xarray.DataArray(np.arange(6).reshape(2,3),
dims=['A', 'B'],
coords=dict(A=['a0', 'a1'],
B=['b0', 'b1', 'b2']))
I want to iterate over the first dimension and do the following (of course I want to do something more complex than printing)
for coor in arr.A.values:
print(coor, arr.sel(A=coor).values)
and get
a0 [0 1 2]
a1 [3 4 5]
I am new to xarray, so I was wondering whether there was some more natural way to achieve this, something like
for coor, sub_arr in arr.some_method():
print(coor, sub_arr)
You can simply iterate over the DataArray - each element of the iterator will itself be a DataArray with a single value for the first coordinate:
for a in arr:
print(a.A.item(), a.values)
prints
a0 [0 1 2]
a1 [3 4 5]
Note the use of the .item() method to access the scalar value of the zero-dimensional array a.A.
To iterate over the second dimension, you can just transpose the data:
for b in arr.T: # or arr.transpose()
print(b.B.item(), b.values)
prints
b0 [0 3]
b1 [1 4]
b2 [2 5]
For multidimensional data, you can move the dimension you want to iterate over to the first place using ellipsis:
for x in arr.transpose("B", ...):
# x has one less dimension than arr, and x.B is a scalar
do_stuff_with(x)
The documentation on reshaping and reorganizing data has further details.
It's an old question, but I find that using groupby is cleaner and makes more intuitive sense to me than using transpose when you want to iterate some dimension other than the first:
for coor, sub_arr in arr.groupby('A'):
print(coor)
print(sub_arr)
a0
<xarray.DataArray (B: 3)>
array([0, 1, 2])
Coordinates:
* B (B) <U2 'b0' 'b1' 'b2'
A <U2 'a0'
a1
<xarray.DataArray (B: 3)>
array([3, 4, 5])
Coordinates:
* B (B) <U2 'b0' 'b1' 'b2'
A <U2 'a1'
Also it seems that older versions of xarray don't handle the ellipsis correctly (see mgunyho's answer), but groupby still works correctly.
When I am doing the slicing, an unexpected thing happened that seems the first to be view but the second is copy.
First
First slice of row, then slice of column. It seems is a view.
>>> a = np.arange(12).reshape(3, 4)
>>> a[0:3:2, :][:, [0, 2]] = 100
>>> a
array([[100, 1, 100, 3],
[ 4, 5, 6, 7],
[100, 9, 100, 11]])
Second
But if I first slice of column, then slice of row, it seems a copy:
>>> a[:, [0, 2]][0:3:2, :] = 0
>>> a
array([[100, 1, 100, 3],
[ 4, 5, 6, 7],
[100, 9, 100, 11]])
I am confused because the two methods finally will cause seem position to change, but why the second actually doesn't change the number?
The accepted answer by John Zwinck is actually false (I just figured this out the hard way!).
The problem in the question is a combination of doing "l-value indexing" with numpy's fancy indexing.
The following doc explains exactly this case
https://scipy-cookbook.readthedocs.io/items/ViewsVsCopies.html
in the section "But fancy indexing does seem to return views sometimes, doesn't it?"
Edit:
To summarize the above link:
Whether a view or a copy is created is determined by whether the indexing can be represented as a slice.
Exception: If one does "fancy indexing" then always a copy is created. Fancy indexing is something like a[[1,2]].
Exception to the exception: If one does l-value indexing (i.e. the indexing happens left of the = sign), then the rule for when a view or a copy are created doesn't apply anymore (though see below for a further exception). The python interpreter will directly assign the values to the left hand side without creating a copy or a view.
To prove that a copy is created in both cases, you can do the operation in two steps:
>>> a = np.arange(12).reshape(3, 4)
>>> b = a[0:3:2, :][:, [0, 2]]
>>> b[:] = 100
>>> a
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
and
>>> b = a[:, [0, 2]][0:3:2, :]
>>> b[:] = 0
>>> a
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
Just as an aside, the question by the original poster is the exact problem stated at the end of the scipy-cookbook link above. There is no solution given in the book. The tricky thing about the question is that there are two indexing operations done in a row.
Exception to the exception to the exception: If there are two indexing operations done in a row on the left hand side (as is the case in this question), the direct assignment in l-value indexing only works if the first indexing operation can be represented as a slice. Otherwise a copy has to be created even though it is l-value indexing.
All that matters is whether you slice by rows or by columns. Slicing by rows can return a view because it is a contiguous segment of the original array. Slicing by column must return a copy because it is not a contiguous segment. For example:
A1 A2 A3
B1 B2 B3
C1 C2 C3
By default, it is stored in memory this way:
A1 A2 A3 B1 B2 B3 C1 C2 C3
So if you want to choose every second row, it is:
[A1 A2 A3] B1 B2 B3 [C1 C2 C3]
That can be described as {start: 0, size: 3, stride: 6}.
But if you want to choose every second column:
[A1] A2 [A3 B1] B2 [B3 C1] C2 [C3]
And there is no way to describe that using a single start, size, and stride. So there is no way to construct such a view.
If you want to be able to view every second column instead of every second row, you can construct your array in column-major aka Fortran order instead:
np.array(a, order='F')
Then it will be stored as such:
A1 B1 C1 A2 B2 C2 A3 B3 C3
This is my understanding, for your reference
a[0:3:2, :] # basic indexing, a view
... = a[0:3:2, :][:, [0, 2]] # getitme version, a copy,
# because you use advanced
# indexing [:,[0,2]]
a[0:3:2, :][:, [0, 2]] = ... # howver setitem version is
# like a view, setitem version
# is different from getitem version,
# this is not c++
a[:, [0, 2]] # getitem version, a copy,
# because you use advanced indexing
a[:, [0, 2]][0:3:2, :] = 0 # the copy is modied,
# but a keeps unchanged.
If I have any misunderstanding, please point it out.
np.nditer automatically iterates of the elements of an array row-wise. Is there a way to iterate of elements of an array columnwise?
x = np.array([[1,3],[2,4]])
for i in np.nditer(x):
print i
# 1
# 3
# 2
# 4
What I want is:
for i in Columnwise Iteration(x):
print i
# 1
# 2
# 3
# 4
Is my best bet just to transpose my array before doing the iteration?
For completeness, you don't necessarily have to transpose the matrix before iterating through the elements. With np.nditer you can specify the order of how to iterate through the matrix. The default is usually row-major or C-like order. You can override this behaviour and choose column-major, or FORTRAN-like order which is what you desire. Simply specify an additional argument order and set this flag to 'F' when using np.nditer:
In [16]: x = np.array([[1,3],[2,4]])
In [17]: for i in np.nditer(x,order='F'):
....: print i
....:
1
2
3
4
You can read more about how to control the order of iteration here: http://docs.scipy.org/doc/numpy-1.10.0/reference/arrays.nditer.html#controlling-iteration-order
You could use the shape and slice each column
>>> [x[:, i] for i in range(x.shape[1])]
[array([1, 2]), array([3, 4])]
You could transpose it?
>>> x = np.array([[1,3],[2,4]])
>>> [y for y in x.T]
[array([1, 2]), array([3, 4])]
Or less elegantly:
>>> [np.array([x[j,i] for j in range(x.shape[0])]) for i in range(x.shape[1])]
[array([1, 2]), array([3, 4])]
nditer is not the best iteration tool for this case. It is useful when working toward a compiled (cython) solution, but not in pure Python coding.
Look at some regular iteration strategies:
In [832]: x=np.array([[1,3],[2,4]])
In [833]: x
Out[833]:
array([[1, 3],
[2, 4]])
In [834]: for i in x:print i # print each row
[1 3]
[2 4]
In [835]: for i in x.T:print i # print each column
[1 2]
[3 4]
In [836]: for i in x.ravel():print i # print values in order
1
3
2
4
In [837]: for i in x.T.ravel():print i # print values in column order
1
2
3
4
You comment: I need to fill values into an array based on the index of each cell in the array
What do you mean by index?
A crude 2d iteration with indexing:
In [838]: for i in range(2):
.....: for j in range(2):
.....: print (i,j),x[i,j]
(0, 0) 1
(0, 1) 3
(1, 0) 2
(1, 1) 4
ndindex uses nditer to generate similar indexes
In [841]: for i,j in np.ndindex(x.shape):
.....: print (i,j),x[i,j]
.....:
(0, 0) 1
(0, 1) 3
(1, 0) 2
(1, 1) 4
enumerate is a good Python way of getting both values and indexes:
In [847]: for i,v in enumerate(x):print i,v
0 [1 3]
1 [2 4]
Or you can use meshgrid to generate all the indexes, as arrays
In [843]: I,J=np.meshgrid(range(2),range(2))
In [844]: I
Out[844]:
array([[0, 1],
[0, 1]])
In [845]: J
Out[845]:
array([[0, 0],
[1, 1]])
In [846]: x[I,J]
Out[846]:
array([[1, 2],
[3, 4]])
Note that most of these iterative methods just treat your array as a list of lists. They don't take advantage of the array nature, and will be slow compared to methods that work with the whole x.