I have two numpy arrays of different shapes, but with the same length (leading dimension). I want to shuffle each of them, such that corresponding elements continue to correspond -- i.e. shuffle them in unison with respect to their leading indices.
This code works, and illustrates my goals:
def shuffle_in_unison(a, b): assert len(a) == len(b) shuffled_a = numpy.empty(a.shape, dtype=a.dtype) shuffled_b = numpy.empty(b.shape, dtype=b.dtype) permutation = numpy.random.permutation(len(a)) for old_index, new_index in enumerate(permutation): shuffled_a[new_index] = a[old_index] shuffled_b[new_index] = b[old_index] return shuffled_a, shuffled_b
>>> a = numpy.asarray([[1, 1], [2, 2], [3, 3]]) >>> b = numpy.asarray([1, 2, 3]) >>> shuffle_in_unison(a, b) (array([[2, 2], [1, 1], [3, 3]]), array([2, 1, 3]))
However, this feels clunky, inefficient, and slow, and it requires making a copy of the arrays -- I"d rather shuffle them in-place, since they"ll be quite large.
Is there a better way to go about this? Faster execution and lower memory usage are my primary goals, but elegant code would be nice, too.
One other thought I had was this:
def shuffle_in_unison_scary(a, b): rng_state = numpy.random.get_state() numpy.random.shuffle(a) numpy.random.set_state(rng_state) numpy.random.shuffle(b)
This works...but it"s a little scary, as I see little guarantee it"ll continue to work -- it doesn"t look like the sort of thing that"s guaranteed to survive across numpy version, for example.