Tengo dos matrices numpy de diferentes formas, pero con la misma longitud (dimensión principal). Quiero barajar cada uno de ellos, de modo que los elementos correspondientes sigan correspondiendo, es decir, barajarlos al unísono con respecto a sus índices principales.
Este código funciona e ilustra mis objetivos:
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
Por ejemplo:
>>> 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]))
Sin embargo, esto se siente torpe, ineficiente y lento, y requiere hacer una copia de los arreglos; prefiero mezclarlos en su lugar, ya que serán bastante grandes.
¿Hay una mejor manera de hacerlo? Mis objetivos principales son una ejecución más rápida y un menor uso de memoria, pero un código elegante también sería bueno.
Otro pensamiento que tuve fue este:
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)
Esto funciona ... pero da un poco de miedo, ya que veo pocas garantías de que continuará funcionando; no parece el tipo de cosa que se garantiza que sobrevivirá a través de la versión numpy, por ejemplo.