You want np.ndenumerate:
>>> for (x, y), element in np.ndenumerate(np.array([[i for i in "egg"] for j in range(3)])):
... print(x, y, element)
...
(0L, 0L, 'e')
(0L, 1L, 'g')
(0L, 2L, 'g')
(1L, 0L, 'e')
(1L, 1L, 'g')
(1L, 2L, 'g')
(2L, 0L, 'e')
(2L, 1L, 'g')
(2L, 2L, 'g')
Answer from Jaime on Stack OverflowPython enumerate through 2D array in numpy - Stack Overflow
Iterate over numpy with index (numpy equivalent of python enumerate) - Stack Overflow
python - How to iterate 1d NumPy array with index and value - Stack Overflow
python - How to iterate 1d NumPy array with index and value - Stack Overflow
As I've become more familiar with the NumPy and general scientific array processing ecosystem, it's become clearer to me that iteration is usually outright wrong due to how slow it is in comparison, and writing to use a vectorized operation is best whenever possible. Though the style is not as obvious/Pythonic at first, I've (anecdotally) gained ridiculous speedups with vectorized operations; more than 1000x in a case of swapping out a form like some row iteration .apply(lambda)
@MSeifert's answer much better provides this and will be significantly more performant on a dataset of any real size
More general Answer by @cs95 covering and comparing alternatives to iteration in Pandas
Original Answer
You can iterate through the values in your array with numpy.ndenumerate to get the indices of the values in your array.
Using the documentation above:
A = np.array([[1,2,3],[4,5,6],[7,8,9]])
for index, values in np.ndenumerate(A):
print(index, values) # operate here
You can do it using np.ndenumerate but generally you don't need to iterate over an array.
You can simply create a meshgrid (or open grid) to get all indices at once and you can then process them (vectorized) much faster.
For example
>>> x, y = np.mgrid[slice(A.shape[0]), slice(A.shape[1])]
>>> x
array([[0, 0, 0],
[1, 1, 1],
[2, 2, 2]])
>>> y
array([[0, 1, 2],
[0, 1, 2],
[0, 1, 2]])
and these can be processed like any other array. So if your function that needs the indices can be vectorized you shouldn't do the manual loop!
For example to calculate the lattice distance for each point to a point say (2, 3):
>>> abs(x - 2) + abs(y - 3)
array([[5, 4, 3],
[4, 3, 2],
[3, 2, 1]])
For distances an ogrid would be faster. Just replace np.mgrid with np.ogrid:
>>> x, y = np.ogrid[slice(A.shape[0]), slice(A.shape[1])]
>>> np.hypot(x - 2, y - 3) # cartesian distance this time! :-)
array([[ 3.60555128, 2.82842712, 2.23606798],
[ 3.16227766, 2.23606798, 1.41421356],
[ 3. , 2. , 1. ]])
There are a few alternatives. The below assumes you are iterating over a 1d NumPy array.
Iterate with range
for j in range(theta.shape[0]): # or range(len(theta))
some_function(j, theta[j], theta)
Note this is the only of the 3 solutions which will work with numba. This is noteworthy since iterating over a NumPy array explicitly is usually only efficient when combined with numba or another means of pre-compilation.
Iterate with enumerate
for idx, j in enumerate(theta):
some_function(idx, j, theta)
The most efficient of the 3 solutions for 1d arrays. See benchmarking below.
Iterate with np.ndenumerate
for idx, j in np.ndenumerate(theta):
some_function(idx[0], j, theta)
Notice the additional indexing step in idx[0]. This is necessary since the index (like shape) of a 1d NumPy array is given as a singleton tuple. For a 1d array, np.ndenumerate is inefficient; its benefits only show for multi-dimensional arrays.
Performance benchmarking
# Python 3.7, NumPy 1.14.3
np.random.seed(0)
arr = np.random.random(10**6)
def enumerater(arr):
for index, value in enumerate(arr):
index, value
pass
def ranger(arr):
for index in range(len(arr)):
index, arr[index]
pass
def ndenumerater(arr):
for index, value in np.ndenumerate(arr):
index[0], value
pass
%timeit enumerater(arr) # 131 ms
%timeit ranger(arr) # 171 ms
%timeit ndenumerater(arr) # 579 ms
You can use numpy.ndenumerate for example
import numpy as np
test_array = np.arange(2, 3, 0.1)
for index, value in np.ndenumerate(test_array):
print(index[0], value)
For more information refer to https://docs.scipy.org/doc/numpy/reference/generated/numpy.ndenumerate.html
I think there's no more "elegant" form, sincerely, I will use the basic range(1,q_ij-1)* , but all is our programming manner at the end, just do it with the form that youre more confortable and works well
range(start, stop[, step])
Construct the array with sliced assignment:
In [164]: arr = np.zeros((4,4),int)
In [165]: arr[1:3,1:3] = np.arange(1,5).reshape(2,2)
In [166]: arr
Out[166]:
array([[0, 0, 0, 0],
[0, 1, 2, 0],
[0, 3, 4, 0],
[0, 0, 0, 0]])
Since you print each element, a double loop on the desired indices is just as good as ndenumerate (or anything else that 'hides' the indexing):
In [167]: for i in range(1,3):
...: for j in range(1,3):
...: print(f'({i},{j}) {arr[i,j]}')
...:
(1,1) 1
(1,2) 2
(2,1) 3
(2,2) 4
There's nothing elegant about printing the elements of an array one by one with coodinates.
edit
q[i+1][j] + q[i-1][j] + q[i][j+1] + q[i][j-1] - 4*a[i][j]
can rewritten with slices as something like this (defails may not be right)
q[2:4,1:3] - q[0:2,1:3] + ... - 4*a[1:3, 1:3]
What I'm aiming for is a 2d extension of the basic difference calculation:
In [178]: x = np.array([1,0,3,2,0,1])
In [179]: x[1:] - x[:-1]
Out[179]: array([-1, 3, -1, -2, 1])
This is what np.diff(x).
In scipy.signal there's a convolve function that may be applicable. I've seen others use it, but haven't myself.
https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.convolve.html