Python 在Pandas中查找相同连续元素的块(及其大小)

Python 在Pandas中查找相同连续元素的块(及其大小),python,pandas,Python,Pandas,我需要找到具有特定长度的相同元素块(NaN)的“参与者id”。例如,考虑下面的代码 df>代码>: summary participant_id 13865 3.0 28 13995 NaN 28 14050 3.0 28 14219 5.0 28 14346 NaN 28 14364 4.0

我需要找到具有特定长度的相同元素块(NaN)的“
参与者id
”。例如,考虑下面的代码<代码> df>代码>:

       summary  participant_id
13865      3.0              28
13995      NaN              28
14050      3.0              28
14219      5.0              28
14346      NaN              28
14364      4.0              28
14456      4.0              28
14680      NaN              28
14733      3.0              28
14913      2.0              28
15007      4.0              28
15107      4.0              28
15280      NaN              28
15287      3.0              28
15420      2.0              28
15521      2.0              28
15756      NaN              28
15758      3.0              28
15973      NaN              28
16038      4.0              28
16079      6.0              28
16215      4.0              28
16412      NaN              28
16506      6.0              28
16543      6.0              28
16649      2.0              28
16811      NaN              28
16911      NaN              28
16928      3.0              28
17028      2.0              28
11582      NaN              27
11718      2.0              27
11843      NaN              27
11941      2.0              27
12053      NaN              27
12142      NaN              27
12269      NaN              27
12367      4.0              27
12510      NaN              27
12632      NaN              27
12732      NaN              27
12796      2.0              27
12946      NaN              27
13059      NaN              27
13126      2.0              27
13312      NaN              27
13394      3.0              27
13427      2.0              27
13618      NaN              27
13707      NaN              27
13832      NaN              27
13945      NaN              27
14087      NaN              27
14199      NaN              27
14299      NaN              27
14398      NaN              27
14520      NaN              27
14639      NaN              27
14759      NaN              27
14897      NaN              27
15013      NaN              27
15116      NaN              27
15182      3.0              27
15319      NaN              27
15437      NaN              27
15518      3.0              27
15695      NaN              27
15812      NaN              27
15821      2.0              27
15933      2.0              27
如果我对超过4个连续N的块感兴趣,那么唯一的选择将是
participant\u id=27
,如果我想要
blocks\u length=2
,那么答案将是
participant\u id=[27,28]


我试图遵循类似的方法,但没有成功。

您可以使用自定义函数和
groupby
计算连续的
NaN

N = 4
def f(x):
    a = x.isnull()
    return a.cumsum()-a.cumsum().where(~a).ffill().fillna(0) == N
mask = df.groupby('participant_id', sort=False)['summary'].apply(f)
L = df.loc[mask, 'participant_id'].unique().tolist()
print (L)
替代解决方案:

from functools import reduce

N = 4
nulls = df['summary'].isnull()
df1 = nulls.groupby(df['participant_id']).expanding() \
            .apply(lambda i: reduce(lambda x, y: x+1 if y==1 else 0, i, 0))

L = df1[df1 == N].index.get_level_values(0).unique().tolist()
print (L)

groupby
有助于分别获取每个参与者的数据。然后你可以用任何你想要的方式来计算这个数字。简单明了的一个,不使用熊猫的力量可能是这样的

block_size = 4
for name, gr_data in data.groupby("participant_id"):
    counter = 0
    for value in gr_data["summary"]:
        if value is None:
            counter+=1
            if counter>=block_size:
                print("%s has block of NaN of length >= %d"%(str(name), block_size))
                break
        else:
            counter = 0
演示

which_ids(2)

[27, 28]

which_ids(4)

[27]
它的工作原理

which_ids(2)

[27, 28]

which_ids(4)

[27]
  • null\u块
    • 我从一个布尔序列开始,其中值是
      NaN
      with
      np.isnan
    • 由于
      bool
      int
      的一个子类,我们可以用
      cumsum
    • 然后,我们可以通过取
      isnull
      的否定并将其移动一个空格来确定块的结束位置。当
      nextnot
      isnull
      均为
      True
      时,即为块的结尾
    • 然后我将
      csum
      与块末端的位置进行切片,并获取差异。。。这将给出块的大小
    • 如果块的最大大小大于阈值,则返回
      True
  • 哪些ID
    • groupby
      对象使用列表理解
    • 仅返回组本身的块大小大于阈值的
      groupby
      名称

感谢您的解决方案,但它会失败并出现错误。我相信我可以调整你的解决方案,但耶兹雷尔做得很好。再次感谢!