2015-02-08 21 views
6

Mam 1-D numpy tablicy a = [1,2,3,4,5,6] i funkcję, która dostaje dwa wejścia, starting_index i ending_index i zwraca a[staring_index:ending_index].indeksy okrągłych numpy tablicy

Najwyraźniej napotykam problemy, gdy ending_index jest mniejszy niż starting_index. W takim przypadku funkcja powinna rozpoczynać się od początkowego indeksu i przechodzić po nim w kierunku kołowym, tj. Zwracać wszystkie elementy przychodzące po starting_index oraz wszystkie elementy od zera indeksu do ending_index.

Na przykład, jeśli starting_index=4 i ending_index=1, wyjście powinno być output = [5,6,1]. Mogę go wdrożyć z warunkiem if, ale zastanawiałem się, czy istnieje jakiś Pythoniczny i zwięzły sposób na zrobienie tego?

+1

Wydaje związane: https://scimusing.wordpress.com/2013/10/25/ring-buffers-in-pythonnumpy/ – endolith

Odpowiedz

4

np.take ma wrap tryb:

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

To nie jest dokładnie to, czego chcesz.

Właściwie moduł robi to samo

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

Ale jak o małym funkcji, która zamienia (4,1) do [4, 5, 6], lub jeśli wolisz ?

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

Czy nie powinno to być modulo w instrukcji return metody foo, aby to działało? – Ozgar

+0

@Ozgar, dzięki; poprawione. – hpaulj

3

Niestety nie można tego zrobić z krojenia, musisz concatonate na dwa segmenty:

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

aktualnie robię coś takiego. Dzięki. choć nie można go używać z numpy, czy wyjaśniłbyś więcej o krojeniu? Zakładam, że można go używać z listami? – TNM

+0

Indeksowanie i krojenie Numpy'ego jest opisane [tutaj] (http://docs.scipy.org/doc/numpy/reference/arrays.indexing.html#basic-slicing-and-indexing) jest również bardziej ogólna dyskusja o krojeniu [tutaj] (https://docs.python.org/2.3/whatsnew/section-slices.html). –

1

alternatywa, że ​​można użyć jest funkcja numpy roll połączeniu z indeksowania:

# -*- 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

To kręgi na zawsze.

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)