Creating multiple random numpy arrays with different range of values - python

I got a question so I was trying to create a 3D array containing multiple 2D array with different range of values, for example I can do this:
import numpy as np
np.random.seed(1)
arr = np.random.randint(1, 10, size = (2,2)) #Random 2D array with range of values (1, 10)
arr2 = np.random.randint(11, 20, size = (2,2)) #Random 2D array with range of values (11, 20)
...
and then create the 3D array by this
newarr = np.array([arr, arr2, ...])
I try doing this:
import numpy as np
np.random.seed(1)
n = 3
aux = []
for i in range (n):
if i == 0:
aux.append(rng4.randint(1, 10, size = (2, 2)))
elif i == 1:
aux.append(rng4.randint(11, 20, size = (2, 2)))
elif i == 2:
aux.append(rng4.randint(21, 30, size = (2, 2)))
newarr = np.array(aux)
The output is what I want but in either case if I want another range of values I need to "add" manually a new elif to give another range, is there a way I can do this? Thank you!

It is a trivial loop programming exercise:
newarr = np.empty(shape=(2, 2, n))
for i in range (n):
newarr[:,:,i] = rng4.randint(i * 10 + 1, i * 10 + 10,
size = (2, 2))

Related

Numpy: Iterate multiplication of 3D array by 1D array

I have a 3D array (4,3,3) in which I would like to iteratively multiply with a 1D array (t variable) and sum to end up with an array (A) that is a summation of the four 3,3 arrays
I'm unsure on how I should be assigning indexes or how and if I should be using np.ndenumerate
Thanks
import numpy as np
import math
#Enter material constants for calculation of stiffness matrix
E1 = 20
E2 = 1.2
G12 = 0.8
v12=0.25
v21=(v12/E1)*E2
theta = np.array([30,-30,-30,30])
deg = ((math.pi*theta/180))
k = len(theta) #number of layers
t = np.array([0.005,0.005,0.005,0.005])
#Calculation of Q Values
Q11 = 1
Q12 = 2
Q21 = 3
Q22 = 4
Q66 = 5
Qbar = np.zeros((len(theta),3,3),order='F')
#CALCULATING THE VALUES OF THE QBAR MATRIX
for i, x in np.ndenumerate(deg):
m= np.cos(x) #sin of rotated lamina
n= np.sin(x) #cos of rotated lamina
Qbar11=Q11*3
Qbar12=Q22*4
Qbar16=Q16*4
Qbar21 = Qbar12
Qbar22=Q22*1
Qbar26=Q66*2
Qbar66=Q12*3
Qbar[i] = np.array([[Qbar11, Qbar12, Qbar16], [Qbar21, Qbar22, Qbar26], [Qbar16, Qbar26, Qbar66]], order = 'F')
print(Qbar)
A = np.zeros((3,3))
for i in np.nditer(t):
A[i]=Qbar[i]*t[i]
A=sum(A[i])
If I understand correctly, you want to multiply Qbar and t over the first axis, and then summing the result over the first axis (which results in an array of shape (3, 3)).
I created random arrays to make the code minimal:
import numpy as np
Qbar = np.random.randint(2, size=(4, 3, 3))
t = np.arange(4)
A = (Qbar * t[:, None, None]).sum(axis=0)
t[:, None, None] will create two new dimensions so that the shape becomes (4, 1, 1), which can be multiplied to Qbar element-wise. Then we just have to sum over the first axis.
NB: A = np.tensordot(t, Qbar, axes=([0],[0])) also works and can be faster for larger dimensions, but for the dimensions you provided I prefer the first solution.

How to stack numpy array along an axis

I have two numpy arrays, one with shape let's say (10, 5, 200), and another one with the shape (1, 200), how can I stack them so I get as a result an array of dimensions (10, 6, 200)? Basically by stacking it to each 2-d array iterating along the first dimension
a = np.random.random((10, 5, 200))
b = np.zeros((1, 200))
I'v tried with hstack and vstack but I get an error in incorrect number of axis
Let's say:
a = np.random.random((10, 5, 200))
b = np.zeros((1, 200))
Let's look at the volume (number of elements) of each array:
The volume of a is 10*5*200 = 10000.
The volume of an array with (10,6,200) is 10*5*200=1200.
That is you want to create an array that has 2000 more elements.
However, the volume of b is 1*200 = 200.
This means a and b can't be stacked.
As hpaulj mentioned in the comments, one way is to define an numpy array and then fill it:
result = np.empty((a.shape[0], a.shape[1] + b.shape[0], a.shape[2]))
result[:, :a.shape[1], :] = a
result[:, a.shape[1]:, :] = b

ValueError: could not broadcast input array from shape (2,5,2) into shape (5,2)

A n-dimensional array which is initialised as
features=np.empty(shape=(100,5,2), dtype=float)
and I am trying to add 3D array into it as
features[i,:] = features_next
features_next has shape (2,5,2).
However, it shows error,
ValueError: could not broadcast input array from shape (2,5,2) into shape (5,2).
here is the piece of code :
features=np.empty(shape=((historical*2),5,2), dtype=float)
i = 0
while i < 50:
state = self.getDictState(state_index)
asks = state['asks']
bids = state['bids']
features_next = self.getNormalisedFeature(
bids=bids,
asks=asks,
state_index=state_index,
qty=qty,
price=price,
size=size,
normalize=normalize,
levels=levels
)
'''if i == 0:
features = np.array(features_next)
else:
features = np.vstack((features, features_next))'''
features[i,:] = features_next
state_index = (state_index - 1)
return features
Note : I am trying to replace commented 'if condition' with features[i,:] = features_next to make the code execution bit faster.
Its pretty simple, just one point to make features[i,:] has shape (5, 2) and feature_next has shape (2, 5, 2). I want to say that both are compatible shapes. But broadcasting is done on a smaller shape over a larger shape. SO there is error since you are doing revere. Also look up on broadcasting on numpy docs.
Next, this one I think will do
This does not directly solve your problem, but has some ideas about what you can try, like you can reshape your array before going in loop using features.shape = (50, 2, 5, 2).
import numpy as np
features=np.empty(shape=(100,5,2), dtype=float)
features_next = np.random.random((2, 5, 2))
features.shape = ((50, 2, 5, 2))
features[:] = features_next
features.shape = (100, 5, 2)

How to join two 3D numpy arrays so that np.arr(1,m,n) + np.arr(1,m,n) = np.arr(2,m,n)

I have several 3-dimensional numpy arrays that I want to join together to feed them as a training set for my LSTM neural network. They are mostly of shape (1,m,n)
I want to join them so that, for e.g. np.arr(1,50,20) + np.arr(1,50,20) = np.arr(2,50,20) and np.arr(1,50,20) + np.arr(3,50,20) = np.arr(4,50,20)
Which of the stack functions of numpy would suit my problem? Or is there another way to solve it more efficiently?
Use numpy concatenate with the first axis.
import numpy as np
rng = np.random.default_rng()
a = rng.integers(0, 10, (1, 3, 20))
b = rng.integers(-10, -1, (2, 3, 20))
c = np.concatenate((a, b), axis=0)
print(c.shape)
(3, 3, 20)
Use np.vstack
x = np.array([[[2,3,5],[4,5,1]]])
y = np.array([[[1,5,8],[8,0,9]]])
x.shape
(1,2,3)
np.vstack((x,y)).shape
(2,2,3)

How do I iterate over the vectors of all but one axis of a numpy array (tensor)?

Suppose p has shape (4, 3, 2). I want to iterate 12 times over arrays of size (2,)
q = np.empty_like(p)
op_axes = [list(range(len(p.shape) - 1)) + [-1]] * 2
it = np.nditer([p, q],
op_axes=op_axes,
op_flags=[['readonly'], ['writeonly', 'allocate']])
with it:
for this_p, this_q in it:
print(this_p.shape) # I want this to have shape (2,)
this_q[...] = some_function_of(this_p)
What am I doing wrong?
Best I can do:
q = np.empty_like(p)
for i in np.ndindex(p.shape[: -1]):
this_p = p[i]
...
q[i] = solution.x

Categories