2011-04-16 11 views
5

Tengo dos matrices 1D, una que tiene algunos valores de interés (a) y otra que proporciona índices en esa matriz (b). Sé que los valores en b siempre aumentan, excepto en un punto (podría estar en cualquier parte) donde el número disminuye ya que se desplaza desde el final hasta el comienzo de la matriz a. El siguiente método parece funcionar, pero creo que debe existir una forma más limpia. ¿Alguien puede sugerir algo mejor? Gracias.Python/Numpy - Wrap Slice Around End of Array

Código:

import numpy as np 
a = np.arange(12) 
b = np.array([5, 9, 2, 4]) 
#I want to generate these: 
#[5,6,7,8,9] 
#[9,10,11,0,1,2] 
#[2,3,4] 
#[4,5] 

a = np.roll(a, -b[0], axis=0) 
# Subtract off b[0] but ensure that all values are positive 
b = (b-b[0]+len(a))%len(a) 
for i, ind in enumerate(b): 
    if i < len(b)-1: 
     print a[b[i]:b[i+1]+1] 
    else: 
     print np.hstack((a[b[i]:len(a)], a[0])) 

Respuesta

3

un poco más corto, pero tal vez todavía puedo hacerlo mejor ...

import numpy as np 

a = np.arange(12) 
b = np.array([5, 9, 2, 4]) 
b = np.append(b, b[0]) 

for i in range(0, len(b)-1): 
    print np.roll(a, len(a)-b[i])[:b[i+1]-b[i]+1] 
+0

de que podría hacer un poco más limpio mediante el uso de: 'np.roll (a, -B [i]) [: b [i + 1] -b [i] 1] ' – JoshAdel

+1

Gracias, esto es más limpio. A pesar de que potencialmente tiene muchas más llamadas a la función de balanceo, lo que supongo podría ralentizar las cosas para matrices muy grandes. ¿Puedes pensar de todos modos para hacer esto sin usar rollo? Reemplazar su línea 'np.roll (...' simplemente con 'a [b [i]: b [i + 1] +1] 'funcionaría para todos los casos, además de aquel en el que se produce el vuelco. –

+0

Podría Anexar toda la matriz a, y volver a calcular los índices para 'a [start: end]', pero creo que eso sería más complicado, no menos. Estoy seguro de que hay una manera de hacer esto con zancadas, solo asilo Tuve tiempo de intentarlo ... – Benjamin

0

No estoy seguro si esto ayuda, pero una manera rápida sin jugar con la memoria de a sería la siguiente:

import numpy as np 

a = np.arange(12) 
b = np.array([5, 9, 2, 4]) 
b = np.append(b, b[0]) 

b2 = b.copy() 

b2[(np.diff(b)<0).nonzero()[0]+1:] += a.size 

print [np.take(a, np.r_[b2[i]:b2[i+1]+1], mode='wrap') for i in range(b.size-1)] 

print [np.roll(a, len(a)-b[i])[:b[i+1]-b[i]+1] for i in range(b.size-1)] 

%timeit [np.take(a, np.r_[b2[i]:b2[i+1]+1], mode='wrap') for i in range(b.size-1)] 
# 10000 loops, best of 3: 28.6 µs per loop 

%timeit [np.roll(a, len(a)-b[i])[:b[i+1]-b[i]+1] for i in range(b.size-1)] 
# 10000 loops, best of 3: 77.7 µs per loop