2017-11-08 7 views
7

私が持っているintパンダ

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 

今私はグループにシリーズをクラスタ化することで、それぞれのグループで構成されているpandasSeries 2つの隣接値間の差は、<=距離である。距離は1として定義されている場合、距離は2ある場合、例えば、我々は、我々は、距離が3ある場合、我々は

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

を有する

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

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

有していますどのようにpandas/numpyを使用してこれを行うには? 、私は、スタートを得るためにzipを使用してインデックスを停止してからスライスを示唆している、パフォーマンスのために

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

- リストの機能出力にリストとして

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

-

答えて

7

は、ここに1つのアプローチですしたがって、ボトルネックとなる可能性があるnp.splitを避ける -

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

出力を配列のリストとして必要とする場合は、リスト変換をスキップして.tolist/map(list,)とします。

サンプルの実行 -

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

ランタイムテスト -

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

これはgroupbyを使用して、pandas方法です。

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