【问题标题】:Pandas Group by certain conditionPandas 按特定条件分组
【发布时间】:2022-01-11 17:34:11
【问题描述】:

我的数据框如下所示:

Id name size metric week1 week2 ... until week 20
54 foo 1 A 20 20 ....
54 foo 1 B 0 0 ....
54 foo 1 C 0.39 0.39 ....
54 foo 6 A 40 40 ....
54 foo 6 B 0.50 0.50 ....
54 foo 6 C 0.39 0.39 ....

所以我每个 id 有 6 行,但我只想要 3 行。我想将第 1 行与第 4 行合并,将第 2 行与第 5 行合并,将第 3 行与第 6 行合并。

所以我的目标是得到这样的东西:

Id name size metric week1 week2 ... until week 20
54 foo 6 A 60 60 ....
54 foo 6 B 0.50 0.50 ....
54 foo 6 C 0.39 0.39 ....

-> 对于具有“度量”A 的行,每“周”列求和。
-> 对于具有“metric” B 和 C 的行,检查值是否相等(如果不相等:获取更高的值)

我已经尝试过:

df.groupby(["id","metric"])[df.columns[4:].sum()

但是所有带有“度量”B 和 C 的行也是总和。


对于尺寸:
保持周值(度量 A)较大的大小。 所以大小为 1 的行的值为 20,大小为 6 的行的值为 40 -> 因此保持 6 作为大小。

我知道有一个嵌套循环的解决方案,但我很确定这可以用 pandas 完成。

【问题讨论】:

  • 如果能提供上面df的创建代码就好了
  • @badhushamuhammed 您可以复制表格并使用 pd.read_clipboard()。
  • 在第 3 行的预期输出 week1 week2 是 0.78 对..?

标签: python pandas group-by pandas-groupby


【解决方案1】:
week = ['week{}'.format(i) for i in range(1,23)]
df = pd.read_excel('a.xlsx')
df2 = pd.concat([df.query("metric == 'A'") 
                .groupby(['metric','id','name'],as_index=False)[week].agg('sum'),
           df.query("metric != 'A'")
                .groupby(['metric','id','name'],as_index=False)[week].agg('max')
          ]).reset_index(drop=True)
df3 = pd.concat([df.groupby(['metric','id','name'],as_index=False)['size'].agg('max')]).reset_index(drop=True)
df4 = pd.merge(df2, df3, how='inner', on=['metric'], suffixes=('', '_DROP')).filter(regex='^(?!.*_DROP)')
df = df4.reindex(columns=df.columns)
df
  1. 使用列表理解创建 22 周的列
  2. 将文件读入 pandas 数据框
  3. 按指标、ID 和名称对 df 进行分组,对 metric='A' 的所有周列求和
  4. 按指标、ID 和名称对 df 进行分组,查找 metric='B' 和 'C' 的周列的最大值
  5. 按指标、ID 和名称对 df 进行分组,找到最大尺寸
  6. 合并两个 dfs 而不保留重复项
  7. 使用主 df 的引用重新索引最终 df 的列

输出:

    id  name    size    metric  week1   week2   
0   54  foo       6      A       60.0    60.0   
1   54  foo       6      B       0.50    0.50    
2   54  foo       6      C       0.39    0.39    

【讨论】:

  • 谢谢你的作品。但就我而言,我必须合并所有 3 列:df4 = pd.merge(df2, df3, how='inner', on=['metric','id','name'], suffixes=('', '_DROP')).filter(regex='^(?!.*_DROP)')
【解决方案2】:

您可以使用以下代码生成预期的输出,假设大小 6 即将 bcz 6 是最大值。

data = {"Id": [54, 54, 54, 54, 54, 54],"name": ["foo", "foo","foo","foo","foo","foo"],"size":[1,1,1,6,6,6], 
    "metrics":["A", "B", "C", "A", "B", "C"], "week1": [20, 0, 0.39, 40, 0.50, 0.39],
    "week2": [20, 0, 0.39, 40, 0.50, 0.39]
   }


grup = df.groupby(["metrics"]).agg({"Id":max, "name":max, "size":max, "week1":sum, "week2":sum})

grup["week1"] = df.groupby(["metrics"]).apply(lambda x: x["week1"].max() if x["metrics"].max() in ["C","B"] else x["week1"].sum())
grup["week2"] = df.groupby(["metrics"]).apply(lambda x: x["week2"].max() if x["metrics"].max() in ["C","B"] else x["week2"].sum()) # Use loop for repeating week column
grup.reset_index()

输出

metrics Id name size week1 week2
A 54 foo 6 60.00 60.00
B 54 foo 6 0.50 0.50
C 54 foo 6 0.39 0.39

【讨论】:

  • 谢谢,这有帮助。但是对于第 2,3 行(公制 B 和 C),我不想要总和,我想要更大的值。现在,您还将计算它们的总和。
  • @danielguo 更新了代码。请检查
【解决方案3】:

只是另一种方法:

df_pivot = df.pivot_table(index=['Id','name','metric'], 
               values = ['size', 'week1','week2'], 
               aggfunc={'size':'max', 'week1':('sum','max'),'week2':('sum','max')}).reset_index()

n_weeks = 20 #number of weeks

for n in range(1,n_weeks+1):
    week_sum = 'week'+str(n),'sum'
    week_max = 'week'+str(n),'max'
    def week_final(row):
        metric = row['metric']
   
        if metric[0] == 'A':
            return row[week_sum]
        else:
            return row[week_max]

    df_pivot['res'+str(n)] = df_pivot.apply(week_final, axis=1)
    df_pivot = df_pivot.drop(columns=[week_sum, week_max])

2周的输出:

    Id  name    metric  size    res1    res2
                        max     
0   54  foo     A       6      60.00    60.00
1   54  foo     B       6      0.50     0.50
2   54  foo     C       6      0.39     0.39

【讨论】:

    猜你喜欢
    • 2020-07-25
    • 2022-01-13
    • 2022-01-08
    • 1970-01-01
    • 2018-05-19
    • 1970-01-01
    • 2022-01-18
    • 1970-01-01
    • 2018-11-13
    相关资源
    最近更新 更多