Home > Mobile >  a matrix making using i, j for-loop (for 2*9 shape)
a matrix making using i, j for-loop (for 2*9 shape)

Time:05-02

I hope to make the a matrix using i, j for-loop. The code I tried is as below. The output 'xcount1' shows 1 by 18 shape. but, the output I hope is 2 by 9 shape as below.

xcount1 = [[0. 0.],[0. 1.],[0. 2.],[1. 0.],[1. 1.],[1. 2.],[2. 0.],[2. 1.],[2. 2.]]

How the below code need to modified for above output?

import numpy as np
xcount1 = []
for i in range(3):
    for j in range(3):
        xcount1 = np.append(xcount1,[i,j])
print(np.shape(xcount1))

CodePudding user response:

A fast way to do this in numpy (without doing all the work to generate a list of lists in Python, just to convert it to numpy at the end and get no vectorization benefits during construction) is:

# Make a range of floats from 0 to 8, double each one in place, then reshape it
# so it becomes nine two-element subarrays that look like:
array([[0., 0.], [1., 1.], [2., 2.], ... [7., 7.], [8., 8.]])
xcount1 = np.arange(9, dtype=float).repeat(2).reshape(9,2)

xcount1[:, 0] //= 3  # Divide first element of each two element subarray by 3
xcount1[:, 1] %= 3   # Reduce secodnd element of each subarray modulo 3

# xcount is now *exactly* what you expected
print(xcount)

which outputs:

[[0. 0.]
 [0. 1.]
 [0. 2.]
 [1. 0.]
 [1. 1.]
 [1. 2.]
 [2. 0.]
 [2. 1.]
 [2. 2.]]

Your original code didn't work because numpy.append, when not provided an axis argument, flattens both input and output before appending, so you lose your structure. I'm not sufficiently expert with numpy to make it build the correct way from scratch using append (that said, np.append is incredibly slow, making a copy every time, so it's a bad solution anyway), but it's easy to reshape it once you're done. Just add:

xcount1 = xcount1.reshape(9,2)

to the end of your code and it will reshape it to match the groupings you intended (though it would be much slower than my code, or even just xcount1 = np.array([[i, j] for i in range(3) for j in range(3)], dtype=float) which doesn't benefit from any vectorization, but for small enough inputs it doesn't really matter).

CodePudding user response:

You don't need numpy here. Simple pythonic way of doing it would be

xcount1 = [[i,j]for i in range(3) for j in range(3)]

With lists similarly

xcount1 = []
for i in range(3):
    for j in range(3):
        xcount1.append([i,j])
print(xcount1)

Numpy Way

import numpy as np
xcount1 = np.empty((0,2))
for i in range(3):
    for j in range(3):
        xcount1 = np.append(xcount1, np.array([[i,j]]), axis=0)

A different numpy approach

np.flip(np.dstack(np.meshgrid(np.arange(3), np.arange(3))).reshape(-1, 2), axis=1)

CodePudding user response:

If you read the docs for np.append() you'll find out that we need to provide an axis to prevent the list from getting flattened. Earlier when you did not provide an axis the list was getting flattened which means it was getting converted to 1-D just like in your output. To prevent that you need to provide an axis of the row i.e. axis = 0(in order to append it to each row.). Also, you need to make sure that your xcount1 has the same dimensions as the [i,j] so use np.empty((0,2)).

Here's how you can do it:

import numpy as np

xcount1 = np.empty((0,2)) # Create an empty list with desired dimension
for i in range(3):
    for j in range(3):
        xcount1 = np.append(xcount1,np.array([[i,j]]), axis = 0) # Provide axis of rows and convert the list to `np.array()`

print(xcount1)

Output:

array([[0., 0.],
       [0., 1.],
       [0., 2.],
       [1., 0.],
       [1., 1.],
       [1., 2.],
       [2., 0.],
       [2., 1.],
       [2., 2.]])

CodePudding user response:

Just use np.indices and some transposing/reshaping:

np.indices((3,3)).transpose(1,2,0).reshape(-1,2)
Out[]: 
array([[0, 0],
       [0, 1],
       [0, 2],
       [1, 0],
       [1, 1],
       [1, 2],
       [2, 0],
       [2, 1],
       [2, 2]])

Or, as @MichaelSczcesny noted in the commments, np.indices((3,3)).reshape(2,-1).T works as well.

  • Related