识别 Pandas Dataframe 中一组参数的变化并创建一个增量值

Identify a change in a group of parameters within Pandas Dataframe and create an incrementing value

我有一个数据框:

dct = {'A':['abc','abc','abc', 'xyz', 'xyz','abc','abc','abc', 'xyz', 'xyz', 'xyz', 'xyz'],
       'B':['a','a','a','a','a','z','z','z','p','p','p','q'],
       'C':[1,1,1,1,2,5,5,5,9,9,9,9],
   'GROUP':[123,123,123,123,123,456,456,456,767,767,767,767]
    }

df = pd.DataFrame(dct)

    A   B   C   GROUP
0   abc a   1   123
1   abc a   1   123
2   abc a   1   123
3   xyz a   1   123
4   xyz a   2   123
5   abc z   5   456
6   abc z   5   456
7   abc z   5   456
8   xyz p   9   767
9   xyz p   9   767
10  xyz p   9   767
11  xyz q   9   767

我正在尝试创建一个名为 'change' 的新列。

假设我按组分组,并且当 A、B 或 C 列中的任何内容与上一行发生变化时发生变化。 'change' 该组增加 1。如果没有任何变化,则保持相同的值。当一个新组开始时,更改值再次从 1 开始。我可以使用列表和循环来完成此操作,但感觉应该使用 pandas?

示例输出如下所示:

    A   B   C GROUP change
0   abc a   1   123 1
1   abc a   1   123 1
2   abc a   1   123 1
3   xyz a   1   123 2
4   xyz a   2   123 3
5   abc z   5   456 1
6   abc z   5   456 1
7   abc z   5   456 1
8   xyz p   9   767 1
9   xyz p   9   767 1
10  xyz p   9   767 1
11  xyz q   9   767 2

您可以使用双 groupby 和 groupby 编号 (ngroup):

df['change'] = (df.groupby('GROUP', group_keys=False)
                  .apply(lambda d: d.groupby(list(df.columns), sort=False)
                                    .ngroup().add(1))
                )

输出:

      A  B  C  GROUP  change
0   abc  a  1    123       1
1   abc  a  1    123       1
2   abc  a  1    123       1
3   xyz  a  1    123       2
4   xyz  a  2    123       3
5   abc  z  5    456       1
6   abc  z  5    456       1
7   abc  z  5    456       1
8   xyz  p  9    767       1
9   xyz  p  9    767       1
10  xyz  p  9    767       1
11  xyz  q  9    767       2

您可以计算每组 non-duplicated 个值的累计和:

df["change"] = (df.groupby("GROUP", group_keys=False)
                  .apply(lambda gr: (~gr.duplicated()).cumsum()))

获得

      A  B  C  GROUP  change
0   abc  a  1    123       1
1   abc  a  1    123       1
2   abc  a  1    123       1
3   xyz  a  1    123       2
4   xyz  a  2    123       3
5   abc  z  5    456       1
6   abc  z  5    456       1
7   abc  z  5    456       1
8   xyz  p  9    767       1
9   xyz  p  9    767       1
10  xyz  p  9    767       1
11  xyz  q  9    767       2

group_keys=False 不会在 apply 之后产生 MultiIndex 并通过索引对齐简化赋值。


一个示例组及其作用:

>>> gr = df.groupby("GROUP", group_keys=False).get_group(123)
>>> gr
     A  B  C  GROUP  change
0  abc  a  1    123       1
1  abc  a  1    123       1
2  abc  a  1    123       1
3  xyz  a  1    123       2
4  xyz  a  2    123       3

# note the `~` in front; negates the result
# so the "first" seen values are True
>>> ~gr.duplicated()
0     True
1    False
2    False
3     True
4     True
dtype: bool

>>> (~gr.duplicated()).cumsum()
0    1
1    1
2    1
3    2
4    3
dtype: int32

因此,对于重复的标记,错误的标记(即重复项)不会对累积和有贡献,并且会通过它们保持不变。