Python 从多个ID列创建子ID

Python 从多个ID列创建子ID,python,python-3.x,pandas,Python,Python 3.x,Pandas,假设我有一个类似于以下的数据: import pandas as pd d = {'col1': [1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3], 'col2': [11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 11, 11, 11, 11], 'col3': ['X', 'X', 'Y', 'Y', 'Z', 'Y', 'Y', 'Z', 'Z', 'X', 'Y', 'X', 'Z', 'Z']} df = pd

假设我有一个类似于以下的数据:

import pandas as pd

d = {'col1': [1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3],
 'col2': [11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 11, 11, 11, 11],
 'col3': ['X', 'X', 'Y', 'Y', 'Z', 'Y', 'Y', 'Z', 'Z', 'X', 'Y', 'X', 'Z', 'Z']}

df = pd.DataFrame(data = d)
print(df)

    col1  col2 col3
0      1    11    X
1      1    11    X
2      1    11    Y
3      1    11    Y
4      1    11    Z
5      2    12    Y
6      2    12    Y
7      2    12    Z
8      2    12    Z
9      2    12    X
10     3    11    Y
11     3    11    X
12     3    11    Z
13     3    11    Z
我想为主Id列['col1',col2',col3']的唯一值创建一个['subID']列,如下所示:

    col1  col2 col3  subID
0      1    11    X      1
1      1    11    X      1
2      1    11    Y      2
3      1    11    Y      2
4      1    11    Z      3
5      2    12    Y      1
6      2    12    Y      1
7      2    12    Z      2
8      2    12    Z      2
9      2    12    X      3
10     3    11    Y      1
11     3    11    X      2
12     3    11    Z      3
13     3    11    Z      3
我可以通过创建临时文件来实现这一点。使用唯一值['col1'、'col2'、'col3']的dataframe,然后在主dataframe中填充新的['subID']列,但是,鉴于我有一个非常大的数据集,循环/iterrows并不理想,因为它需要大量时间来运行。因此,我希望我能找到一种简单/有效的方法:

df['subID'] = df.groupby(['col1', 'col2', 'col3']).cumcount()+1
请注意,上面这行代码并没有真正产生我想要的东西,只是一个完成这项工作的方法示例。你们知道有没有办法做到这一点吗


非常感谢

看起来这样就可以了

groups = df.groupby(['col1','col2'])

df['subID'] = groups['col3'].shift().fillna(df['col3']) != df['col3']

df['subID'] = (groups['subID'].cumsum() +1).astype(int)
产出

    col1  col2 col3  subID
0      1    11    X      1
1      1    11    X      1
2      1    11    Y      2
3      1    11    Y      2
4      1    11    Z      3
5      2    12    Y      1
6      2    12    Y      1
7      2    12    Z      2
8      2    12    Z      2
9      2    12    X      3
10     3    11    Y      1
11     3    11    X      2
12     3    11    Z      3
13     3    11    Z      3

看起来这样就可以了

groups = df.groupby(['col1','col2'])

df['subID'] = groups['col3'].shift().fillna(df['col3']) != df['col3']

df['subID'] = (groups['subID'].cumsum() +1).astype(int)
产出

    col1  col2 col3  subID
0      1    11    X      1
1      1    11    X      1
2      1    11    Y      2
3      1    11    Y      2
4      1    11    Z      3
5      2    12    Y      1
6      2    12    Y      1
7      2    12    Z      2
8      2    12    Z      2
9      2    12    X      3
10     3    11    Y      1
11     3    11    X      2
12     3    11    Z      3
13     3    11    Z      3
我们还可以做到:

df['subID']=(df[['col2','col3']].ne(df[['col2','col3']].shift()).any(1)
             .groupby(df['col1']).cumsum().astype(int))
我们还可以做到:

df['subID']=(df[['col2','col3']].ne(df[['col2','col3']].shift()).any(1)
             .groupby(df['col1']).cumsum().astype(int))
这是一种方式:

df['subID'] = df.assign(dupes=~df.duplicated()).groupby('col1')['dupes'].cumsum().astype(int)
结果:

  col1  col2 col3  subID
0      1    11    X      1
1      1    11    X      1
2      1    11    Y      2
3      1    11    Y      2
4      1    11    Z      3
5      2    12    Y      1
6      2    12    Y      1
7      2    12    Z      2
8      2    12    Z      2
9      2    12    X      3
10     3    11    Y      1
11     3    11    X      2
12     3    11    Z      3
13     3    11    Z      3
这是一种方式:

df['subID'] = df.assign(dupes=~df.duplicated()).groupby('col1')['dupes'].cumsum().astype(int)
结果:

  col1  col2 col3  subID
0      1    11    X      1
1      1    11    X      1
2      1    11    Y      2
3      1    11    Y      2
4      1    11    Z      3
5      2    12    Y      1
6      2    12    Y      1
7      2    12    Z      2
8      2    12    Z      2
9      2    12    X      3
10     3    11    Y      1
11     3    11    X      2
12     3    11    Z      3
13     3    11    Z      3