Python 找出数据帧中事件的中间出现的“0”和第一出现的“1”

Python 找出数据帧中事件的中间出现的“0”和第一出现的“1”,python,pandas,dataframe,Python,Pandas,Dataframe,您好,我有一个pandas数据框,它有事件列和其他列。我想在id上执行group by,在group by上我想从所有连续0中提取2条记录我想找出连续5 0的模式可能更多,但它也必须始终后跟1,然后确定一组记录,即连续5 0的一个d后跟下一个1,然后从这5组0的记录中获取0的中间行,找出0之后的第一个1并获取该行。但对于0,我应该重复5次或更多次,然后从最后5个记录中获取中间行 简言之: 我想要0和1的集合,条件是只取1,对于上面找到的继续5 0或更多,如果此模式是多次的,则取一个模式为每个id

您好,我有一个pandas数据框,它有事件列和其他列。我想在id上执行group by,在group by上我想从所有连续0中提取2条记录我想找出连续5 0的模式可能更多,但它也必须始终后跟1,然后确定一组记录,即连续5 0的一个d后跟下一个1,然后从这5组0的记录中获取0的中间行,找出0之后的第一个1并获取该行。但对于0,我应该重复5次或更多次,然后从最后5个记录中获取中间行

简言之: 我想要0和1的集合,条件是只取1,对于上面找到的继续5 0或更多,如果此模式是多次的,则取一个模式为每个id获取两条记录,每个id具有0和1

例如

 import pandas as pd
 data={'id':[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
        2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2],
  'name': ['a','b','c','d','e','f','g','h','i','j','k','l','m','n'
          ,'o','p','q','r','s','t','a1','b1','c1','d1','e1','f1','g1','h1','i1','j1','k1','l1','m1','n1'
          ,'o1','p1','q1','r1','s1','t1','aa','bb','cc','dd','ee','ff',
          'gg','hh','ii','jj','kk','ll','mm','nn'
          ,'oo','pp','qq','rr','ss','tt','aa1','bb1','cc1','dd1','ee1','ff1',
          'gg1','hh1','ii1','jj1','kk1','ll1','mm1','nn1'
          ,'oo1','pp1','qq1','rr1','ss1','tt1'],
  'value':[0,0,1,0,0,0,0,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
           0,0,0,0,0,0,0,1,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0]}
 df=pd.DataFrame.from_dict(data)
作为输出,我希望每个id获得2条记录,一条为0,一条为1。0行应该是5个或更多连续0的中间记录

预期产出为:

    id  name    value

 16 1   q       0
 19 1   t       1

64  2   ee1     0
67  2   hh1     1

您可以使用透视表并为不同的值应用掩码来完成此操作。首先,我们应该按id、值对进行分组:

然后选择每个值的零==0和id对,并保留中间值:

mask_zeros = ((df_grouped['value']==0)*
              (df_grouped['name'].apply(len)>=5))
df_zeros = mask_zeros*df_grouped['name'].apply(
           lambda x: x[int(np.ceil(.5*len(x)))] 
                      if len(x)%2==1 
                      else x[int(.5*len(x))])
print(df_zeros)

0    f
1     
2    o
3     
并选择每个值==1和id对的第一个名称:

然后,通过指定以下项仅保留选定的名称:

 df_grouped['name'] = df_ones + df_zeros

 df_grouped = df_grouped.merge(df.reset_index(),
                               on=['name','value','id']
                               ).set_index('index')
 print(df_grouped)

       id  value name
index                
5       1      0    f
2       1      1    c
14      2      0    o
10      2      1    k

我打破了台阶

df['New']=df.value.diff().fillna(0).ne(0).cumsum()
df1=df.loc[df.value.eq(0)]
s1=df1.groupby(['id','New']).filter(lambda x : len(x)>=5 ).groupby('id').apply(lambda x : x.iloc[len(x)//2-1:len(x)//2+1] if len(x)%2==0 else x.iloc[[(len(x)+1)//2],:] ).reset_index(level=0,drop=True)
s2=df1.groupby(['id','New']).filter(lambda x : len(x)>=5 )
pd.concat([df.loc[s2.drop_duplicates(['id'],keep='last').index+1],s1]).sort_index()
Out[1995]: 
    id name  value  New
5    1    f      0    2
6    1    g      0    2
9    1    j      1    3
14   2    o      0    4
16   2    q      1    5

谢谢Mabel,但我只需要4条记录作为输出,就这样。我不明白你的答案对我有什么帮助?好的,我知道了。如果有奇数个0,两个相邻的中间元素和第一个1,你想返回中间元素吗?是的,只需要一个小的更改,我不需要两个相邻的0,只有一个就可以了。实际上,我似乎尚未涵盖我的数据集的所有场景。我不是在寻找索引+1的下一个立即数,但我在寻找0之后出现的1,现在1可以是下一个立即数索引,也可以是多个0之后。因此,我需要我们确定的0之后的任何第一个1?对此有何建议?另一个问题是,在我的数据集中它的发生就像我得到了相当多的0的数量,比如20-25个计数,然后得到1,那么是否有可能得到最后5个连续的0,并将中间部分作为0的一个记录,并将下一个1作为1的另一个记录?我的数据是每个月的事件,所以在目前的情况下,我从2014年得到0,从2017年得到1,这是什么时间窗很大。我希望我有点清楚?如果你的问题解决了,请用绿色勾号标出正确答案,这样线程就关闭了。
 df_grouped['name'] = df_ones + df_zeros

 df_grouped = df_grouped.merge(df.reset_index(),
                               on=['name','value','id']
                               ).set_index('index')
 print(df_grouped)

       id  value name
index                
5       1      0    f
2       1      1    c
14      2      0    o
10      2      1    k
df['New']=df.value.diff().fillna(0).ne(0).cumsum()
df1=df.loc[df.value.eq(0)]
s1=df1.groupby(['id','New']).filter(lambda x : len(x)>=5 ).groupby('id').apply(lambda x : x.iloc[len(x)//2-1:len(x)//2+1] if len(x)%2==0 else x.iloc[[(len(x)+1)//2],:] ).reset_index(level=0,drop=True)
s2=df1.groupby(['id','New']).filter(lambda x : len(x)>=5 )
pd.concat([df.loc[s2.drop_duplicates(['id'],keep='last').index+1],s1]).sort_index()
Out[1995]: 
    id name  value  New
5    1    f      0    2
6    1    g      0    2
9    1    j      1    3
14   2    o      0    4
16   2    q      1    5