Pandas DataFrame – 在多列上使用groupby()函数分组连续数值块。

huangapple go评论105阅读模式
英文:

Pandas dataframe - groupby() blocks of constant value over multiple columns

问题

我可以将这个数据框按照'A'和'B'的常数值来分组,得到你期望的结果:

  1. import pandas as pd
  2. df = pd.DataFrame({
  3. 'A': [1,1,1,1,2,2,2,1,1,3,3,3],
  4. 'B': [0,0,1,1,0,0,0,1,1,0,0,0],
  5. })
  6. df.index.names = ['Index']
  7. # 创建一个分组键,当'A'和'B'的值都发生变化时,分组键加一
  8. group_key = (df['A'].ne(df['A'].shift()) | df['B'].ne(df['B'].shift())).cumsum()
  9. df = df.groupby(group_key).apply(lambda x: x)
  10. df.index.names = ['Block', 'Index']
  11. df

这将产生你期望的结果,将数据框分组成了常数'A'和'B'的块。

英文:

I have the following pandas dataframe:

  1. df = pd.DataFrame({
  2. 'A': [1,1,1,1,2,2,2,1,1,3,3,3],
  3. 'B': [0,0,1,1,0,0,0,1,1,0,0,0],
  4. });
  5. df.index.names = ['Index']
  6. df
  7. A B
  8. Index
  9. 0 1 0
  10. 1 1 0
  11. 2 1 1
  12. 3 1 1
  13. 4 2 0
  14. 5 2 0
  15. 6 2 0
  16. 7 1 1
  17. 8 1 1
  18. 9 3 0
  19. 10 3 0
  20. 11 3 0

I can group this dataframe into blocks of constant 'A' like so:

  1. df = df.groupby(df['A'].diff().ne(0).cumsum()).apply(lambda x: x)
  2. df.index.names = ['Block', 'Index']
  3. df
  4. A B
  5. Block Index
  6. 1 0 1 0
  7. 1 1 0
  8. 2 1 1
  9. 3 1 1
  10. 2 4 2 0
  11. 5 2 0
  12. 6 2 0
  13. 3 7 1 1
  14. 8 1 1
  15. 4 9 3 0
  16. 10 3 0
  17. 11 3 0

How do I instead group this dataframe into blocks of constant 'A' AND constant 'B'? My desired result is:

  1. A B
  2. Block Index
  3. 1 0 1 0
  4. 1 1 0
  5. 2 2 1 1
  6. 3 1 1
  7. 3 4 2 0
  8. 5 2 0
  9. 6 2 0
  10. 4 7 1 1
  11. 8 1 1
  12. 5 9 3 0
  13. 10 3 0
  14. 11 3 0

答案1

得分: 4

使用与 any 相同的逻辑 (df.diff().ne(0).any(axis=1).cumsum()) 作为分组器:

  1. out = df.groupby(df.diff().ne(0).any(axis=1).cumsum(), group_keys=True).apply(lambda x: x)
  2. out.index.names = ['Block', 'Index']

或者:

  1. out = (df.assign(Block=df.diff().ne(0).any(axis=1).cumsum())
  2. .groupby('Block', group_keys=True)
  3. .apply(lambda x: x)
  4. )

输出:

  1. A B
  2. Block Index
  3. 1 0 1 0
  4. 1 1 0
  5. 2 2 1 1
  6. 3 1 1
  7. 3 4 2 0
  8. 5 2 0
  9. 6 2 0
  10. 4 7 1 1
  11. 8 1 1
  12. 5 9 3 0
  13. 10 3 0
  14. 11 3 0
英文:

Use the same logic with any (df.diff().ne(0).any(axis=1).cumsum()) as grouper:

  1. out = df.groupby(df.diff().ne(0).any(axis=1).cumsum(), group_keys=True).apply(lambda x: x)
  2. out.index.names = ['Block', 'Index']

Or:

  1. out = (df.assign(Block=df.diff().ne(0).any(axis=1).cumsum())
  2. .groupby('Block', group_keys=True)
  3. .apply(lambda x: x)
  4. )

Output:

  1. A B
  2. Block Index
  3. 1 0 1 0
  4. 1 1 0
  5. 2 2 1 1
  6. 3 1 1
  7. 3 4 2 0
  8. 5 2 0
  9. 6 2 0
  10. 4 7 1 1
  11. 8 1 1
  12. 5 9 3 0
  13. 10 3 0
  14. 11 3 0

huangapple
  • 本文由 发表于 2023年5月29日 12:39:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/76354710.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定