Renaissance Man
Renaissance Man

Reputation: 53

Creating numpy array from calculations across arrays

I currently have the task of creating a 4x4 array with operations performed on the cells

Below you will see a function that takes in array into function the_matrix which returns adj_array

It then has a for loop that is supposed to loop through array, looking at the the cell in ref_array and upon finding the matching first two numbers in array (like 6,3") it will put that function lambda N: 30 into it's respective cell in adj_array, as it will do for all cells in the 4x4 matrix

Essentially the function should return an array like this

array([[inf, <function <lambda> at 0x00000291139AF790>,
<function <lambda> at 0x00000291139AF820>, inf],
[inf, inf, inf, <function <lambda> at 0x00000291139AF8B0>],
[inf, inf, inf, <function <lambda> at 0x00000291139AF940>],
[inf, inf, inf, inf]], dtype=object)

My work so far below

def the_matrix(array):
  

    ref_array = np.zeros((4,4), dtype = object)
    ref_array[0,0] = (5,0)
    ref_array[0,1] = (5,1)
    ref_array[0,2] = (5,2)
    ref_array[0,3] = (5,3)
    ref_array[1,0] = (6,0)
    ref_array[1,1] = (6,1)
    ref_array[1,2] = (6,2)       
    ref_array[1,3] = (6,3)       
    ref_array[2,0] = (7,0)     
    ref_array[2,1] = (7,1)       
    ref_array[2,2] = (7,2)      
    ref_array[2,3] = (7,3)
    ref_array[3,0] = (8,0)
    ref_array[3,1] = (8,1)
    ref_array[3,2] = (8,2)
    ref_array[3,3] = (8,3)
 
   
    for i in ref_array:
        for a in i: #Expecting to get (5,1) here, but's showing me array
            if a == array[0, 0:2]: #This specific slice was a test
             put the function in that cell for adj_array

    return adj_array

array = np.array([[5, 1, lambda N: 120],
                  [5, 2, lambda N: 30],
                  [6, 3, lambda N: 30],
                  [7, 3, lambda N: N/30]])

Have tried variations of this for loop, and it's throwing errors. For one, the a in the for loop is displaying the input argument array, which is weird because it hasn't been called in the loop at that stage. My intention here is to refer to the exact cell in ref_array.

Not sure where I'm going wrong here and how I'm improperly looping through. Any help appreciated

Upvotes: 0

Views: 66

Answers (1)

hpaulj
hpaulj

Reputation: 231540

Your ref_array is object dtype, (4,4) containing tuples:

In [26]: ref_array
Out[26]: 
array([[(5, 0), (5, 1), (5, 2), (5, 3)],
       [(6, 0), (6, 1), (6, 2), (6, 3)],
       [(7, 0), (7, 1), (7, 2), (7, 3)],
       [(8, 0), (8, 1), (8, 2), (8, 3)]], dtype=object)

Your iteration, just showing the iteration variables. I'm using `repr

In [28]: for i in ref_array:
    ...:     print(repr(i))
    ...:     for a in i:
    ...:         print(repr(a))
    ...: 
array([(5, 0), (5, 1), (5, 2), (5, 3)], dtype=object)
(5, 0)
(5, 1)
(5, 2)
(5, 3)
...

So i is a "row" of the array, itself a 1d object dtype array.

a is one of those objects, a tuple.

Your description of the alternatives is vague. But assume on tries to start with a numeric dtype array

In [30]: arr = np.array(ref_array.tolist())
In [31]: arr
Out[31]: 
array([[[5, 0],
        [5, 1],
        [5, 2],
        [5, 3]],

         ...
        [8, 2],
        [8, 3]]])
In [32]: arr.shape
Out[32]: (4, 4, 2)

now the looping:

In [33]: for i in arr:
    ...:     print(repr(i))
    ...:     for a in i:
    ...:         print(repr(a))
    ...: 
array([[5, 0],          # i is a (4,2) array
       [5, 1],
       [5, 2],
       [5, 3]])
array([5, 0])           # a is (2,) array....
array([5, 1])
array([5, 2])
array([5, 3])

If "the a in the for loop is displaying the input argument array", it's most likely because a IS a an array.

Keep in mind that object dtype arrays are processed at list speeds. You might as well think of them as bastardized lists. While they have some array enhancements (multidimensonal indexing etc), the elements are still references, and are processed as in lists.

I haven't paid attention as to why you are putting lambdas in the array. It looks ugly, and I don't see what it gains you. They can't be "evaluated" at array speeds. You'd have to do some sort of iteration or list comprehension.

edit

A more direct way of generating the arr, derived from ref_array:

In [39]: I,J = np.meshgrid(np.arange(5,9), np.arange(0,4), indexing='ij')
In [40]: I
Out[40]: 
array([[5, 5, 5, 5],
       [6, 6, 6, 6],
       [7, 7, 7, 7],
       [8, 8, 8, 8]])
In [41]: J
Out[41]: 
array([[0, 1, 2, 3],
       [0, 1, 2, 3],
       [0, 1, 2, 3],
       [0, 1, 2, 3]])
In [42]: arr = np.stack((I,J), axis=2)  # shape (4,4,2)

If the function was something like

In [46]: def foo(I,J):
    ...:     return I*10 + J
    ...: 

You could easily generate a value for each pair of the values in ref_array.

In [47]: foo(I,J)
Out[47]: 
array([[50, 51, 52, 53],
       [60, 61, 62, 63],
       [70, 71, 72, 73],
       [80, 81, 82, 83]])

Upvotes: 1

Related Questions