Python 在Pandas中查找相同连续元素的块(及其大小)
我需要找到具有特定长度的相同元素块(NaN)的“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
参与者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块
- 我从一个布尔序列开始,其中值是
withNaN
np.isnan
- 由于
是bool
的一个子类,我们可以用int
cumsum
- 然后,我们可以通过取
的否定并将其移动一个空格来确定块的结束位置。当isnull
和nextnot
均为isnull
时,即为块的结尾True
- 然后我将
与块末端的位置进行切片,并获取差异。。。这将给出块的大小csum
- 如果块的最大大小大于阈值,则返回
True
- 我从一个布尔序列开始,其中值是
哪些ID
- 对
对象使用列表理解groupby
- 仅返回组本身的块大小大于阈值的
名称groupby
- 对