如何在NumPy数组中查找连续元素的组


70

我必须对NumPy数组中的连续元素进行聚类。考虑以下示例

a = [ 0, 47, 48, 49, 50, 97, 98, 99]

输出应为元组列表,如下所示

[(0), (47, 48, 49, 50), (97, 98, 99)]

在这里,差异只是元素之间的差异。如果差异也可以指定为限制或硬编码数字,那就太好了。


1
我发现这个答案完全一样的问题……小世界!:o)
heltonbiker 2012年


Answers:


21

这是一个可能有用的lil函数:

def group_consecutives(vals, step=1):
    """Return list of consecutive lists of numbers from vals (number list)."""
    run = []
    result = [run]
    expect = None
    for v in vals:
        if (v == expect) or (expect is None):
            run.append(v)
        else:
            run = [v]
            result.append(run)
        expect = v + step
    return result

>>> group_consecutives(a)
[[0], [47, 48, 49, 50], [97, 98, 99]]
>>> group_consecutives(a, step=47)
[[0, 47], [48], [49], [50, 97], [98], [99]]

PS这是纯Python。有关NumPy的解决方案,请参见unutbu的答案。


2
PS如果您想使用元组而不是列表,则可以这样做tuple(map(tuple, group_consecutives(a)))
dkamins 2011年

8
这不是NumPy解决方案!
marscher

1
这应该比使用答案慢得多np.split

195
def consecutive(data, stepsize=1):
    return np.split(data, np.where(np.diff(data) != stepsize)[0]+1)

a = np.array([0, 47, 48, 49, 50, 97, 98, 99])
consecutive(a)

产量

[array([0]), array([47, 48, 49, 50]), array([97, 98, 99])]

3
对于查找相同字符串的partitions = np.where(a[1:] != a[:-1])[0] + 1np.diff
游程

3
谢谢!而且,如果我们使用的是np.split(np.r_[:len(data)], np.where(np.diff(data) != stepsize)[0]+1)连续的索引列表,那么如果data是大表的一列,则可以使用该结果来索引相同的行组。

@unutbu我想仅选择具有至少5个连续元素的组吗,我知道在此功能中需要更改的内容吗?
加布里埃尔·卢卡斯

12

(a[1:]-a[:-1])==1 将产生一个布尔数组,其中False指示运行中断。您还可以使用内置的numpy.grad


我不理解这个答案,尽管它是唯一看起来像“功能”(如功能性语言)的答案。您在这里所做的是将减号运算符应用于列表。我不知道那怎么工作。
卢克·天行者

2
@LukeSkywalker它不起作用。 a在这种情况下,它是一个numpy数组,而不是列表,并且减号运算符进行逐元素减法。
保罗

5

这是我到目前为止提出的:不确定100%正确

import numpy as np
a = np.array([ 0, 47, 48, 49, 50, 97, 98, 99])
print np.split(a, np.cumsum( np.where(a[1:] - a[:-1] > 1) )+1)

返回:

>>>[array([0]), array([47, 48, 49, 50]), array([97, 98, 99])]

4
反例:a = np.array([0,47,48,49,50,97,98,99,101,102,103,140,141])print(np.split(a,np.cumsum(np .where(a [1:]-a [:-1]> 1))+1))产生[array([0]),array([47,48,49,50]),array([97,
98、99、101、102、103、140

0

经过一维数组测试

获取其中DIFF不是一个

diffs = numpy.diff(array) != 1

获取差异索引,获取第一个维度,然后将所有维度相加,因为差异与上一个索引进行比较

indexes = numpy.nonzero(diffs)[0] + 1

用给定索引拆分

groups = numpy.split(array, indexes)

-3

这听起来有点像作业,所以如果您不介意我会建议一种方法

您可以使用遍历列表

for i in range(len(a)):
    print a[i]

您可以测试列表中的下一个元素是否符合某些条件,如下所示

if a[i] == a[i] + 1:
    print "it must be a consecutive run"

您可以将结果分别存储在

results = []

当心-上面隐藏着一个索引超出范围错误,您需要处理


7
当存在更明显的解决方案时,请不要建议对numpy数组使用python迭代器。它达不到使用numpy的目的。(通常。)如果OP不在乎性能,则他们可能会使用python列表。
保罗
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.