Applying a function along a numpy array using indexes as parameters - python

I am trying to find a way to run a function through a whole ndarray using the indexes of every value as parameters. A regular loop is quite slow and I can't find a way to make it work using numpy built-in functions. The next example code summarizes what i'm trying to do. Thanks in advance.
import numpy as np
arr = np.arange(10).reshape(2, 5)
print(arr)
def example_func(row, col, value):
return(row + col + value)
for row in range(arr.shape[0]):
for col in range(arr.shape[1]):
arr[row, col] = example_func(row, col, arr[row, col])
print(arr)
[[0 1 2 3 4]
[5 6 7 8 9]]
[[ 0 2 4 6 8]
[ 6 8 10 12 14]]

What you try to do can be done with meshgrid.
Return coordinate matrices from coordinate vectors.
n_rows, n_cols = arr.shape
col_matrix, row_matrix = np.meshgrid(np.arange(n_cols), np.arange(n_rows))
result = arr + col_matrix + row_matrix
print(result)
This returns
[[ 0 2 4 6 8]
[ 6 8 10 12 14]]

Related

how to make rank array in numpy

Given a numpy ndarray A, return its rank array.
Input : [[ 9 4 15 0 18]
[16 19 8 10 1]]
Return value: [[4 2 6 0 8]
[7 9 3 5 1]]
**but I didnt solve actually I solve but my solution is wrong
how can I solve ? please help meemphasized text**
import numpy as np
array=np.array([[9,4,15,0,18],[16,19,8,10,1]])
array_1=np.array([9,4,15,0,18])
array_2=np.array([16,19,8,10,1])
temp1 = array_1.argsort()
temp2 = array_2.argsort()
ranks1 = np.arange(len(array_1))[temp1.argsort()]
rankss=ranks1.argsort()
ranks2 = np.arange(len(array_2))[temp2.argsort()]
print(ranks1*array.ndim)
print(rankss)
If you pass axis=None to argsort then the source array
is flattened at the first step (and only then arg-sorted).
So probably the shortest code is:
result = arr.argsort(axis=None).reshape(arr.shape)
No need to explicitely flatten the source array and only
a single call to argsort.

Modifying Array Giving Back Wrong Output

I'm new to numpy and am trying to do some slicing and indexing with arrays. My goal is to take an array, and use slicing and indexing to square the last column, and then subtract the first column from that result. I then want to put the new column back into the old array.
I've been able to figure out how to slice and index the column to get the result I want for the last column. My problem however is that when I try to put it back into my original array, I get the wrong output (as seen below).
theNumbers = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]])
sliceColumnOne = theNumbers[:,0]
sliceColumnThree = theNumbers[:,3]**2
editColumnThree = sliceColumnThree - sliceColumnOne
newArray = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12],[editColumnThree]])
print("nums:\n{}".format(newArray))
I want the output to be
[[ 1 2 3 15]
[ 5 6 7 59]
[ 9 10 11 135]
[ 13 14 15 243]]
However mine becomes:
[list([1, 2, 3, 4]) list([5, 6, 7, 8]) list([9, 10, 11, 12])
list([array([ 15, 59, 135, 243])])]
Any suggestions on how to fix this?
Just assign the last numpy array row to the new one "theNumbers[3] = editColumnThree"
Code:
import numpy as np
theNumbers = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]])
sliceColumnOne = theNumbers[:,0]
sliceColumnThree = theNumbers[:,3]**2
editColumnThree = sliceColumnThree - sliceColumnOne
theNumbers[3] = editColumnThree
print("nums:\n{}".format(theNumbers))
Output:
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]
[ 15 59 135 243]]
newArray = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12],[editColumnThree]])
print("nums:\n{}".format(newArray))
this way, editColumnThree is the last row, not column. You can use
newArray = theNumbers.copy() # if a copy is needed
newArray[:,-1] = editColumnThree # replace last (-1) column
If you just want to stack the vectors on top of eachother, use vstack:
import numpy as np
theNumbers = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]])
newNumbers = np.vstack(theNumbers)
print(newNumbers)
>>>[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]
[13 14 15 16]]
But the issue here isn't just that you need to stack these numbers, you are mixing up columns and rows. You are changing a row instead of a column. To change the column, update the last element in each row:
import numpy as np
theNumbers = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]])
LastColumn = theNumbers[:,3]**2
FirstColumn = theNumbers[:,0]
editColumnThree = LastColumn - FirstColumn
for i in range(4):
theNumbers[i,3] = editColumnThree [i]
print(theNumbers)
>>>[[ 1 2 3 15]
[ 5 6 7 59]
[ 9 10 11 135]
[ 13 14 15 243]]

Loop through an array column in order to find the required values python

I have a minimum and a maximum value, i also have a 70X3 array. I would like to find all the values from the second column of the array which are within the range of the min and max value and export all 3 columns of the array for those values.
For example
A=[2,3,4
3,5,6
5,5,5
5,6,7
10,11,22
3,50,6]
Max value is 11 and min is 5 the result of the matrix would be something like
B=[3,5,6
5,5,5
5,6,7
10,11,22]
Up till now i what i did is :
for i in MatrixA[:,1]):
if i<maximum and i>minimum:
aa.append(i)
aa=np.asarray(aa)
But this only finds the range of values i need from the second column and not the corresponding values from column 1 and 3
You can use
A[numpy.logical_and(5 <= A[:, 1], A[:, 1] <= 11), :]
With simple numpy expression:
import numpy as np
a = np.array([[2,3,4],[3,5,6], [5,5,5], [5,6,7],[10,11,22], [3,50,6]])
b = a[(a[:,1] >= 5) & (a[:,1] <= 11)]
print(b)
The output:
[[ 3 5 6]
[ 5 5 5]
[ 5 6 7]
[10 11 22]]
a[:,1] - considering values from specified axis (1 axis, 2nd column)

Python: how to reduce the dimension of a matrix by doing the sum of the first neighbors?

Suppose we have a matrix of dimension N x M and we want to reduce its dimension preserving the values in each by summing the firs neighbors.
Suppose the matrix A is a 4x4 matrix:
A =
3 4 5 6
2 3 4 5
2 2 0 1
5 2 2 3
we want to reduce it to a 2x2 matrix as following:
A1 =
12 20
11 6
In particular my matrix represent the number of incident cases in an x-y plane. My matrix is A=103x159, if I plot it I get:
what I want to do is to aggregate those data to a bigger area, such as
Assuming you're using a numpy.matrix:
import numpy as np
A = np.matrix([
[3,4,5,6],
[2,3,4,5],
[2,2,0,1],
[5,2,2,3]
])
N, M = A.shape
assert N % 2 == 0
assert M % 2 == 0
A1 = np.empty((N//2, M//2))
for i in range(N//2):
for j in range(M//2):
A1[i,j] = A[2*i:2*i+2, 2*j:2*j+2].sum()
Though these loops can probably be optimized away by proper numpy functions.
I see that there is a solution using numpy.maxtrix, maybe you can test my solution too and return your feedbacks.
It works with a*b matrix if a and b are even. Otherwise, it may fail if a or b are odd.
Here is my solution:
v = [
[3,4,5,6],
[2,3,4,5],
[2,2,0,1],
[5,2,2,3]
]
def shape(v):
return len(v), len(v[0])
def chunks(v, step):
"""
Chunk list step per step and sum
Example: step = 2
[3,4,5,6] => [7,11]
[2,3,4,5] => [5,9]
[2,2,0,1] => [4,1]
[5,2,2,3] => [7,5]
"""
for i in v:
for k in range(0, len(i),step):
yield sum(j for j in i[k:k+step])
def sum_chunks(k, step):
"""
Sum near values with step
Example: step = 2
[
[7,11], [
[5,9], => [12, 11],
[4,1], [20, 6]
[7,5] ]
]
"""
a, c = [k[i::step] for i in range(step)], []
print(a)
for m in a:
# sum near values
c.append([sum(m[j:j+2]) for j in range(0, len(m), 2)])
return c
rows, columns = shape(v)
chunk_list = list(chunks(v, columns // 2))
final_sum = sum_chunks(chunk_list, rows // 2)
print(final_sum)
Output:
[[12, 11], [20, 6]]

Loop across K-uplets from a N-K matrix in python

I have to use dynamic programming in a python script.
I defined a numpy array u with shape=(N,K).
I want to pick one element for each column, therefore generating a K-uplets.
How would you proceed to loop efficiently across all K-uplets generated this way ? A solution would be to use
import itertools
itertools.combination_with_replacement(list,K)
where list = [0..N-1], but I will need to build iteratively each of my K-uplets using the output (index) of the itertools method.
Is there a more direct way to proceed ?
Thanks
Vincent
You can build the K-uplet with arr[ind, np.arange(K)]. Of course, that's actually a NumPy ndarray, but they are easy to convert to tuplets if you really want tuplets: tuple(arr[ind, np.arange(K)]).
import numpy as np
import itertools as IT
N, K = 5,3
arr = np.arange(N*K).reshape(N,K)
print(arr)
# [[ 0 1 2]
# [ 3 4 5]
# [ 6 7 8]
# [ 9 10 11]
# [12 13 14]]
for ind in IT.combinations_with_replacement(range(N), K):
print(arr[ind, np.arange(K)])
# [0 1 2]
# [0 1 5]
# [0 1 8]
# [ 0 1 11]
# ...

Categories

Resources