【问题标题】:How can I find a combination of rows from a table where each column sums a specific number (or range)?如何从表中找到每列总和特定数字(或范围)的行组合?
【发布时间】:2020-06-24 21:35:49
【问题描述】:

我有一个三列的表。假设第一行充满了一些人的名字。第二个和第三个是代表他们花费的价值的数字。我想用这些人的子集构建另一个表,其中这个新表的每一列的总和给出一个特定的值。我如何在 Python 中做到这一点?

示例:这是我的桌子

Col1       Col2   Col3
John       10     100
Andrew     5      50
Martha     8      20
Ana        2      5

假设我想要一个组合,其中第二列总和为 20,第三列总和为 125。结果将是:

Col1       Col2   Col3
John       10     100
Martha     8      20
Ana        2      5

注意:当然,有时可能无法准确得出总和。如果代码接受一些近似值,比如从 0,9X 到 1,1X,是我想要的总和,它会很好。 此外,我不需要获取特定数量的行。它可以是 2、3、...、n 的组合。

【问题讨论】:

  • 如果需要 sum = 10 在这种情况下,John & MarthaAna 的行会是可接受的结果吗?
  • @DOOM 这将取决于第三列的总和。我会传递两个参数,第二列的总和和第三列的总和。
  • 我想我的问题是,如果您的条件导致多种组合会发生什么,这是可以接受的结果吗?
  • @DOOM 我猜有两个合理的选项:1) 两个选项都出现,用户选择一个 2) 任何一个选项都被选中(没关系)
  • @dekio 您可以执行 df['Col2'].cumsum()df['Col3'].cumsum(),然后根据您想要的 cumsum 值对 df 进行切片。但这将按照df中行的顺序选择行(或者可以对df进行排序,但它仍然会以相同的排序顺序获得子集)。我想这不是你所期望的。

标签: python pandas python-2.7 numpy


【解决方案1】:

扩展@stanna 的解决方案:我们可以使用iterables.combinations() 创建要删除的行的所有可能组合,并检查我们的要求是否满足

def checkRequirements(sum1, sum2):
  if sum1 == 20 and sum2 == 125:
    return True
  else:
    return False

# first check if the df as a whole satisfy the requirement
if checkRequirements(df['Col2'].sum(), df['Col3'].sum()) == True:
    print(df)
else:
    # create multiple combination of rows and drop them and check if they satisfy the requriement
    for r in range(1, len(df.index)):
        drop_list = list(combinations(list(df.index), r))
        for idx in drop_list:
            temp_df = df.drop(list(idx))
            if checkRequirements(temp_df['Col2'].sum(), temp_df['Col3'].sum()) == True:
                print(temp_df)
                break

输出:

     Col1  Col2  Col3
0    John    10   100
2  Martha     8    20
3     Ana     2     5

如果要打印所有匹配的子集,请删除末尾的break stmt

【讨论】:

    【解决方案2】:

    这是算法任务 - 找到符合所需条件的值组合。对于不复杂的任务,您可以使用以下脚本逐行删除数据框中的内容,并检查列的总和组合是否符合所需条件。但是,如果您想继续删除行(即,如果在尝试删除一行后未找到匹配项,则删除两行),应详细说明该脚本。在这里应该实现特定的算法(即要删除哪两行以及以什么顺序删除?)并且根据数据的复杂性可能会有非常多的组合。

    
    
    #sample dataframe
    d = {'Column1': ["John", "Andrew", "Martha", "Ana"], 'Column2': [10, 5, 8, 2], 'Column3': [100, 50, 20, 5]}
    df = pd.DataFrame(data=d)
    
    #count the sum of each column
    totalColumn2 = df['Column2'].sum()
    totalColumn3 = df['Column3'].sum()
    
    #function to check if sums of columns match the requrements
    def checkRequirements():
      if totalColumn2 == 20 and totalColumn3 == 125:  #vsums of each column
        return True
      else:
        return False
    
    #iterating through dataframe, removing rows and checking the match
    ind = 0
    for i, row in df.iterrows():
      df1 = df.drop(df.index[ind])
      totalColumn2 = df1['Column2'].sum()
      totalColumn3 = df1['Column3'].sum()
      checkRequirements()
      if checkRequirements() is True:
        print(df1)
        break
      ind = ind+1
    
    

    【讨论】:

    • 这是一次删除一行并计算剩余行的总和吗?这也是按顺序一一删除行。如果您想删除第 2 行和第 4 行以获得结果总和,该怎么办?
    猜你喜欢
    • 1970-01-01
    • 2023-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多