8 votes

pandas comment trouver des valeurs continues dans une série dont les différences sont comprises dans une certaine distance

J'ai un pandas Series qui se compose de int s

a = np.array([1,2,3,5,7,10,13,16,20])
pd.Series(a)

0  1
1  2
2  3
3  5
4  7
5  10
6  13
7  16
8  20

Je souhaite maintenant regrouper les séries en groupes de sorte que, dans chaque groupe, les différences entre deux valeurs voisines soient les suivantes <= distance. Par exemple, si la distance est définie comme suit 1 , nous avons

[1,2,3], [5], [7], [10], [13], [16], [20]

si la distance est de 2 , nous avons

[1,2,3,5,7], [10], [13], [16], [20]

si la distance est de 3 , nous avons

[1,2,3,5,7,10,13,16], [20]

comment le faire en utilisant pandas / numpy ?

9voto

Divakar Points 20144

Voici une approche -

np.split(a,np.flatnonzero(np.diff(a)>d)+1)

Comme fonction de sortie d'une liste de listes -

def splitme(a,d) : 
    return list(map(list,np.split(a,np.flatnonzero(np.diff(a)>d)+1)))

Pour des raisons de performance, je suggère d'utiliser zip pour obtenir les indices de départ et d'arrêt, puis le découpage, ce qui permet d'éviter les erreurs de calcul. np.split qui pourrait s'avérer être le goulot d'étranglement -

def splitme_zip(a,d) : 
    m = np.concatenate(([True],a[1:] > a[:-1] + d,[True]))
    idx = np.flatnonzero(m)
    l = a.tolist()
    return [l[i:j] for i,j in zip(idx[:-1],idx[1:])]

Si vous avez besoin de la sortie sous forme de liste de tableaux, sautez la conversion en liste avec .tolist / map(list,) .

Échantillons -

In [122]: a = np.array([1,2,3,5,7,10,13,16,20])

In [123]: splitme(a,1)
Out[123]: [[1, 2, 3], [5], [7], [10], [13], [16], [20]]

In [124]: splitme(a,2)
Out[124]: [[1, 2, 3, 5, 7], [10], [13], [16], [20]]

In [125]: splitme(a,3)
Out[125]: [[1, 2, 3, 5, 7, 10, 13, 16], [20]]

Test d'exécution -

In [180]: a = np.sort(np.random.randint(1,10000*2,(10000)))

In [181]: s = pd.Series(a)

In [182]: d = 3

In [183]: %timeit pandas_way(s,d) #@cᴏʟᴅsᴘᴇᴇᴅ's soln
10 loops, best of 3: 55.1 ms per loop

In [184]: %timeit np.split(a,np.flatnonzero(np.diff(a)>d)+1)
     ...: %timeit splitme(a,d)
     ...: %timeit splitme_zip(a,d)
1000 loops, best of 3: 1.47 ms per loop
100 loops, best of 3: 2.87 ms per loop
1000 loops, best of 3: 516 µs per loop

In [185]: a
Out[185]: array([    2,     2,     2, ..., 19992, 19996, 19999])

4voto

coldspeed Points 111053

Il s'agit de la pandas en utilisant groupby .

n = 1

s

0     1
1     2
2     3
3     5
4     7
5    10
6    13
7    16
8    20
dtype: int64

m = ~s.diff().fillna(0).le(n)   
v = s.groupby(m.cumsum()).apply(lambda x: x.tolist()).tolist()

v
[[1, 2, 3], [5], [7], [10], [13], [16], [20]]

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