2015-02-08 2 views
6

Possiedo un array numpy 1-D a = [1,2,3,4,5,6] e una funzione che riceve due input, starting_index e ending_index e restituisce a[staring_index:ending_index].indici circolari numpy array

Chiaramente mi imbatto in problemi quando ending_index è minore di starting_index. In questo caso, la funzione dovrebbe iniziare da starting_index e attraversare il vettore a in modo circolare, cioè restituire tutti gli elementi che arrivano dopo lo starting_index più tutti gli elementi dall'indice zero a ending_index.

Ad esempio, se starting_index=4 e ending_index=1, l'uscita deve essere output = [5,6,1]. Posso implementarlo con una condizione if ma mi stavo chiedendo se c'è qualche modo Pythonico e conciso per farlo?

+1

questo sembra Correlati: https://scimusing.wordpress.com/2013/10/25/ring-buffers-in-pythonnumpy/ – endolith

risposta

4

np.take ha una modalità wrap:

In [171]: np.take(np.arange(1,7),range(4,7),mode='wrap') 
Out[171]: array([5, 6, 1]) 

Non è proprio quello che vuoi.

In realtà, il modulo fa la stessa cosa

In [177]: a[np.array([4,5,6])%6] 
Out[177]: array([5, 6, 1]) 

Ma come circa una piccola funzione che si trasforma in (4,1)[4, 5, 6], o se si preferisce ?

def foo(a, start, stop): 
    # fn to convert your start stop to a wrapped range 
    if stop<=start: 
     stop += len(a) 
    return np.arange(start, stop)%len(a) 

a[foo(a,4,1)] # or 
np.take(a,foo(a,4,1)) 
+0

Non dovrebbe essere modulo nella dichiarazione di ritorno del metodo foo perché funzioni? – Ozgar

+0

@Ozgar, grazie; corretto. – hpaulj

3

Purtroppo non si può fare questo con affettare, avrete bisogno di concatonate a due segmenti:

import numpy as np 

a = [1, 2, 3, 4, 5, 6] 
if starting_index > ending_index: 
    part1 = a[start_index:] 
    part2 = a[:end_index] 
    result = np.concatenate([part1, part2]) 
else: 
    result = a[start_index:end_index] 
+0

attualmente sto facendo qualcosa di simile. Grazie. comunque, non può essere usato con numpy, spiegherebbe di più sull'affettatura? Presumo che possa essere usato con le liste? – TNM

+0

L'indicizzazione e l'affettamento di Numpy sono descritti [qui] (http://docs.scipy.org/doc/numpy/reference/arrays.indexing.html#basic-slicing-and-indexing) c'è anche una discussione più generale sull'affettatura [qui] (https://docs.python.org/2.3/whatsnew/section-slices.html). –

1

Un'alternativa che è possibile utilizzare sia la funzione NumPy roll combinata con l'indicizzazione:

# -*- coding: utf-8 -*- 
import numpy as np 

def circular_array(starting_index, ending_index): 

    idx = np.arange(1,7) 
    idx = np.roll(idx, -starting_index)[:(len(idx)-starting_index+ending_index)%len(idx)] 

    return idx 


a = circular_array(4, 1) 
print a 
0

Questo cerchi per sempre.

def circular_indices(lb, ub, thresh): 
    indices = [] 
    while True: 
     stop = min(ub, thresh) 
     ix = np.arange(lb, stop) 
     indices.append(ix) 
     if stop != ub: 
      diff = ub - stop 
      lb = 0 
      ub = diff 
     else: 
      break 

    return np.concatenate(indices)