Related
I have a 40 x 40 x 40 array in Python and would like to extract all i values with k=10 index. I understand how to do this with a nxn array but not a nxnxn array.
Thanks
As per the Numpy Index documentation.
import numpy as np
arr = np.arange(3*4*5).reshape( 3,4,5 )
arr
# array([[[ 0, 1, 2, 3, 4],
# [ 5, 6, 7, 8, 9],
# [10, 11, 12, 13, 14],
# [15, 16, 17, 18, 19]],
# [[20, 21, 22, 23, 24],
# [25, 26, 27, 28, 29],
# [30, 31, 32, 33, 34],
# [35, 36, 37, 38, 39]],
# [[40, 41, 42, 43, 44],
# [45, 46, 47, 48, 49],
# [50, 51, 52, 53, 54],
# [55, 56, 57, 58, 59]]])
arr[:,:,1] # For k = 1
# or arr[ ...,1] as its the last index
This returns a 2d array.
array([[ 1, 6, 11, 16],
[21, 26, 31, 36],
[41, 46, 51, 56]])
I can initialize a numpy array and reshape it at the time of creation.
test = np.arange(32).reshape(4, 8)
which produces this:
array([[ 0, 1, 2, 3, 4, 5, 6, 7],
[ 8, 9, 10, 11, 12, 13, 14, 15],
[16, 17, 18, 19, 20, 21, 22, 23],
[24, 25, 26, 27, 28, 29, 30, 31]])
... but I'd like to know how to start the sequential numbering at a given point, say at 13 rather than at 0. How is that done in numpy?
I've looked for answers and found something somewhat similar but it seems there would be a numpy command to do this.
arange takes an optional start argument.
start = 13 # Any number works here
np.arange(start, start + 32).reshape(4, 8)
# array([[13, 14, 15, 16, 17, 18, 19, 20],
# [21, 22, 23, 24, 25, 26, 27, 28],
# [29, 30, 31, 32, 33, 34, 35, 36],
# [37, 38, 39, 40, 41, 42, 43, 44]])
I have a multiband raster having 23 bands for example. I am reading the raster using GDAL and converting it to numpy array. In numpy when I am checking the array shape it is showing as 23,4,5 i.e. 23 = bands, 4 = row and 5 = col. I want to loop through each pixel in a manner that I am able to get the vector/array of all 23 values related to one pixel.
I am explaining it further in detail by example...
Band 1
[[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10],
[11, 12, 13, 14, 15],
[16, 17, 18, 19, 20]]
Band 2
[[21, 22, 23, 24, 25],
[26, 27, 28, 29, 30],
[31, 32, 33, 34, 35],
[36, 37, 38, 39, 40]]
Band 3
[[31, 32, 33, 34, 35],
[36, 37, 38, 39, 40],
[41, 42, 43, 44, 45],
[46, 47, 48, 49, 50]]
Band 4
[[41, 42, 43, 44, 45],
[46, 47, 48, 49, 50],
[51, 52, 53, 54, 55],
[56, 57, 58, 59, 60]]
Now I want to loop through all bands in such a way that I should get array of values [1,21,31,41] in first iteration and [2,22,32,42] in second iteration and so on. I can do that in R using the pointer math and extract function easily but in python I am not able to do that because I have very less experience with looping and array indexing in python.
I have tried some codes given on the StackOverflow
for cell in arr:
print cell
for cell in arr.flat:
print cell
for row in arr:
for cell in row:
print cell
for (i,row) in enumerate(arr):
for (j,value) in enumerate(row):
print value
The output I am getting is not as required.
As i see it what you need is to have pixel values of same index grouped together. For grouping together same index e use zip here since the bandx itself is not flat we may first flatten then band and then do zip on the flattend bands
Here is example with 3 bands
band1 = np.array( [[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10],
[11, 12, 13, 14, 15],
[16, 17, 18, 19, 20]])
band2 = np.array([[21, 22, 23, 24, 25],
[26, 27, 28, 29, 30],
[31, 32, 33, 34, 35],
[36, 37, 38, 39, 40]])
band3 = np.array([[31, 32, 33, 34, 35],
[36, 37, 38, 39, 40],
[41, 42, 43, 44, 45],
[46, 47, 48, 49, 50]])
arr = [band1,band2,band3]
Following will give you array of tuples as you expected
zip(*map(lambda x:x.flatten(),arr))
If the bands are not numpy arrays but normal python arrays ,you may do the following
zip(*map(lambda x:x.flatten(),np.array(arr)))
A simple way is using np.nditer:
>>> for i in np.nditer((Band1, Band2, Band3, Band4)):
... print(i)
This prints
(array(1), array(21), array(31), array(41))
(array(2), array(22), array(32), array(42))
(array(3), array(23), array(33), array(43))
(array(4), array(24), array(34), array(44))
(array(5), array(25), array(35), array(45))
(array(6), array(26), array(36), array(46))
(array(7), array(27), array(37), array(47))
(array(8), array(28), array(38), array(48))
(array(9), array(29), array(39), array(49))
(array(10), array(30), array(40), array(50))
(array(11), array(31), array(41), array(51))
(array(12), array(32), array(42), array(52))
(array(13), array(33), array(43), array(53))
(array(14), array(34), array(44), array(54))
(array(15), array(35), array(45), array(55))
(array(16), array(36), array(46), array(56))
(array(17), array(37), array(47), array(57))
(array(18), array(38), array(48), array(58))
(array(19), array(39), array(49), array(59))
(array(20), array(40), array(50), array(60))
Even though it seems strange that this returns arrays actually makes it a really cool feature because these are views of the original array so you don't have the overhead of unpacking the value as python type and these zero-dimensional arrays behave (almost) like native python types.
travel_mat1= numpy.array([[23,23,20,24,28,12,17,10],[11,27,17,19,24,18,23,7],
[17,26,22,13,18,29,30,18],[22,21,28,7,18,29,30,18],[27,16,33,36,10,23,26,25],
[31,13,36,14,26,23,20,27],[34,7,33,20,35,17,14,24],[28,13,27,26,37,11,10,18],
[25,17,33,28,34,10,12,15]])
I need to change the size of array dynamically with no loss of actual data in the array. Means, I need to have a virtual dynamic array.
The above array Travel_mat1 is a 9X8 matrix. So if i need a 8X7 size matrix from Travel_mat1, it should look like:
([[23,23,20,24,28,12,17],[11,27,17,19,24,18,23],[17,26,22,13,18,29,30],
[22,21,28,7,18,29], [27,16,33,36,10,23,26],[31,13,36,14,26,23,20],
[34,7,33,20,35,17,14],[28,13,27,26,37,11,10]]).
Means, I need to reduce a row and a column in this case. How can I do this in python?
You can use numpy.delete:
>>> numpy.delete(numpy.delete(travel_mat1, 8, 0), 7, 1)
array([[23, 23, 20, 24, 28, 12, 17],
[11, 27, 17, 19, 24, 18, 23],
[17, 26, 22, 13, 18, 29, 30],
[22, 21, 28, 7, 18, 29, 30],
[27, 16, 33, 36, 10, 23, 26],
[31, 13, 36, 14, 26, 23, 20],
[34, 7, 33, 20, 35, 17, 14],
[28, 13, 27, 26, 37, 11, 10]])
I am using nested arrays as a matrix representation. I created the following function for spliting quadratic matrices with size 2^k into four equal parts (used for Strassen algorithm):
import itertools
def splitmat(mat):
n = len(mat)
return map( \
lambda (x,y):map(lambda z:z[y[0]:y[1]],mat[x[0]:x[1]]), \
itertools.product([(0,n/2),(n/2,n)],repeat=2)
)
Now I'm trying to find an inverse function that joins the four parts back to a full matrix. I could use two nested loops, but may there be any pythonic way to achieve this? I would prefer to not use numpy but only builtin modules. Do you have any idea or hint how to achieve this?
Your inverse operation can be split into 2 simplier operation:
concatenate rows(numpy.vstack)
concatenate columns(numpy.hstack)
So, if you have matrix divided into 4 submatrix:
M = |m1|m2|
|m3|m4|
then M = hstack(vstack(m1, m2), vstack(m3, m4).
This operations can be code like this:
import itertools
import math
# iterators
def ihstack(*matrixes):
return map(lambda rows: itertools.chain(*rows), zip(*matrixes))
def ivstack(*matrixes):
return itertools.chain(*matrixes)
# main function
def squarejoin(*matrixes):
size = int(math.sqrt(len(matrixes)))
assert size ** 2 == len(matrixes), 'Incorrect number of matrices'
return _matrixjoin(matrixes, size, size)
def _matrixjoin(matrixes, hsize, vsize):
print(matrixes, hsize, vsize)
return ivstack(*(ihstack(*itertools.islice(matrixes, i*hsize, (i+1)*hsize)) for i in range(vsize)))
Here I have an example program where a 2 loops implementation works and is crystal clear in its intent, a 1 loop implementation works and is, imho, slightly less clear and eventually a 0 (explicit, btw) loops implementation that, alas, is buggy.
My vote goes to the two loops... further, I'd like to be shown what's wrong with my 0 loops attempt
Code
import itertools
def pm(m):
for row in m: print row
mat = []
n = 8
for i in range(n):
mat.append(range(i*n, i*n+n))
# this is shorthand for your splitmat function
res = map(lambda (x,y):
map(lambda z:z[y[0]:y[1]],mat[x[0]:x[1]]),
itertools.product([(0,n/2),(n/2,n)],repeat=2))
pm(res)
print "\n2 cycles"
mat = []
for i, j in ((0,1),(2,3)):
for a, b in zip(res[i],res[j]):
mat.append(a+b)
pm(mat)
print "\n1 cycle"
mat = []
for i, j in ((0,1),(2,3)):
map(lambda x: mat.append(x[0]+x[1]), zip(res[i],res[j]))
pm(mat)
print "\n0 cycles"
mat = map(lambda i_j:
map(lambda x: x[0]+x[1], zip(res[i_j[0]],res[i_j[1]])), ((0,1),(2,3)))
pm(mat)
Output
[[0, 1, 2, 3], [8, 9, 10, 11], [16, 17, 18, 19], [24, 25, 26, 27]]
[[4, 5, 6, 7], [12, 13, 14, 15], [20, 21, 22, 23], [28, 29, 30, 31]]
[[32, 33, 34, 35], [40, 41, 42, 43], [48, 49, 50, 51], [56, 57, 58, 59]]
[[36, 37, 38, 39], [44, 45, 46, 47], [52, 53, 54, 55], [60, 61, 62, 63]]
2 cicli
[0, 1, 2, 3, 4, 5, 6, 7]
[8, 9, 10, 11, 12, 13, 14, 15]
[16, 17, 18, 19, 20, 21, 22, 23]
[24, 25, 26, 27, 28, 29, 30, 31]
[32, 33, 34, 35, 36, 37, 38, 39]
[40, 41, 42, 43, 44, 45, 46, 47]
[48, 49, 50, 51, 52, 53, 54, 55]
[56, 57, 58, 59, 60, 61, 62, 63]
1 ciclo
[0, 1, 2, 3, 4, 5, 6, 7]
[8, 9, 10, 11, 12, 13, 14, 15]
[16, 17, 18, 19, 20, 21, 22, 23]
[24, 25, 26, 27, 28, 29, 30, 31]
[32, 33, 34, 35, 36, 37, 38, 39]
[40, 41, 42, 43, 44, 45, 46, 47]
[48, 49, 50, 51, 52, 53, 54, 55]
[56, 57, 58, 59, 60, 61, 62, 63]
0 cicli
[[0, 1, 2, 3, 4, 5, 6, 7], [8, 9, 10, 11, 12, 13, 14, 15], [16, 17, 18, 19, 20, 21, 22, 23], [24, 25, 26, 27, 28, 29, 30, 31]]
[[32, 33, 34, 35, 36, 37, 38, 39], [40, 41, 42, 43, 44, 45, 46, 47], [48, 49, 50, 51, 52, 53, 54, 55], [56, 57, 58, 59, 60, 61, 62, 63]]