Calculate mean of each image block - Python [duplicate] - python

This question already has answers here:
How to evaluate the sum of values within array blocks
(3 answers)
Closed 3 years ago.
I have a matrix like below
c = [[ 1 2 3 4 5 6 7 8 9 1]
[ 2 3 4 5 6 7 8 9 1 2]
[ 3 4 5 6 7 8 9 1 2 3]
[ 4 5 6 7 8 9 1 2 3 4]]
From the given SO ANSWERS in this post, I used it to divide the matrix into blocks (2*5) like below
def blockshaped(arr, nrows, ncols):
"""
Return an array of shape (n, nrows, ncols) where
n * nrows * ncols = arr.size
If arr is a 2D array, the returned array should look like n subblocks with
each subblock preserving the "physical" layout of arr.
"""
h, w = arr.shape
assert h % nrows == 0, "{} rows is not evenly divisble by {}".format(h, nrows)
assert w % ncols == 0, "{} cols is not evenly divisble by {}".format(w, ncols)
return (arr.reshape(h//nrows, nrows, -1, ncols)
.swapaxes(1,2)
.reshape(-1, nrows, ncols))
print(blockshaped(c, 2, 5))
Result:
[[[ 1 2 3 4 5 ]
[ 2 3 4 5 6 ]]
[[ 6 7 8 9 1 ]
[ 7 8 9 1 2]]
[[ 3 4 5 6 7 ]
[ 4 5 6 7 8 ]]
[[ 8 9 1 2 3 ]
[ 9 1 2 3 4]]]
I got 4 blocks of matrix, and now I need the mean value of each block. How to calculate the mean of this each block?
When I try to use the mean() it is going to calculate the mean for the whole matrix but not for each block.

1. Half line solution with List comprehension
results = blockshaped(c, 2, 5)
block_means = [np.mean(results[block,:,:]) for block in range(results.shape[0])]
print(block_means)
# [3.5, 5.8, 5.5, 4.2]
Version 2 -- shorter code:
results = blockshaped(c, 2, 5)
block_means = [np.mean(block) for block in results]
# [3.5, 5.8, 5.5, 4.2]
In [15]: %timeit [np.mean(results[block,:,:]) for block in range(results.shape[0])]
10000 loops, best of 3: 35.9 µs per loop
In [16]: %timeit [np.mean(block) for block in results]
10000 loops, best of 3: 33.4 µs per loop
P.S: The second solution will only work if the blocks are in the first (0) dimension of results.

Another option is to use the map function:
means = np.round(map(np.mean, r),3)
print(means)
which results in:
[ 3.5 5.8 5.5 4.2]

Related

Shuffling an array except the first and the last element in Python

I am generating a normal distribution but keeping the mean and std exactly the same by using np.random.seed(0). I am trying to shuffle r except the first and the last elements of the array but it keeps the remaining elements at the same location in the array as shown in the current output. I also present the expected output.
import numpy as np
np.random.seed(0)
mu, sigma = 50, 2.0 # mean and standard deviation
Nodes=10
r = np.random.normal(mu, sigma, Nodes)
sort_r = np.sort(r);
r1=sort_r[::-1]
r1=r1.reshape(1,Nodes)
r2 = r.copy()
np.random.shuffle(r2.ravel()[1:])
r2=r2.reshape(1,Nodes) #actual radius values in mu(m)
maximum = r2.max()
indice1 = np.where(r2 == maximum)
r2[indice1] = r2[0][0]
r2[0][0] = maximum
r2[0][Nodes-1] = maximum #+0.01*maximum
print("r2 with max at (0,0)=",[r2])
The current output for many runs is
r2 with max at (0,0)= [array([[54.4817864 , 51.90017684, 53.52810469, 53.73511598, 48.04544424,
51.95747597, 50.80031442, 50.821197 , 49.7935623 , 54.4817864 ]])]
The expected output is (shuffling all elements randomly except the first and the last element)
Run 1: r2 with max at (0,0)= [array([[54.4817864 , 53.52810469, 51.90017684, ,53.73511598, 48.04544424,49.7935623 ,50.80031442, 50.821197 , 51.95747597, 54.4817864 ]])]
Run 2: r2 with max at (0,0)= [array([[54.4817864 , 51.90017684,53.52810469, 48.04544424, 53.73511598, 51.95747597, 49.7935623 ,50.80031442, 50.821197 , 54.4817864 ]])]
It's not that clear from your question what do you include in a run.
If, like it seems, you're initializing distribution and seed every time, shuffling it once will always give you the same result. It must be like that because random state is fixed, just like you want your random numbers to be predictable also the shuffle operation will return always the same result.
Let me show you what I mean with some simpler code than yours:
# reinit distribution and seed at each run
for run in range(5):
np.random.seed(0)
a = np.random.randint(10, size=10)
np.random.shuffle(a)
print(f'{run}:{a}')
Which will print
0:[2 3 9 0 3 7 4 5 3 5]
1:[2 3 9 0 3 7 4 5 3 5]
2:[2 3 9 0 3 7 4 5 3 5]
3:[2 3 9 0 3 7 4 5 3 5]
4:[2 3 9 0 3 7 4 5 3 5]
What you want is to initialize your distribution once and shuffle it at each run:
# init distribution and just shuffle it at each run
np.random.seed(0)
a = np.random.randint(10, size=10)
for run in range(5):
np.random.shuffle(a)
print(f'{run}:{a}')
Which will print:
0:[2 3 9 0 3 7 4 5 3 5]
1:[9 0 3 4 2 5 7 3 3 5]
2:[2 0 3 3 3 5 7 5 4 9]
3:[5 3 5 3 0 2 7 4 9 3]
4:[3 9 3 2 5 7 3 4 0 5]

How to fill a zeros matrix using for loop?

I have an array full of zeros created as A = np.zeros(m,m) and m = 6.
I want to fill this array with specific numbers that each equals sum of it's row and column number; such as A(x,y) = x+y.
How can i do this using for loop and while loop?
Method that avoids a loop with rather significant performance improvement on a large ndarray:
A = np.zeros((6,6))
m = A.shape[0]
n = A.shape[1]
x = np.transpose(np.array([*range(1,m+1)]*n).reshape(n,m))
y = np.array([*range(1,n+1)]*m).reshape(m,n)
A = x+y
print(A)
[[ 2 3 4 5 6 7]
[ 3 4 5 6 7 8]
[ 4 5 6 7 8 9]
[ 5 6 7 8 9 10]
[ 6 7 8 9 10 11]
[ 7 8 9 10 11 12]]
A = np.zeros((6,6))
for i in range(0,A.shape[0]):
for j in range(0, A.shape[1]):
A[i][j] = i+j+2
If you want the rows and columns to be starting from 1, you can directly use this code, but if you want them to be starting from 0 you can surely remove the "+2" in line-4.
Explanation:
I am first traversing the row in a loop when, then traversing the columns in loop 2, and then I am accessing the cell value using A[i][j]. and assigning it to i+j+2 (or just i + j). This way the original array will fill your new values.
Have you tried this?
for y in range(len(A)):
for x in range(len(A[Y]):
A[y][x] = x + y

Mean values inside matrix [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
Suppose we have a 6x6 matrix (numpy ndarray) like:
[1 1 2 2 3 3
1 1 2 2 3 3
4 4 5 5 6 6
4 4 5 5 6 6
7 7 8 8 9 9
7 7 8 8 9 9]
How would I calculate the mean value of each of the 2x2 submatrices containing the same number, and get as an output a 3x3 matrix?
Not sure whether this is what you want
import numpy as np
x = np.arange(1,10).reshape(3,3)
y = np.ones((2,2),dtype=np.int32)
z = np.kron(x,y)
z
def meanpool2d(x):
h,w = x.shape
out = np.zeros((h//2,w//2))
for i in range(h//2):
for j in range(w//2):
out[i][j] = np.mean(x[2*i:2*i+2,2*j:2*j+2])
return out
meanpool2d(z)
Construct the input array
import numpy as np
x = np.arange(1,10).reshape(3,3)
x = np.repeat(x, 2, 0)
x = np.repeat(x, 2, 1)
print(x)
Out:
[[1 1 2 2 3 3]
[1 1 2 2 3 3]
[4 4 5 5 6 6]
[4 4 5 5 6 6]
[7 7 8 8 9 9]
[7 7 8 8 9 9]]
Compute the means of all 2x2 blocks
m = (x.reshape(3, 2, -1, 2)
.swapaxes(1,2)
.mean((2,3)))
print(m)
Out:
[[1. 2. 3.]
[4. 5. 6.]
[7. 8. 9.]]

Create dynamic nested for loops

I have some arrays m rows by 2 `columns (like series of coordinates) and I want to automatize my code so that I will not use nested loop for every coord. Here is my code it runs well and gives right answer coordinates but I want to make a dynamic loop:
import numpy as np
A = np.array([[1,5,7,4,6,2,2,6,7,2],[2,8,2,9,3,9,8,5,6,2],[3,4,0,2,4,3,0,2,6,7],\
[1,5,7,3,4,5,2,7,9,7],[6,2,8,8,6,7,9,6,9,7],[0,2,0,3,3,5,2,3,5,5],[5,5,5,0,6,6,8,5,9,0]\
,[0,5,7,6,0,6,9,9,6,7],[5,5,8,5,0,8,5,3,5,5],[0,0,6,3,3,3,9,5,9,9]])
number = 8292
number = np.asarray([int(i) for i in str(number)]) #split number into array
#the coordinates of every single value contained in required number
coord1=np.asarray(np.where(A == number[0])).T
coord2=np.asarray(np.where(A == number[1])).T
coord3=np.asarray(np.where(A == number[2])).T
coord4=np.asarray(np.where(A == number[3])).T
coordinates = np.array([[0,0]]) #initialize the array that will return all the desired coordinates
solutions = 0 #initialize the array that will give the number of solutions
for j in coord1:
j = j.reshape(1, -1)
for i in coord2 :
i=i.reshape(1, -1)
if (i[0,0]==j[0,0]+1 and i[0,1]==j[0,1]) or (i[0,0]==j[0,0]-1 and i[0,1]==j[0,1]) or (i[0,0]==j[0,0] and i[0,1]==j[0,1]+1) or (i[0,0]==j[0,0] and i[0,1]==j[0,1]-1) :
for ii in coord3 :
ii=ii.reshape(1, -1)
if (np.array_equal(ii,j)==0 and ii[0,0]==i[0,0]+1 and ii[0,1]==i[0,1]) or (np.array_equal(ii,j)==0 and ii[0,0]==i[0,0]-1 and ii[0,1]==i[0,1]) or (np.array_equal(ii,j)==0 and ii[0,0]==i[0,0] and ii[0,1]==i[0,1]+1) or (np.array_equal(ii,j)==0 and ii[0,0]==i[0,0] and ii[0,1]==i[0,1]-1) :
for iii in coord4 :
iii=iii.reshape(1, -1)
if (np.array_equal(iii,i)==0 and iii[0,0]==ii[0,0]+1 and iii[0,1]==ii[0,1]) or (np.array_equal(iii,i)==0 and iii[0,0]==ii[0,0]-1 and iii[0,1]==ii[0,1]) or (np.array_equal(iii,i)==0 and iii[0,0]==ii[0,0] and iii[0,1]==ii[0,1]+1) or (np.array_equal(iii,i)==0 and iii[0,0]==ii[0,0] and iii[0,1]==ii[0,1]-1) :
point = np.concatenate((j,i,ii,iii))
coordinates = np.append(coordinates,point,axis=0)
solutions +=1
coordinates = np.delete(coordinates, (0), axis=0)
import itertools
A = [1, 2, 3]
B = [4, 5, 6]
C = [7, 8, 9]
for (a, b, c) in itertools.product (A, B, C):
print (a, b, c);
outputs:
1 4 7
1 4 8
1 4 9
1 5 7
1 5 8
1 5 9
1 6 7
1 6 8
1 6 9
2 4 7
2 4 8
2 4 9
2 5 7
2 5 8
2 5 9
2 6 7
2 6 8
2 6 9
3 4 7
3 4 8
3 4 9
3 5 7
3 5 8
3 5 9
3 6 7
3 6 8
3 6 9
See documentation for details.

Write multidimensional numpy array to csv

I have a multidimensional numpy array containing function values, and I'd like to write it to a long csv. How can I do that cleanly? I couldn't find a numpy function but maybe I was googling the wrong terms. An example:
#!/usr/bin/python
import csv
import numpy as np
x = np.array([1, 2, 3, 4])
y = np.array([50, 51])
z = np.array([99, 100, 101])
f = np.arange(24).reshape((4, 2, 3)) # Contains f(x, y, z)
assert f.shape == (x.size, y.size, z.size)
## I'd like to create a csv file whose columns are x, y, z, f
## How can I do that?
## np.savetxt("test.csv", a, delimiter=",")
## TypeError: float argument required, not numpy.ndarray
## Works, but does numpy already have a function that does this?
with open("test.csv", "wb") as csvfile:
writer = csv.writer(csvfile, delimiter=",", quotechar="'", quoting=csv.QUOTE_MINIMAL)
writer.writerow(["x", "y", "z", "f"])
for x_index in range(x.size):
for y_index in range(y.size):
for z_index in range(z.size):
writer.writerow([x[x_index], y[y_index], z[z_index],
f[x_index, y_index, z_index]])
I have three vectors x, y, z and an X-by-Y-by-Z array containing function values f(x, y, z). In other words, f[i, j, k] contains the function value f that corresponds to x[i], y[j] and z[k]. Is there a cleaner way to write a long csv with columns x,y,z,f?
Here's head test.csv:
x,y,z,f
1,50,99,0
1,50,100,1
1,50,101,2
1,51,99,3
1,51,100,4
1,51,101,5
2,50,99,6
2,50,100,7
2,50,101,8
Edit: This seems to work as well:
x_y_z = np.array([x for x in itertools.product(x, y, z)])
assert x_y_z.shape[0] == f.size
output_array = np.hstack((x_y_z, f.flatten().reshape((f.size, 1)))
np.savetxt("test2.csv", output_array, comments="", delimiter=",", fmt="%i",
header="x,y,z,f")
Am I reinventing the wheel?
In fact, yes it's lightly more complicated than what it should be.
Given 3 lists x,y and z
import numpy as np
x = [1,2,3]
y = [4,5]
z = [6,7,8]
You need to modify this lists in order to get all possible combinations, use numpy.repeat this way:
new_x = np.array(x).repeat(len(y)*len(z))
print new_x
>> [1 1 1 1 1 1 2 2 2 2 2 2 3 3 3 3 3 3]
new_y = np.array([y]).repeat(len(z),axis=0).repeat(len(x),axis=1)
print new_y
>> [4 4 4 5 5 5 4 4 4 5 5 5 4 4 4 5 5 5]
new_z = np.array([z]).repeat(len(x)*len(y),axis=0)
print new_z
>> [6 7 8 6 7 8 6 7 8 6 7 8 6 7 8 6 7 8]
# reshape y and z just like new_x
new_y = new_y.reshape(new_x.shape)
new_z = new_z.reshape(new_x.shape)
just concatenate them!
# suppose that your vector f
f = np.array(range(len(x)*len(y)*len(z)))
matrix = np.array([new_x,new_y,new_z,f]).T
# or matrix = np.concatenate((np.concatenate((new_x,new_y),axis=1),np.concatenate((new_z,f),axis=1)),axis=1).T
print matrix
>>
[[ 1 4 6 0]
[ 1 4 7 1]
[ 1 4 8 2]
[ 1 5 6 3]
[ 1 5 7 4]
[ 1 5 8 5]
[ 2 4 6 6]
[ 2 4 7 7]
[ 2 4 8 8]
[ 2 5 6 9]
[ 2 5 7 10]
[ 2 5 8 11]
[ 3 4 6 12]
[ 3 4 7 13]
[ 3 4 8 14]
[ 3 5 6 15]
[ 3 5 7 16]
[ 3 5 8 17]]
finally, save the array as csv
np.savetxt('file_name.csv',matrix)

Categories