如何根据最大总和分配组?

共5个回答,已解决, 标签: python pandas dataframe

我有一个这样的数据框:

Df = pd。 dataFrame ({'key': list ('aaaabbcccc'),'value': [1 、 5 、 6 、 8 、 2 、 4 、 7 、 5]})

键值
0 一 1
1 个 5
2 a 6
3 a 8
B 2
5 b 4
6 b 7
7 b 7
8 c 1
9 c 1
10 c 1
11 c 1
12 c 5

此外,我有一个变量max_sum = 10

我想根据中的值为每一行 (I) 分配一个组keys and (ii) the max_sum每个组不应该超过它。

我的预期结果是这样的:

键值组
0 一 1
1 个 5 个 1
2 个 6 个 2
3 个 8 个 3
4 b 2 4
B 4 4
6 b 7 5
7 b 7 6
8 c 1 7
9 c 1 7
10 c 1 7
11 c 1 7
12 c 5 7

因此,前两个值a group (1 and 5) sum up to 6 which is less than 10, so they are in the same group. If we now added also 6, max_sum would be exceeded and therefore this value goes into group 2. We cannot add 8 to this group as then again max_sum would be exceeded, therefore we define a group 3. Same then for the values b and c

可以做的

Df ['cumsum'] = df.group by ('key') ['value'].cumsum ()

键值累计
0 一 1
1 个 5 个 6
2 a 6 12
3 个 8 个 20
B 2 2
5 b 4 6
6 b 7 13
7 b 7 20
8 c 1 1
9 c 1 2
10 c 1 3
11 c 1 4
12 c 5 9

但是我不知道如何从这里获取组信息。

第1个答案(采用)

我们可以创建两个掩码,并在此基础上创建一个True / False数组。

  • M1: 所有大于的值max_sum mark as True else False
  • M2: 前一行中的值所在的行keys与当前行不同。

np.where在伪代码中,我们基本上有以下内容:

当 m1或者M2 是真的,返回 True,否则返回 False

现在我们可以翻译了True and False因为它们是布尔值,所以是 1/0:

真实真实

2

这就是我们要找的cumsum在最后一行

代码:

Max_sum = 10

M1 = df.group by (“键”) [“值”].cumsum ().gt (max _ sum) # 大于 max _ sum 的所有值
M2 = df ['key'].ne (df ['key').shift () # 键改变的所有行

Df ['group'] = np.where (m1 | m2,真,假).cumsum ()


键值组
0 一 1
1 个 5 个 1
2 个 6 个 2
3 个 8 个 3
4 b 2 4
B 4 4
6 b 7 5
7 b 7 6
8 c 1 7
9 c 1 7
10 c 1 7
11 c 1 7
12 c 5 7
第2个答案

我们希望根据行的累积和对行进行分区,所以我们使用cumsum, take the modulus with respect to max_sum, then find the difference to find points where the difference is negative (to mark the next group). We also need to do this per key, so the entire operation described above is done inside a GroupBy.apply打电话。

(Df.group by ('key') ['value']
。应用 (lambda x: x.cumsum ().mod (max _ sum).diff ())
.Fillna (-1)
.Lt (0)
。())

0 1
1 1
2 2
3 3
4 4
5 4
6 5
7 6
8 7
9 7
10 7
11 7
12 7
名称: 值,dtype: int64

在下面的评论中,我写道:

@ Cleb 我这边的回答好像是错的 4 、 9 、 2 的输出 应该是 1 、 2 、 3,但是我的代码会分配 1 、 2,因为 cumsum 折扣的价值。

所以,这是我解决这个角落案件的方法。定义分配组的函数:

至少比 “全局” 更好的 grp = {'gr': 0} #
Def func (V):
累计 = 0
【】】 = 1
Grps = []
对于 v.tolist () 中的 V:
累计 = v
如果 cumsum> max_sum:
累计 = v
【】】 = 1
Grps.append (【】】)

返回 pd 系列 (grps)

现在,打电话apply:

Df.group by (“键”) [“值”。应用 (func)。值
# 数组 (【 1 、 2 、 3 、 4 、 5 、 6 、 7 】)
第3个答案

我的逻辑,先把cumsum within each group , then we need get the pervious group's max last group number cumsum分配到下一个组

S = (df.group by ('key') ['value'].cumsum ()/10 1)
S.group by (df ['key').last ().shift ().fillna (0).cumsum ()

出【 24 】:
0 1.0
1.0
2 2.0
3 3.0
4 4.0
5 4.0
6 5.0
7 6.0
8 7.0
9 7.0
10 7.0
11 7.0
7.0
名称: 值,dtype: float64

另一种方式

Pd.因子化 (列表 (zip (df ['key') 、 df.group by ('key') ['value'].cumsum ()//10)
Out [51]: 数组 ([1 、 2 、 3 、 4 、 5 、 6 、 7],dtype = int64)

方法 3 来自 Pir 的数据

S = df.group by ('key') ['value'].rolling (2,min _ periods = 1).sum ().gt (10)
S.loc [s.group by (级别 = 0).head (1).index [1:] = True
美国 cumsum () 1
出【 79 】:
钥匙
0 1
1 1
2 2
3 3
B 4 4
5 4
6 5
7 6
C 8 7
9 7
10 7
11 7
12 7
D 13 8
14 8
15 9
16 10
名称: 值,dtype: int
第4个答案

这不是一个可向量化的问题

据我所知,至少没有

设置

考虑扩展的例子

数据框 ({)
“关键”: [* “aaaabbcccddddd”,
“值”: [* map (int,'1568247711151544922252')]
})

使用发电机

Def gen_groups (tups,max _ sum = 10):
标签 = 0
金额 = {}
对于 key,val in tups:
如果关键不在金额中:
标签 = 1
【 Key 】 = 0 的和
和 [键] = val
如果和 [键]> max_sum:
# 这将重置求和
# 超过最大值的第一件事
和 [键] = val
标签 = 1
产量标签

Df.assign (group = [* gen_groups (zip (df ['key'),df ['value')

输出

键值组
0 一 1
1 个 5 个 1
2 个 6 个 2
3 个 8 个 3
4 b 2 4
B 4 4
6 b 7 5
7 b 7 6
8 c 1 7
9 c 1 7
10 c 1 7
11 c 1 7
12 c 5 7
“Key = = d” 的 13 d 4 8 # 第一组
因为 '4 4 <= 10',14 d 4 8 # 仍然是同一个组
因为 '4 4 9> 10',所以 15 d 9 9 # 新组
因为 '9 2> 10',所以 16 d 2 10 # 新组
因为 '2 2 <= 10',所以 17 d 2 10 # 同组
因为 '2 <= 10',所以 18 d 2 10 # 同组
因为 '2 5> 10',19 d 5 11 # 新组
因为 '5 2 <= 10',所以 20 d 2 11 # 同组
第5个答案

我创造每 groupIDcumsum and use it to group again together with keys to derive the ngroup per keys-cumsum

Max_sum = 10
S = df.group by ('key').值.cumsum ().gt (max _ sum).cumsum ()
[Df ['key'],s].ngroup () 1

出【 461 】:
0 1
1 1
2 2
3 3
4 4
5 4
6 5
7 6
8 7
9 7
10 7
11 7
12 7
Dtype: int64

相关问题

通过随机抽样其他列数据创建新列 如何使用熊猫获得包括每一个组合的计数 如何有效地展开矩阵的值与小块? 如何破坏 Python 对象并释放内存 将具有特殊格式的文本文档转换为熊猫数据框架 用两本字典绘制一只熊猫专栏图 获取比较多列的最大值并返回特定值 基于字典向数据帧添加新列 基于多列和阈值的合并数据帧