循环 numpy 数组索引

12
我有一个1-D numpy数组 a = [1,2,3,4,5,6],还有一个接受两个输入参数starting_indexending_index的函数,返回a[starting_index:ending_index]
ending_index小于starting_index时,函数将出现问题。在这种情况下,函数应从starting_index开始,并以循环方式遍历向量a,即返回所有位于starting_index之后的元素以及从索引零到ending_index的所有元素。
例如,如果starting_index=4ending_index=1,则输出应为output=[5,6,1]。我可以使用一个if条件实现它,但我想知道是否有一种Pythonic且简洁的方法来实现它?

1
这似乎与编程有关:https://scimusing.wordpress.com/2013/10/25/ring-buffers-in-pythonnumpy/ - endolith
4个回答

11

np.take 有一个 wrap 模式:

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

那不是你想要的。

实际上,模数做的是同样的事情。

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

不过,要是有一个小函数可以把(4,1)转换成[4, 5, 6],或者如果你更喜欢的话,[4, 5, 0]怎么样?

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))

方法foo的返回语句中应该使用模运算符才能使其正常工作,是吗? - Ozgar

6
很遗憾,你不能使用切片来实现此操作,你需要将两个段连接起来:
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]

目前我正在做这样的事情。谢谢。不过,不能与numpy一起使用,你能解释一下切片吗?我猜它可以用于列表? - TNM
Numpy的索引和切片在这里有描述:http://docs.scipy.org/doc/numpy/reference/arrays.indexing.html#basic-slicing-and-indexing,此外还有更一般的讨论:https://docs.python.org/2.3/whatsnew/section-slices.html。 - Bi Rico
我可以确认,对于较小的(<1e6)大小数组,这比使用np.roll更快。例如,对于一个100项的数组:np.roll:23.4 µs ± 968 ns每个循环; np.concatenate:3.22 µs ± 61 ns每个循环。对于一个1e6项的数组,concatenate仍然略快:每个循环2.19毫秒±82微秒与2.29毫秒±92.9微秒。对于较大的数组,像这个例子中使用标量比使用范围或索引数组也更快。 - n4321d

2

您可以使用numpy roll函数与索引相结合的替代方法:

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

这将永无止境地循环。

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)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接