【问题标题】:Summing dataframe over combinations of index columns对索引列组合的数据帧求和
【发布时间】:2023-01-13 11:17:08
【问题描述】:

我有一个包含不同部分的数据框(这里只有 2 个部分和速度,但一个电路最多可以有 8 个部分和 6 个测量速度),如下所示:

section speed Data1 Data2
A 10 1.5 2.5
A 20 1.0 2.0
B 10 2.5 3.5
B 20 2.0 3.0

我想总结所有可能电路的数据列

A B Data1 Data2
10 10 4.0 6.0
10 20 3.5 5.5
20 10 3.5 5.5
20 20 3.0 5.0

我该怎么做?我可以进行组合,但不确定如何对它们的数据列求和。

【问题讨论】:

  • 你只有A和B吗?如果更多,您想要所有组合吗?
  • 是的,这就是它会变得困难的地方。您可以有 A-H 部分,每个部分最多有 6 种不同的速度。 2**2 很简单,8**6 不简单 :P
  • 好的,我想我明白了
  • 您是在寻找有关如何将表 A 转换为表 B,然后计算总和的答案,还是从表 B 计算仅计算总和?另外,请确认您是否正在寻找一个答案来考虑所有可能的 8 个部分,然后计算 Data1 和 Data2。

标签: python pandas


【解决方案1】:

使用itertools.product 怎么样,然后按组求和:

from itertools import product

df2 = df.set_index(['section', 'speed']).T

out = (pd.concat({k: df2[list(k)].sum(1)
                  for k in product(*(d for _,d in df2.groupby(axis=1, level=0)))})
         .unstack(level=-1)
      )

输出:

                 Data1  Data2
(A, 10) (B, 10)    4.0    6.0
        (B, 20)    3.5    5.5
(A, 20) (B, 10)    3.5    5.5
        (B, 20)    3.0    5.0

对于提供的确切格式:

df2 = df.set_index(['section', 'speed']).T

sections = df2.columns.get_level_values('section').unique()

out = (pd.concat({tuple(x[1] for x in k):
                  df2[list(k)].sum(1)
                  for k in product(*(d for _,d in df2.groupby(axis=1, level=0)))
                 })
         .unstack(level=-1)
         .rename_axis(sections).reset_index()
      )

输出:

    A   B  Data1  Data2
0  10  10    4.0    6.0
1  10  20    3.5    5.5
2  20  10    3.5    5.5
3  20  20    3.0    5.0

【讨论】:

【解决方案2】:

一种方法:

from itertools import product

groups = [[row for i, row in v.iterrows()] for _, v in df.groupby("section")]
rows = []
for p in product(*groups):
    row = {}
    for e in p:
        d = e.to_dict()
        row[d.pop("section")] = d.pop("speed")
        for k, v in d.items():
            row[k] = row.get(k, 0) + v
    rows.append(row)

res = pd.DataFrame(rows)
print(res)

输出

    A  Data1  Data2   B
0  10    4.0    6.0  10
1  10    3.5    5.5  20
2  20    3.5    5.5  10
3  20    3.0    5.0  20

或者更多蟒蛇式的:

def build_row(prod):
    row = {}
    for e in prod:
        d = e.to_dict()
        row[d.pop("section")] = d.pop("speed")
        for k, v in d.items():
            row[k] = row.get(k, 0) + v
    return row


groups = [[row for i, row in v.iterrows()] for _, v in df.groupby("section")]
res = pd.DataFrame([build_row(p) for p in product(*groups)])
print(res)

请注意,如果您想要准确的输出,只需重新排列列即可。

【讨论】:

    【解决方案3】:

    使用 pandasql 包

    df1.sql("""
        select a,b,tb1.data1+tb2.data1 as Data1,tb1.data2+tb2.data2 as Data2
            from
            (select speed as A,data1,data2 from self where section = 'A') tb1
            join
            (select speed as B,data1,data2 from self where section = 'B') tb2
    """)
    

    出去:

        A   B  Data1  Data2
    0  10  10    4.0    6.0
    1  10  20    3.5    5.5
    2  20  10    3.5    5.5
    3  20  20    3.0    5.0
    

    【讨论】:

      猜你喜欢
      • 2020-12-21
      • 1970-01-01
      • 2018-07-27
      • 1970-01-01
      • 1970-01-01
      • 2014-07-04
      • 1970-01-01
      • 2018-05-18
      • 1970-01-01
      相关资源
      最近更新 更多