Reputation: 179
I wish to shuffle between two pairs of numpy arrays, for example given
a = [a1,a2,a3,a4]
a_next = [a2,a3,a4,a5]
b = [b1,b2,b3,b4]
b_next [b2,b3,b4,b5]
I want to shuffle between a and b to get
x = [a1,b2,b3,a4]
x_next = [a2,b3,b4,a5]
y = [b1,a2,a3,b4]
y_next = [b2,a3,a4,b5]
I have managed to get this working for single-dimensional a and b, using:
a = np.array([11,22,33,44])
a_next = np.array([22,33,44,55])
b = np.array([10,20,30,40])
b_next = np.array([20,30,40,50])
choices = [a,b]
choices_next = [a_next,b_next]
alternating_indices = np.random.randint(0, 2, len(a)) # Random 0s or 1s
x = np.choose(alternating_indices, choices)
x_next = np.choose(alternating_indices, choices_next)
y = np.choose(1-alternating_indices, choices)
y_next = np.choose(1-alternating_indices, choices_next)
But my real a and b are actually 3D arrays (so a1, a2, ..., b1, b2 are of shape [width, height]
) which gives the error ValueError: shape mismatch: objects cannot be broadcast to a single shape
. Here's a toy example which gives the same error:
a = np.array([[11,11],[22,22],[33,33],[44,44]])
a_next = np.array([[22,22],[33,33],[44,44],[55,55]])
b = np.array([[10,10],[20,20],[30,30],[40,40]])
b_next = np.array([[20,20],[30,30],[40,40],[50,50]])
So, how can I make this work for arrays with elements of non-trivial shape? The real arrays a, a_next, b and b_next are of equal shape [M, width, height]
.
Thanks in advance!
Upvotes: 1
Views: 197
Reputation: 1653
tl;dr: You can concatenate the arrays that interest you, then shuffle them and slice them:
c = np.concatenate((a, b))
np.random.shuffle(c)
x, y = c[:N], c[N:]
Slightly longer explanation:
From the arrays a
and b
you can create c = np.concatenate((a, b))
that returns the array c = np.array([a1, a2, a3, a4, b1, b2, b3, b4])
, then shuffle it in place using the function np.random.shuffle(c)
. Now c will look something like c = np.array([a3, b1, a2, b2, a4, a1, b3, b4])
. Finally, You can create the arrays x and y by slicing c in two parts. Assuming that the length of the array x you want to create is N < M, the array x can be created doing x = c[:N]
and y by y = c[N:]
.
Upvotes: 0
Reputation:
Use boolean indexing on the first axis. The following
import numpy as np
a = np.array([[11,11],[22,22],[33,33],[44,44]])
b = np.array([[10,10],[20,20],[30,30],[40,40]])
ind = np.random.randint(0, 2, len(a), dtype=np.bool)
a[ind,...], b[ind,...] = b[ind,...], a[ind,...]
print(a)
print(b)
gives
[[10 10]
[22 22]
[33 33]
[40 40]]
[[11 11]
[20 20]
[30 30]
[44 44]]
for, in this case,
ind = [ True False False True]
Upvotes: 2