确定Pandas Series中是否存在一个序列,并返回包含该序列的行。

3
我有一个存储在Pandas系列中的numpy数组,如下所示。
array([0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0,
   0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1,
   0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0,
   0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1,
   1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1,
   0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1,
   1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0,
   1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0,
   1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
   0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1,
   0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0,
   1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0,
   0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0,
   1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0,
   1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1,
   0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1,
   1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1,
   0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1,
   0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0,
   0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1,
   1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0,
   0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
   1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0,
   1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0,
   1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0,
   0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1,
   1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1,
   1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0,
   1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1,
   1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0,
   0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0,
   0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0,
   1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0,
   1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1,
   0, 1, 1, 0, 1, 1, 1])

我想确定这个数组中是否有一定的“1”序列。如果有,我想获取行。例如:这个数组是否有三个连续的“1”?它们在哪里?
我尝试查看Pandas文档,例如isin(),但那些只涉及特定元素,而不是一系列元素。似乎没有任何函数能够满足我的需求。希望有人能帮忙。谢谢。
2个回答

1

Python解决方案

您可以使用itertools.groupby来获得所需的内容:

from itertools import groupby

def oneruns_groupby(arr, n):
    ix = 0
    ixs = []
    for k,g in groupby(arr):
        leng = len(list(g))
        if k and leng == n:
            ixs.append(ix)
        ix += leng
    return ixs

print(oneruns_groupby(arr, 3))

因此,如果您想找到所有长度为3的运行的索引(如果有的话),则可以像这样使用它(我将称呼您的数组为arr,因为我不想复制和粘贴整个巨大的东西):

oneruns_groupby(arr, 3)

输出:

[2, 17, 41, 71, 87, 100, 172, 265, 359, 376, 380, 410, 442, 495, 523, 551, 557, 609, 620, 627, 633, 637, 661, 710, 752]

Numpy解决方案

这是一个函数,它将为您提供给定长度n的每个连续的1值的起始索引:

def oneruns_npcomp(arr, n):
    d = np.diff(np.pad(arr, 1, 'constant'))
    start = (d > 0).nonzero()[0]
    runlen = (d < 0).nonzero()[0] - start

    return start[runlen == n]

测试一下:

测试内容

oneruns_npcomp(arr, 3)

输出:

array([  2,  17,  41,  71,  87, 100, 172, 265, 359, 376, 380, 410, 442,
       495, 523, 551, 557, 609, 620, 627, 633, 637, 661, 710, 752])

快速而简单的解决方案

这里是一个替代的 Numpy 解决方案:

def oneruns_qd(arr, n):
    return ((np.diff(np.pad(arr, 1, 'constant'), n) == 0) & (arr[:-n] == 1)).nonzero()

需要注意的是,快速而简单的方法会找到所有长度为3或更长的连续1

我最终采用了你的Python解决方案。感谢你花时间和精力回答,非常感激。 - Greenhorn

0

这看起来像是一个模板匹配问题。

如果你只关心找到一连串的1,那么你可以使用np.correlate实现一个简单的解决方案。

这个方法可以代替绝对差值之和,因为任何其他数字序列都会导致相关值小于模板长度。

import numpy as np
def find_matching_ones(sequence, length):
  correlated_values = np.correlate(sequence, np.ones((length)), "same")
  return np.where(correlated_values == length)[0] - length//2

def verify_results(sequence, length, indices):
  for idx in indices.tolist():
    reference = sequence[idx:(idx + length)]
    if not np.all(reference == 1):
      print(idx, reference)
      return False
  return True

for n in range(3, 7):
  indices = find_matching_ones(sequence, n)
  if verify_results(sequence, n, indices):
    print("Results matched for length ", n)
  else:
    print("Results did not match for length ", n)

这段代码假设你的数组名为sequence


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接