按累计和对行进行分组
Group Rows By Cumulative Sum
我正在研究一个问题,通过使用属性的累积总和(在订购后)对行进行分组。但是我是python的新手,不知道怎么处理。请指教。感谢任何帮助。
这是我的输入,这是我制作的熊猫数据框。如您所见,键和组都没有排序。
key group v1 v2
1_A 1 22 4
1_A -1 10 11
1_B 2 15 9
1_B 6 15 2
1_A 2 33 43
1_A 5 50 22
1_A 3 5 122
1_B 1 30 8
1_A 4 1 2
对于数据处理,我需要按组计算v1顺序的累计和,它是针对具有相同键的行。所以我想我应该先订购 table。但我不确定。请建议。如果我需要先订购 table,新的 table 如下所示。基本上,我将具有相同键的行放在一起,并按组对这些行进行排序。
key group v1 v2
1_A -1 10 11
1_A 1 22 4
1_A 2 33 43
1_A 3 5 122
1_A 4 1 2
1_A 5 50 22
1_B 1 30 8
1_B 2 15 9
1_B 6 1 2
这是我想要的输出。主要是我需要按组的顺序对v1进行累加,一旦累加达到一个阈值,这里说30,就停止累加,重新开始下一行。这个过程一直持续到它到达同一组的最后一行。最后,如果最后一个 bin(s) 小于 30,则将它们与较低的 bin(s) 组合,如 1_B 所示,其中第 2 组和第 6 组加起来只有 16(<30) , 所以他们需要与第 1 组合并.
请注意,bin 号可能与我这里的不同。只要它为同一组提供相同的 bin 编号,它就可以工作。例如,您可以将 1、2、3 完全替换为 A、B、C,或替换为 3、2、1,或替换为 A100、B201、M434。
key group v1 v2 bin sum_v1 sum_v2
1_A -1 10 11 1 32 15
1_A 1 22 4 1 32 15
1_A 2 33 43 2 33 43
1_A 3 5 122 3 56 146
1_A 4 1 2 3 56 146
1_A 5 50 22 3 56 146
1_B 1 30 8 1 46 19
1_B 2 15 9 1 46 19
1_B 6 1 2 1 46 19
编辑:
现在我在下面发布了一个完整的解决方案作为答案。享受。
我创建了一个解决方案。我被完整的工作搞得一团糟,但一旦我意识到它可以分解成小的工作,我就能够一次一个地解决这些小任务。过程并不艰难。计划是困难的部分。所以现在我与大家分享我的结果,以防有人有同样的困惑(我已经注意到两个预订星意味着有人感兴趣)。瞧!
import pandas as pd
data = [['1_A',1, 22, 4],['1_A', -1, 10, 11 ],['1_B',2, 15, 9],['1_B',6, 1, 2],['1_A',2, 33, 43 ],['1_A',5, 50, 22 ],['1_A',3, 5 , 122],['1_B',1, 30, 8],['1_A',4, 1 , 2]]
df_1 = pd.DataFrame(data, columns = ['key', 'group', 'v1', 'v2'])
df_2 = df_1.sort(['key', 'group'])
def f1(df, thresh):
myList = []
bin = 0
sum_v1 = 0
sum_v2 = 0
new_df = pd.DataFrame(columns = ['key', 'group', 'v1', 'v2', 'sum_v1', 'sum_v2', 'bin'])
for i, (key, group, v1, v2) in df.iterrows():
if key not in myList:
myList.append(key)
bin = 1
sum_v1 = v1
sum_v2 = v2
else:
if sum_v1 < thresh:
bin += 0
sum_v1 += v1
sum_v2 += v2
else:
bin += 1
sum_v1 = v1
sum_v2 = v2
new_df.loc[i, ['key']] = key
new_df.loc[i, ['group']] = group
new_df.loc[i, ['v1']] = v1
new_df.loc[i, ['v2']] = v2
new_df.loc[i, ['sum_v1']] = sum_v1
new_df.loc[i, ['sum_v2']] = sum_v2
new_df.loc[i, ['bin']] = bin
return new_df
new_df_2 = f1(df_2, 30)
df_3 = new_df_2.groupby(['key', 'bin']).agg({'v1': "sum", 'v2': "sum"}).reset_index()
df_3.rename(columns={'v2': 'a_c_sum_v2', 'v1': 'a_c_sum_v1'}, inplace=True)
def f2(df, thresh):
df_tmp = df.sort(['key', 'bin'], ascending=[1, 0])
myList = []
bin_d = 0
sum_v1_d = 0
sum_v2_d = 0
new_df = pd.DataFrame(columns = ['key', 'bin', 'a_c_sum_v1', 'a_c_sum_v2', 'sum_v1_d', 'sum_v2_d', 'bin_d'])
for i, (key, bin, v1, v2) in df_tmp.iterrows():
if key not in myList:
myList.append(key)
bin_d = 1
sum_v1_d = v1
sum_v2_d = v2
else:
if sum_v1_d < thresh:
bin_d += 0
sum_v1_d += v1
sum_v2_d += v2
else:
bin_d += 1
sum_v1_d = v1
sum_v2_d = v2
new_df.loc[i, ['key']] = key
new_df.loc[i, ['bin']] = bin
new_df.loc[i, ['a_c_sum_v1']] = v1
new_df.loc[i, ['a_c_sum_v2']] = v2
new_df.loc[i, ['sum_v1_d']] = sum_v1_d
new_df.loc[i, ['sum_v2_d']] = sum_v2_d
new_df.loc[i, ['bin_d']] = bin_d
return new_df
new_df_3 = f2(df_3, 30)
df_4 = new_df_3.groupby(['key', 'bin_d']).agg({'a_c_sum_v1': "sum", 'a_c_sum_v2': "sum"}).reset_index()
df_4.rename(columns={'a_c_sum_v2': 'sum_v2', 'a_c_sum_v1': 'sum_v1'}, inplace=True)
m_1 = pd.merge(new_df_3[['key', 'bin', 'bin_d']], df_4[['key', 'bin_d', 'sum_v1', 'sum_v2']], left_on=['key', 'bin_d'], right_on=['key', 'bin_d'], how='left')
m_2 = pd.merge(new_df_2[['key', 'group', 'bin']], m_1[['key', 'bin', 'bin_d', 'sum_v1', 'sum_v2']], left_on=['key', 'bin'], right_on=['key', 'bin'], how='left')
m_3 = pd.merge(df_1[['key', 'group', 'v1', 'v2']], m_2[['key', 'group', 'bin_d', 'sum_v1', 'sum_v2']], left_on=['key', 'group'], right_on=['key', 'group'], how='left')
m_3.rename(columns={'bin_d': 'bin'}, inplace=True)
m_3.sort(['key', 'group'])
我正在研究一个问题,通过使用属性的累积总和(在订购后)对行进行分组。但是我是python的新手,不知道怎么处理。请指教。感谢任何帮助。
这是我的输入,这是我制作的熊猫数据框。如您所见,键和组都没有排序。
key group v1 v2
1_A 1 22 4
1_A -1 10 11
1_B 2 15 9
1_B 6 15 2
1_A 2 33 43
1_A 5 50 22
1_A 3 5 122
1_B 1 30 8
1_A 4 1 2
对于数据处理,我需要按组计算v1顺序的累计和,它是针对具有相同键的行。所以我想我应该先订购 table。但我不确定。请建议。如果我需要先订购 table,新的 table 如下所示。基本上,我将具有相同键的行放在一起,并按组对这些行进行排序。
key group v1 v2
1_A -1 10 11
1_A 1 22 4
1_A 2 33 43
1_A 3 5 122
1_A 4 1 2
1_A 5 50 22
1_B 1 30 8
1_B 2 15 9
1_B 6 1 2
这是我想要的输出。主要是我需要按组的顺序对v1进行累加,一旦累加达到一个阈值,这里说30,就停止累加,重新开始下一行。这个过程一直持续到它到达同一组的最后一行。最后,如果最后一个 bin(s) 小于 30,则将它们与较低的 bin(s) 组合,如 1_B 所示,其中第 2 组和第 6 组加起来只有 16(<30) , 所以他们需要与第 1 组合并.
请注意,bin 号可能与我这里的不同。只要它为同一组提供相同的 bin 编号,它就可以工作。例如,您可以将 1、2、3 完全替换为 A、B、C,或替换为 3、2、1,或替换为 A100、B201、M434。
key group v1 v2 bin sum_v1 sum_v2
1_A -1 10 11 1 32 15
1_A 1 22 4 1 32 15
1_A 2 33 43 2 33 43
1_A 3 5 122 3 56 146
1_A 4 1 2 3 56 146
1_A 5 50 22 3 56 146
1_B 1 30 8 1 46 19
1_B 2 15 9 1 46 19
1_B 6 1 2 1 46 19
编辑: 现在我在下面发布了一个完整的解决方案作为答案。享受。
我创建了一个解决方案。我被完整的工作搞得一团糟,但一旦我意识到它可以分解成小的工作,我就能够一次一个地解决这些小任务。过程并不艰难。计划是困难的部分。所以现在我与大家分享我的结果,以防有人有同样的困惑(我已经注意到两个预订星意味着有人感兴趣)。瞧!
import pandas as pd
data = [['1_A',1, 22, 4],['1_A', -1, 10, 11 ],['1_B',2, 15, 9],['1_B',6, 1, 2],['1_A',2, 33, 43 ],['1_A',5, 50, 22 ],['1_A',3, 5 , 122],['1_B',1, 30, 8],['1_A',4, 1 , 2]]
df_1 = pd.DataFrame(data, columns = ['key', 'group', 'v1', 'v2'])
df_2 = df_1.sort(['key', 'group'])
def f1(df, thresh):
myList = []
bin = 0
sum_v1 = 0
sum_v2 = 0
new_df = pd.DataFrame(columns = ['key', 'group', 'v1', 'v2', 'sum_v1', 'sum_v2', 'bin'])
for i, (key, group, v1, v2) in df.iterrows():
if key not in myList:
myList.append(key)
bin = 1
sum_v1 = v1
sum_v2 = v2
else:
if sum_v1 < thresh:
bin += 0
sum_v1 += v1
sum_v2 += v2
else:
bin += 1
sum_v1 = v1
sum_v2 = v2
new_df.loc[i, ['key']] = key
new_df.loc[i, ['group']] = group
new_df.loc[i, ['v1']] = v1
new_df.loc[i, ['v2']] = v2
new_df.loc[i, ['sum_v1']] = sum_v1
new_df.loc[i, ['sum_v2']] = sum_v2
new_df.loc[i, ['bin']] = bin
return new_df
new_df_2 = f1(df_2, 30)
df_3 = new_df_2.groupby(['key', 'bin']).agg({'v1': "sum", 'v2': "sum"}).reset_index()
df_3.rename(columns={'v2': 'a_c_sum_v2', 'v1': 'a_c_sum_v1'}, inplace=True)
def f2(df, thresh):
df_tmp = df.sort(['key', 'bin'], ascending=[1, 0])
myList = []
bin_d = 0
sum_v1_d = 0
sum_v2_d = 0
new_df = pd.DataFrame(columns = ['key', 'bin', 'a_c_sum_v1', 'a_c_sum_v2', 'sum_v1_d', 'sum_v2_d', 'bin_d'])
for i, (key, bin, v1, v2) in df_tmp.iterrows():
if key not in myList:
myList.append(key)
bin_d = 1
sum_v1_d = v1
sum_v2_d = v2
else:
if sum_v1_d < thresh:
bin_d += 0
sum_v1_d += v1
sum_v2_d += v2
else:
bin_d += 1
sum_v1_d = v1
sum_v2_d = v2
new_df.loc[i, ['key']] = key
new_df.loc[i, ['bin']] = bin
new_df.loc[i, ['a_c_sum_v1']] = v1
new_df.loc[i, ['a_c_sum_v2']] = v2
new_df.loc[i, ['sum_v1_d']] = sum_v1_d
new_df.loc[i, ['sum_v2_d']] = sum_v2_d
new_df.loc[i, ['bin_d']] = bin_d
return new_df
new_df_3 = f2(df_3, 30)
df_4 = new_df_3.groupby(['key', 'bin_d']).agg({'a_c_sum_v1': "sum", 'a_c_sum_v2': "sum"}).reset_index()
df_4.rename(columns={'a_c_sum_v2': 'sum_v2', 'a_c_sum_v1': 'sum_v1'}, inplace=True)
m_1 = pd.merge(new_df_3[['key', 'bin', 'bin_d']], df_4[['key', 'bin_d', 'sum_v1', 'sum_v2']], left_on=['key', 'bin_d'], right_on=['key', 'bin_d'], how='left')
m_2 = pd.merge(new_df_2[['key', 'group', 'bin']], m_1[['key', 'bin', 'bin_d', 'sum_v1', 'sum_v2']], left_on=['key', 'bin'], right_on=['key', 'bin'], how='left')
m_3 = pd.merge(df_1[['key', 'group', 'v1', 'v2']], m_2[['key', 'group', 'bin_d', 'sum_v1', 'sum_v2']], left_on=['key', 'group'], right_on=['key', 'group'], how='left')
m_3.rename(columns={'bin_d': 'bin'}, inplace=True)
m_3.sort(['key', 'group'])