83 votes

Comment trouver les groupes d'éléments consécutifs dans un tableau NumPy ?

Je dois regrouper les éléments consécutifs d'un tableau NumPy. Considérons l'exemple suivant

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

La sortie devrait être une liste de tuples comme suit

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

Ici, la différence est juste une entre les éléments. Ce serait bien si la différence pouvait aussi être spécifiée comme une limite ou un nombre codé en dur.

1 votes

J'ai trouvé cette réponse en ayant EXACTEMENT le même problème... Le monde est petit ! :o)

0 votes

0 votes

216voto

unutbu Points 222216
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)

donne

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

3 votes

Et pour trouver des séries de cordes identiques : partitions = np.where(a[1:] != a[:-1])[0] + 1 ( np.diff ne fonctionne pas pour les chaînes de caractères)

4 votes

Merci ! Et si nous utilisons np.split(np.r_[:len(data)], np.where(np.diff(data) != stepsize)[0]+1) nous obtenons des listes d'index contiguës, donc si data est une colonne d'une grande table, nous pourrions utiliser ce résultat pour indexer les mêmes groupes de lignes.

0 votes

@unutbu Puis-je savoir ce qui doit être modifié dans cette fonction si je veux sélectionner uniquement les groupes ayant au moins 5 éléments consécutifs ?

22voto

dkamins Points 10565

Voici une petite fonction qui pourrait vous aider :

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

P.S. Ceci est du pur Python. Pour une solution NumPy, voir la réponse de unutbu.

2 votes

P.S. Si vous voulez des tuples au lieu de listes, vous pouvez faire tuple(map(tuple, group_consecutives(a)))

9 votes

Ce n'est pas une solution NumPy !

1 votes

Cela devrait être beaucoup plus lent que la réponse qui utilise np.split .

12voto

Paul Points 13042

(a[1:]-a[:-1])==1 produira un tableau booléen où False indique des ruptures dans les parcours. Vous pouvez également utiliser la fonction intégrée numpy.grad .

0 votes

Je ne comprends pas cette réponse, même si c'est la seule qui semble "fonctionnelle" (comme dans un langage fonctionnel). Ce que vous faites ici est d'appliquer l'opérateur moins à la liste. Je ne vois pas comment cela pourrait fonctionner.

2 votes

@LukeSkywalker Ce n'est pas fonctionnel. a dans ce cas, est un tableau numpy, et non une liste, et l'opérateur moins effectue une soustraction par élément.

5voto

fabrizioM Points 11498

Voici ce que j'ai trouvé jusqu'à présent : je ne suis pas sûr que ce soit 100% correct.

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)

retours :

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

6 votes

Contre exemple : 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)) produit [array([0]), array([47, 48, 49, 50]), array([ 97, 98, 99, 101, 102, 103, 140]), array([141]), array([], dtype=int64)]

1voto

Jože Ws Points 1167

Testé pour les tableaux à une dimension

Obtenir où diff n'en est pas une

diffs = numpy.diff(array) != 1

Obtenez les index des différences, prenez la première dimension et ajoutez un à tous car diff par rapport à l'indice précédent

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

Fractionnement avec les index donnés

groups = numpy.split(array, indexes)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X