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

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

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

问题

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

import pandas as pd

df = pd.DataFrame({
   'A': [1,1,1,1,2,2,2,1,1,3,3,3],
   'B': [0,0,1,1,0,0,0,1,1,0,0,0],
})
df.index.names = ['Index']

# 创建一个分组键,当'A'和'B'的值都发生变化时,分组键加一
group_key = (df['A'].ne(df['A'].shift()) | df['B'].ne(df['B'].shift())).cumsum()

df = df.groupby(group_key).apply(lambda x: x)
df.index.names = ['Block', 'Index']
df

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

英文:

I have the following pandas dataframe:

df = pd.DataFrame({
   'A': [1,1,1,1,2,2,2,1,1,3,3,3],
   'B': [0,0,1,1,0,0,0,1,1,0,0,0],
});
df.index.names = ['Index']
df
 		A 	B
Index 		
0 		1 	0
1 		1 	0
2 		1 	1
3 		1 	1
4 		2 	0
5 		2 	0
6 		2 	0
7 		1 	1
8 		1 	1
9 		3 	0
10 		3 	0
11 		3 	0

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

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

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

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

答案1

得分: 4

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

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

或者:

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

输出:

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

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

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

Or:

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

Output:

             A  B
Block Index      
1     0      1  0
      1      1  0
2     2      1  1
      3      1  1
3     4      2  0
      5      2  0
      6      2  0
4     7      1  1
      8      1  1
5     9      3  0
      10     3  0
      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:

确定