循环 numpy 数组索引
circular numpy array indices
我有一个一维 numpy 数组 a = [1,2,3,4,5,6]
和一个获取两个输入的函数,starting_index
和 ending_index
,以及 returns a[staring_index:ending_index]
.
很明显,当 ending_index
小于 starting_index
时,我 运行 遇到了麻烦。在这种情况下,函数应该从starting_index开始,以循环方式遍历向量a
,即return starting_index
之后的所有元素加上所有元素从索引零到 ending_index
。
例如,如果 starting_index=4
和 ending_index=1
那么输出应该是 output = [5,6,1]
。我可以用 if
条件来实现它,但我想知道是否有任何 Pythonic 和简洁的方法来做到这一点?
不幸的是,您不能通过切片来执行此操作,您需要连接到两个片段:
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 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
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))
这个循环永远。
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)
我有一个一维 numpy 数组 a = [1,2,3,4,5,6]
和一个获取两个输入的函数,starting_index
和 ending_index
,以及 returns a[staring_index:ending_index]
.
很明显,当 ending_index
小于 starting_index
时,我 运行 遇到了麻烦。在这种情况下,函数应该从starting_index开始,以循环方式遍历向量a
,即return starting_index
之后的所有元素加上所有元素从索引零到 ending_index
。
例如,如果 starting_index=4
和 ending_index=1
那么输出应该是 output = [5,6,1]
。我可以用 if
条件来实现它,但我想知道是否有任何 Pythonic 和简洁的方法来做到这一点?
不幸的是,您不能通过切片来执行此操作,您需要连接到两个片段:
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 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
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))
这个循环永远。
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)