Reputation: 587
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?
Upvotes: 0
Views: 1638
Reputation: 1
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!:)
Upvotes: 0
Reputation: 231335
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
.
Upvotes: 1
Reputation: 1903
From the documentation on ndarray
with the signature.
ndarray(shape, dtype, buffer, offset, strides, order)
- If
buffer
is None, then only shape, dtype, and order are used.- 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]))
Upvotes: 1