熊猫如何在一个系列中找到其差异在一定距离内的连续值

Posted

技术标签:

【中文标题】熊猫如何在一个系列中找到其差异在一定距离内的连续值【英文标题】:pandas how to find continuous values in a series whose differences are within a certain distance 【发布时间】:2018-04-21 09:12:11 【问题描述】:

我有一个由ints 组成的pandas Series

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

现在我想将系列聚类到每组中,两个相邻值之间的差异为<= 距离。例如,如果距离定义为1,我们有

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

如果距离是2,我们有

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

如果距离是3,我们有

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

如何使用pandas/numpy 做到这一点?

【问题讨论】:

【参考方案1】:

这是一种方法 -

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

作为输出列表列表的函数 -

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

为了性能,我建议使用zip 来获取开始、停止索引然后切片,从而避免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】:

这是pandas的方式,使用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]]

【讨论】:

被低估的评论!这对我帮助很大!

以上是关于熊猫如何在一个系列中找到其差异在一定距离内的连续值的主要内容,如果未能解决你的问题,请参考以下文章

diff()的熊猫反转

如何追踪熊猫系列的连续高点?

Python:如何从熊猫系列的字典中获取值

熊猫在一个系列中从另一个系列中找到超级字符串

如何在熊猫列中找到连续零的最大计数?

如何在熊猫 DataFrame 中对连续值进行分组