简体   繁体   English

对字典值求和,使用两个键作为索引:如何实现这一点?

[英]Sum dictionary values, using two keys as index: how to achieve this?

I have the following dictionary:我有以下字典:

res = [{'name': 'mfi', 'percentage': 100.0, 'tax_base': 1000.0, 'tax_amount': 140.0}, 
{'name': 'serv', 'percentage': 100.0, 'tax_base': 1000.0, 'tax_amount': 140.0}, 
{'name': 'inv', 'percentage': 100.0, 'tax_base': 1200.0, 'tax_amount': 168.0}, 
{'name': 'mfi', 'percentage': 50.0, 'tax_base': 1500.0, 'tax_amount': 210.0}, 
{'name': 'none', 'percentage': 0.0, 'tax_base': 1000.0, 'tax_amount': 0.0}, 
{'name': 'none', 'percentage': 0.0, 'tax_base': 900.0, 'tax_amount': 126.0}, 
{'name': 'mfi', 'percentage': 50.0, 'tax_base': 1000.0, 'tax_amount': 140.0}]

From this dictionary, I need to sum 'tax_base' and 'tax_amount' value keys, and use keys 'name' and 'percentage' as index.从这本字典中,我需要对“tax_base”和“tax_amount”值键求和,并使用键“name”和“percentage”作为索引。

As a result, I need:结果,我需要:

res_final = [{'name': 'mfi', 'percentage': 100.0, 'tax_base': 1000.0, 'tax_amount': 140.0},
{'name': 'mfi', 'percentage': 50.0, 'tax_base': 2500.0, 'tax_amount': 350.0},  
{'name': 'serv', 'percentage': 100.0, 'tax_base': 1000.0, 'tax_amount': 140.0}, 
{'name': 'inv', 'percentage': 100.0, 'tax_base': 1200.0, 'tax_amount': 168.0}, 
{'name': 'none', 'percentage': 0.0, 'tax_base': 1900.0, 'tax_amount': 126.0}, 
]

How can I achieve this?我怎样才能做到这一点? Can you provide me a sample please?你能给我一个样品吗?

Taking your original input, res and your preferred output res_final , the following code would work:使用您的原始输入res和您喜欢的 output res_final ,以下代码将起作用:

# Creating a temporary dictionary with the aggregation
temp_result = {}
for each in res:
    key = (each['name'], each['percentage'])
    if key not in temp_result:
        temp_result[key] = dict(tax_base=0, tax_amount=0)

    temp_result[key]['tax_base'] += each['tax_base']
    temp_result[key]['tax_amount'] += each['tax_amount']

# Transforming the temporary dictionary to the correct format
final_result = []
for (name, percentage), taxes in temp_result.items():
    final_result.append(dict(
            name=name,
            percentage=percentage,
            tax_base=taxes['tax_base'],
            tax_amount=taxes['tax_amount']
    ))

for each in final_result:
    print(each)

The result will be:结果将是:

{'name': 'mfi', 'percentage': 100.0, 'tax_base': 1000.0, 'tax_amount': 140.0}
{'name': 'serv', 'percentage': 100.0, 'tax_base': 1000.0, 'tax_amount': 140.0}
{'name': 'inv', 'percentage': 100.0, 'tax_base': 1200.0, 'tax_amount': 168.0}
{'name': 'mfi', 'percentage': 50.0, 'tax_base': 2500.0, 'tax_amount': 350.0}
{'name': 'none', 'percentage': 0.0, 'tax_base': 1900.0, 'tax_amount': 126.0}

Explanation解释

In the first part we create a new dictionary, that has as key the combination of name and percentage as a tuple , and as value a dictionary with the tax_base and tax_amount for that key.在第一部分中,我们创建了一个新字典,它的键是nametax_amount的组合作为tuple ,作为 value 的字典包含该键的tax_basepercentage

Then we check if the key is already in our dictionary and if it isn't we create the key.然后我们检查键是否已经在我们的字典中,如果不是,我们创建键。 The final step is summing the tax_base and tax_amount .最后一步是将tax_basetax_amount

Now we have one dictionary with all the information, but not in the right format.现在我们有了一本包含所有信息的字典,但格式不正确。 The second part takes care of that.第二部分负责这一点。 We split the key again into the name and percentage and merge the data with tax_base and tax_amount to one dict.我们再次将键拆分为namepercentage ,并将数据与tax_basetax_amount合并到一个字典中。


Edit编辑

In case people are wondering how to do it with pd.DataFrame .如果人们想知道如何使用pd.DataFrame来做到这一点。

import pandas as pd

df = pd.DataFrame(res)
res = df.groupby(['name', 'percentage'], as_index=False).sum()
final_result = res.to_dict('records')

for each in final_result:
    print(each)

Will result in the same output, but it is not guaranteed to be in the same order as the input.会导致相同的output,但不保证与输入的顺序相同。

Here's another (very similar) way of doing it but a little bit more concise.这是另一种(非常相似)的方法,但更简洁一些。

Here we first create a list of unique name:percentage pairs and then loop over those unique keys, filtering out entries from the res list that do not match that unique key.在这里,我们首先创建一个唯一name:percentage对的列表,然后遍历这些唯一键,从res列表中过滤掉与该唯一键不匹配的条目。

unique_keys = list(set([f"{d['name']}:{d['percentage']}" for d in res])) # use list(set()) to keep only unique values as keys
output = []

for key in unique_keys:
    name, percentage = key.split(":")
    matching_entries = list(filter(lambda d: d['name'] == name and str(d['percentage']) == percentage, res))
    
    summed = {"name": name, "percentage": float(percentage), "tax_base": 0.0, "tax_amount": 0.0}
    for entry in matching_entries:
        summed["tax_base"] += entry.get("tax_base", 0) # use get in case value is not in dictionary, 0 is default value
        summed["tax_amount"] += entry.get("tax_amount", 0)
    
    output.append(summed)

output.sort(key=lambda d: d['name']) # sorting to organize a bit

Output: Output:

[{'name': 'inv', 'percentage': 100.0, 'tax_base': 1200.0, 'tax_amount': 168.0},
 {'name': 'mfi', 'percentage': 100.0, 'tax_base': 1000.0, 'tax_amount': 140.0},
 {'name': 'mfi', 'percentage': 50.0, 'tax_base': 2500.0, 'tax_amount': 350.0},
 {'name': 'none', 'percentage': 0.0, 'tax_base': 1900.0, 'tax_amount': 126.0},
 {'name': 'serv', 'percentage': 100.0, 'tax_base': 1000.0, 'tax_amount': 140.0}]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM