首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >基于公共ID将熊猫数据分割成等份

基于公共ID将熊猫数据分割成等份
EN

Stack Overflow用户
提问于 2022-11-11 22:33:33
回答 1查看 23关注 0票数 0

在熊猫数据中给出一个ID,我如何创建一个新列,它有一个额外的id,为每个id计算出5。

代码语言:javascript
复制
df = pd.DataFrame([[1, 1],
                    [2, 1],
                    [3, 1],
                    [4, 1],
                    [5, 1],
                    [6, 1],
                    [7, 1],
                    [8, 2],
                    [9, 2],
                    [10, 3],
                    [11, 3],
                   [12, 3],
                   [13, 4],
                   [14, 5],
                   [15, 5],
                   [16, 5],
                   [17, 5],
                   [18, 5],
                   [19, 5],
                   [20, 5]])
df.columns = ['ln_num', 'id']
print(df)
#expected output
expected = pd.DataFrame([[1, 1, 1],
                    [2, 1, 1],
                    [3, 1, 1],
                    [4, 1, 1],
                    [5, 1, 1],
                    [6, 1, 2],
                    [7, 1, 2],
                    [8, 2, 3],
                    [9, 2, 3],
                    [10, 3, 4],
                    [11, 3, 4],
                   [12, 1, 2],
                   [13, 1, 2],
                   [14, 1, 2],
                   [15, 1, 5],
                   [16, 4, 6],
                   [17, 4, 6],
                   [18, 4, 6],
                   [19, 3, 4],
                   [20, 3, 4]])
expected.columns = ['ln_num', 'id', 'grp_id']
print(expected)

因此,例如,如果我有11行ID=1,那么对于这些警报子集,我需要3个不同的唯一Id。1.第1-5行、第2行、第6-10行、第11行

到目前为止,我得到的最接近的是使用带有+1偏移量的groupby,该偏移量为每个id提供了一个新的grp_id,但没有将其限制为5。

代码语言:javascript
复制
df = df.groupby('id').ngroup() + 1
代码语言:javascript
复制
I've also tried by head() and nlargest() but these don't sort ALL lines into batches, only the first or top 5
EN

回答 1

Stack Overflow用户

发布于 2022-11-11 23:09:26

首先,我要得到所有你知道过渡会发生的点:

代码语言:javascript
复制
df[1].diff() \     # Show where column 1 differs from the previous row
     .astype(bool) # Make it a boolean (true/false)

我们可以在dataframe的索引上使用这个选择来获得更改的行的索引:

代码语言:javascript
复制
df.index[df[1].diff().astype(bool)]

这提供了输出:Int64Index([0, 7, 9, 12, 13], dtype='int64'),我们可以检查行0、7、9、12和13是否更改了第1列。

接下来,我们需要将超过5行的任何段分解成更小的批。我们将迭代每一对步骤,并使用range函数对它们进行批处理:

代码语言:javascript
复制
all_steps = []  # Start with an empty list of steps
for i, step in enumerate(steps[:-1]):
    all_steps += list(range(step, steps[i+1], 5))  # Add each step, but also any needed 5-steps

最后,我们可以使用all_steps按索引为数据分配值:

代码语言:javascript
复制
df['group'] = 0
for i, step in enumerate(all_steps[:-1]):
    df.loc[step:all_steps[i+1], 'group'] = i

综上所述,我们还需要使用len(df)几次,以便range函数知道最后一个组的间隔有多长。

代码语言:javascript
复制
steps = df.index[df[1].diff().astype(bool)].tolist() + [len(df)]  # range needs to know how long the last interval is
all_steps = []
for i, step in enumerate(steps[:-1]):
    all_steps += list(range(step, steps[i+1], 5))
all_steps += [len(df)]  # needed for indexing
df['group'] = 0
for i, step in enumerate(all_steps[:-1]):
    df.loc[step:all_steps[i+1], 'group'] = i

我们的最后产出:

代码语言:javascript
复制
    0   1   group
0   1   1   0
1   2   1   0
2   3   1   0
3   4   1   0
4   5   1   0
5   6   1   1
6   7   1   1
7   8   2   2
8   9   2   2
9   10  3   3
10  11  3   3
11  12  3   3
12  13  4   4
13  14  5   5
14  15  5   5
15  16  5   5
16  17  5   5
17  18  5   5
18  19  5   6
19  20  5   6

如果希望组从1开始,请在start=1函数中使用enumerate关键字。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74408804

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档