Python-切片数组,直到满足特定条件
我需要从给定的索引中切片一个数组,直到满足某个条件Python-切片数组,直到满足特定条件,python,arrays,numpy,slice,Python,Arrays,Numpy,Slice,我需要从给定的索引中切片一个数组,直到满足某个条件 >>> a = numpy.zeros((10), dtype='|S1') >>> a[2] = 'A' >>> a[4] = 'X' >>> a[8] = 'B' >>> a array(['', '', 'A', '', 'X', '', '', '', 'B', ''], dtype='|S1') 例如,对于上面的数组,我想要一个从给定索引到两个
>>> a = numpy.zeros((10), dtype='|S1')
>>> a[2] = 'A'
>>> a[4] = 'X'
>>> a[8] = 'B'
>>> a
array(['', '', 'A', '', 'X', '', '', '', 'B', ''], dtype='|S1')
例如,对于上面的数组,我想要一个从给定索引到两个方向上的第一个非零值的子集。例如,对于索引值2、4、8,结果将是:
['', '', A, ''] # 2
['', X, '', '', ''] # 4
['', '', '', B, ''] # 8
关于使用numpy API实现这一点的最简单方法有什么建议吗?学习python和numpy,如有任何帮助,将不胜感激。谢谢 首先想到的是两个循环。类似这样的方法会奏效:
'''Given an array and an index...'''
def getNoneSlice(a, i):
# get the first non-None index before i
start = 0
for j in xrange(i - 1, -1, -1):
if a[j] is not None: # or whatever condition
start = j + 1
break
# get the first non-None index after i
end = len(a) - 1
for j in xrange(i + 1, len(a)):
if a[j] is not None: # or whatever condition
end = j - 1
break
# return the slice
return a[start:end + 1]
如果您这样设置问题:
import numpy
a = numpy.zeros((10), dtype=str)
a[2] = 'A'
a[4] = 'X'
a[8] = 'B'
您可以轻松获得非空字符串的索引,如下所示:
i = numpy.where(a!='')[0] # array([2, 4, 8])
或者,numpy.argwhere(…)
也可以正常工作
然后,您可以使用此阵列进行切片:
out2 = a[:i[1]] # 2 ['' '' 'A' '']
out4 = a[i[0]+1:i[2]] # 4 ['' 'X' '' '' '']
等等。这是一项针对屏蔽阵列的工作,numpy.ma有许多用于处理子集的函数
a = np.zeros((10), dtype=str)
a[2] = 'A'
a[4] = 'X'
a[8] = 'B'
让我们屏蔽非空元素:
am=np.ma.masked_where(a!='', a)
np.ma.notmasked\u continuous
遍历数组(非常有效),并查找数组未被屏蔽的所有连续元素片:
slices = np.ma.notmasked_contiguous(am)
[slice(0, 1, None), slice(3, 3, None), slice(5, 7, None), slice(9, 9, None)]
例如,数组在元素5和7之间连续为空。
现在,您只需加入感兴趣的切片,首先获得每个切片的起始索引:
slices_start = np.array([s.start for s in slices])
然后获得要查找的索引的位置:
slices_start.searchsorted(4) #4
Out: 2
所以您需要第1和第2部分:
a[切片[1]。开始:切片[2]。停止+1]
数组(['',X','','',''),
数据类型=“| S1”)
或者让我们试试8:
i = slices_start.searchsorted(8)
a[slices[i-1].start:slices[i].stop+1]
Out: array(['', '', '', 'B', ''],
dtype='|S1')
If可能应该在ipython中使用它来更好地理解它。注意,这可以在纯python中使用itertools和functools干净地完成
import functools, itertools
arr = ['', '', 'A', '', 'X', '', '', '', 'B', '']
f = functools.partial(itertools.takewhile, lambda x: not x)
def g(a, i):
return itertools.chain(f(reversed(a[:i])), [a[i]], f(a[i+1:]))
我们将f定义为子迭代器,通过查找直到元素的计算结果为true,将g定义为将其应用于索引前列表的反向区域和索引后列表的组合
这将返回可以转换为包含结果的列表的生成器
>>> list(g(arr, 2))
['', '', 'A', '']
>>> list(g(arr, 4))
['', 'X', '', '', '']
>>> list(g(arr, 8))
['', '', '', 'B', '']
你能澄清你的问题吗?“直到两个方向上的第一个非None值”是什么意思?在尝试确定非None数组项的索引时,使用
对象
数组(不是很常见,内存效率也不是很高)这一事实提出了一个特殊的问题。能说服您使用固定字节的数据类型吗?如果您致力于对象
dtype,那么当typecast为bool
时,任何“非None”都将计算为true
?这两种方法中的任何一种都会大大简化事情。@Paul我正在使用对象数组来存储单个字符串。基本上,我只需要一个char
数组。有没有一种替代的dtype
我可以使用dtype
?@armandino:usedtype='|S1'
(或者干脆dtype=str
)来处理单个字符串。@armandino:另外,如果你还没有注意到的话,在使用dtype='S1'
时,你可能需要numpy.zero(…)而不是numpy.empty(…)。该解决方案非常有效(+1)。不过,我希望有一个numpy
方法来解决类似的问题。我投了反对票,因为这对于大型稀疏阵列来说效率很低。使用其他答案的简单方法。是的,Steabert,同意。。。至少我学到了一些新的东西,我担心它不起作用。我得到了[''A'][''X'][''B']
当我回答这个问题时,它没有空字符串,它没有空字符串。如果非零方法与“None”一起工作,则表示感谢Paul。看起来像是我要找的,很有趣,安德里亚。谢谢你的解释。非常感谢!
>>> list(g(arr, 2))
['', '', 'A', '']
>>> list(g(arr, 4))
['', 'X', '', '', '']
>>> list(g(arr, 8))
['', '', '', 'B', '']