简体   繁体   中英

How to create an n-dimensional array using given data using numpy ndarray

I am trying to cast my data into an ndarray. Although I get what I want but while testing I am not able to figure out why it gives me this output.

I get the output:

np.ndarray(shape = (2,1),buffer = np.array([1,2,3,4]))
array([[4.24399158e-314],
   [8.48798317e-314]])

However for this block I am able to cast my random numbers the way I want.

def x_mat(n,m):
   np.random.seed(0)
   randoms = np.random.normal(size=n*m)
   print(randoms)
   rand_mat = np.ndarray(shape = (n,m),buffer = randoms)
   return(rand_mat)
x_mat(5,2)

to give:

[ 1.76405235  0.40015721  0.97873798  2.2408932   1.86755799 -0.97727788 
  0.95008842 -0.15135721 -0.10321885  0.4105985 ]


array([[ 1.76405235,  0.40015721],
       [ 0.97873798,  2.2408932 ],
       [ 1.86755799, -0.97727788],
       [ 0.95008842, -0.15135721],
       [-0.10321885,  0.4105985 ]])

If someone can help me understand this behavior. It does the correct thing in the second case but I find the first case as something that is not straight forward. Why is the first case the way it is?

From the documentation on ndarray with the signature.

ndarray(shape, dtype, buffer, offset, strides, order)

  1. If buffer is None, then only shape, dtype, and order are used.
  2. If buffer is an object exposing the buffer interface, then all keywords are interpreted.

Seems to be that for the first example, even though the buffer is an np.array of integers, ndarray interprets it as a different type. You have to give it the optional argument dtype = int so that the ndarray explicitly know its elements are of type integer.

np.ndarray(shape = (2,1), dtype = int, buffer = np.array([1,2,3,4]))
In [164]: x = np.array([1,2,3,4])
In [165]: x.__array_interface__
Out[165]: 
{'data': (40465184, False),
 'strides': None,
 'descr': [('', '<i8')],
 'typestr': '<i8',
 'shape': (4,),
 'version': 3}

The array created with ndarray has the same data buffer:

In [166]: y = np.ndarray(shape = (2,1),buffer = x)
In [167]: y
Out[167]: 
array([[5.e-324],
       [1.e-323]])
In [168]: y.__array_interface__
Out[168]: 
{'data': (40465184, False),        # same as for x
 'strides': None,
 'descr': [('', '<f8')],
 'typestr': '<f8',
 'shape': (2, 1),
 'version': 3}

and for an array using the int dtype:

In [169]: z = np.ndarray(shape = (2,1),buffer = x, dtype=int)
In [170]: z.__array_interface__
Out[170]: 
{'data': (40465184, False),
 'strides': None,
 'descr': [('', '<i8')],
 'typestr': '<i8',
 'shape': (2, 1),
 'version': 3}

In fact we don't need to pass x as the buffer argument, just its x.data attribute:

In [171]: np.ndarray(shape = (2,1), buffer = x.data, dtype=int)
Out[171]: 
array([[1],
       [2]])

Because of the shared data buffer, modifications to z appear in x as well In [172]: z[:] *= 2 In [173]: z Out[173]: array([[2], [4]]) In [174]: x Out[174]: array([2, 4, 3, 4])

and y :

In [175]: y
Out[175]: 
array([[1.e-323],
       [2.e-323]])

With an offset we can make an array that selects a different part of the data buffer:

In [178]: w=np.ndarray(shape = (2,1), buffer = x.data, dtype=int, offset=8)
In [179]: w
Out[179]: 
array([[4],
       [3]])

But normally we don't use ndarray to do this. Instead we use slicing to get a view , with reshape if needed:

In [181]: x[1:3].reshape(2,1)
Out[181]: 
array([[4],
       [3]])

You can construct the equivalent of rand_mat with randoms.reshape(n,m) or np.random.normal(size=(n,m)) .

ndarray is normally only needed when the buffer comes from so other source, something that isn't already an ndarray which can be reshaped or viewed .

Let's consider your first example:

n = np.ndarray(shape=(2,2), buffer= np.array([1,12,3,4,5,6]), dtype=int, order='F') 
#Note that order is 'F' here and the the order changes from above. 
print(n)

Output: 
[[ 1  3]
 [12  4]]

Observe since buffer is provided, now it looks further into shape, dtype, and order. Let's change the order to 'c' and see what happens.


n = np.ndarray(shape=(2,2), buffer= np.array([1,12,3,4,5,6]), dtype=int, order='C') 
#Note that order is 'C' here.
print(n)

[[ 1 12]
 [ 3  4]]

Now, let's make the buffer to 'None'. Then it simply takes 0's and 1's values and applies the shape and dtype to it.

n = np.ndarray(shape=(2,2), buffer= None, dtype=int, order='F') 
print(n)

Output:
[[1 1]
 [1 0]]

So to conclude, whenever there is buffer takes an array. It has to apply dtype, order and shape to it. When it is None, buffer is simply not applicable. Hope this helps!:)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM