【问题标题】:Summarize a column if values in another column are inferior (without for loop)如果另一列中的值较差,则汇总一列(没有 for 循环)
【发布时间】:2020-02-27 07:26:34
【问题描述】:

数据框

我有很多项目的数据框。

项目由代码“类型”和重量标识。

最后一列表示数量。

|-|------|------|---------|
| | type |weight|quantity |
|-|------|------|---------|
|0|100010|   3  |  456    |
|1|100010|   1  |  159    |
|2|100010|   5  |  735    |
|3|100024|   3  |  153    |
|4|100024|   7  |  175    |
|5|100024|   1  |  759    |
|-|------|------|---------|

兼容性规则

如果满足以下条件,给定项目“A”与其他项目“兼容”:

  • 是同一类型
  • 其他物品的重量等于或小于物品“A”的重量

预期的结果

我想为每一行添加一个“兼容数量”列,计算有多少项目是兼容的。

|-|------|------|---------|---------------------|
| | type |weight|quantity | compatible quantity |
|-|------|------|---------|---------------------|
|0|100010|   3  |  456    |        615          | 456 + 159
|1|100010|   1  |  159    |        159          | 159 only (the lightest items)
|2|100010|   5  |  735    |       1350          | 735 + 159 + 456 (the heaviest)   
|3|100024|   3  |  153    |        912          | 153 + 759
|4|100024|   7  |  175    |       1087          | ...
|5|100024|   1  |  759    |        759          | ...
|-|------|------|---------|---------------------|

我想避免使用 For 循环来得到这个结果。 (数据框很大)。

我的代码使用 For 循环

import pandas as pd 

df = pd.DataFrame([[100010, 3, 456],[100010, 1, 159],[100010, 5, 735], [100024, 3, 153], [100024, 7, 175], [100024, 1, 759]],columns = ["type", "weight", "quantity"])

print(df)

for inc in range(df["type"].count()):

    the_type = df["type"].iloc[inc]
    the_weight = df["weight"].iloc[inc]
    the_quantity = df["quantity"].iloc[inc]

    df.at[inc,"quantity_compatible"] = df.loc[(df["type"] == the_type) & (df["weight"] <= the_weight),"quantity"].sum()

print(df)

一些可能的想法

  • “应用”或“转换”有用吗?
  • 可以在 loc 中使用 loc 吗?

【问题讨论】:

    标签: pandas dataframe pandas-groupby


    【解决方案1】:

    首先按weighttype 对值进行排序,然后对cumsum 执行groupby,最后在索引上进行合并:

    df = pd.DataFrame([[100010, 3, 456],[100010, 1, 159],[100010, 5, 735], [100024, 3, 153], [100024, 7, 175], [100024, 1, 759]],columns = ["type", "weight", "quantity"])
    
    new_df = df.merge(df.sort_values(["type","weight"])
                      .groupby("type")["quantity"]
                      .cumsum(),left_index=True, right_index=True)
    
    print (new_df)
    
    #
         type  weight  quantity_x  quantity_y
    0  100010       3         456         615
    1  100010       1         159         159
    2  100010       5         735        1350
    3  100024       3         153         912
    4  100024       7         175        1087
    5  100024       1         759         759
    

    【讨论】:

      【解决方案2】:

      解决方案

      试试这个。

      import pandas as pd
      from io import StringIO
      
      s = """
          type    weight  quantity
      0   100010  3   456
      1   100010  1   159
      2   100010  5   735
      3   100024  3   153
      4   100024  7   175
      5   100024  1   759
      """
      
      def process_dataframe(df, sort_values_by_init_index = True):
          df2 = df.groupby(by=['type','weight']).sum().reset_index()
          df3 = df.groupby(by=['type','weight']).sum().groupby(level=[0], as_index=False)['quantity_compatible'].cumsum().reset_index()
          df2['quantity_compatible'] = df3['quantity_compatible'].tolist()
          if sort_values_by_init_index:
              df2 = df2.sort_values('index')
          #print(df2)
          df2 = df2.reset_index().drop(columns=['index'])
      
          return df2
      
      df = pd.read_csv(StringIO(s), sep='\t')
      df.drop(columns='Unnamed: 0', inplace=True)
      df['quantity_compatible'] = df['quantity'].copy()
      df = df.reset_index()
      
      # custom function
      process_dataframe(df)
      

      输出

      参考文献

      1. Pandas reset index on series to remove multiindex
      2. Pandas groupby cumulative sum
      3. Pandas Groupby and Sum Only One Column
      4. https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.reindex.html#pandas.DataFrame.reindex
      5. https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.groupby.html

      【讨论】:

      • @floupinette 立即尝试。更新了解决方案以匹配预期的输出。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-06
      • 2016-06-10
      相关资源
      最近更新 更多