在Pandas身上找到相同连续元素的块(及其大小)

2024-09-28 17:02:19 发布

您现在位置:Python中文网/ 问答频道 /正文

我需要找到'participant_id'具有相同元素(nan)的块,并且具有一定长度。例如,考虑以下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个连续nan的块感兴趣,那么唯一的选项是participant_id = 27,如果我想要blocks_length = 2,那么答案是{}

我试图遵循类似的solution,但没用。在


Tags: 答案id元素df选项nansummarylength
3条回答
def null_blocks(x, n):
    isnull = np.isnan(x.values)
    nextnot = np.append(~isnull[1:], True)
    csum = isnull.cumsum()
    return np.diff(csum[isnull & nextnot]).max() >= n

def which_ids(k):
    return [n for n, g in df.groupby('participant_id').summary if null_blocks(g, k)]

演示

^{pr2}$

它的工作原理

  • null_blocks
    • 我从一个布尔序列开始,其中的值是NaN和{}
    • 由于boolint的一个子类,我们可以用cumsum来总结它们
    • 然后我们可以通过取isnull的否定并将其移动一个空格来确定块的结束位置。当nextnot和{}都是True时,这是块的结尾。在
    • 然后,我将csum与块末端的位置进行切片,并取其差异。。。这给出了块的大小。在
    • 如果块的最大大小大于阈值,则返回True
  • which_ids
    • groupby对象使用列表理解
    • 只返回groupby组本身的块大小大于阈值的名称。在

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

您可以使用自定义函数和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)

替代方案:

^{pr2}$

相关问题 更多 >