在给定特定条件的情况下,对嵌套字典列表中的值进行求和

4

我有一个嵌套字典列表,其中包含给定汽车品牌/型号/年份的汽车销售情况。

    cars = 
    [{'id': 2, 'car': 
                    {'car_make':'Acura', 'car_model':'TL', 'car_year':2005},'total_sales':589}, 
    {'id': 30, 'car': 
                    {'car_make':'Acura', 'car_model':'TL', 'car_year':2004}, 'total_sales':167},
    {'id': 31, 'car': 
                    {'car_make':'Acura', 'car_model':'Integra', 'car_year':2008}, 'total_sales':200},
    {'id': 71, 'car':
                    {'car_make':'BMW', 'car_model':'5 Series', 'car_year':2011},'total_sales':824},
    {'id': 72, 'car':
                    {'car_make':'BMW', 'car_model':'5 Series', 'car_year':2001}, 'total_sales':6}]

我想要汇总所有年份的销售总额,并返回一个total_sales字典,包括汽车品牌、型号和销售总额。
    total_sales = {{'car_make': 'Acura', 'car_model': 'TL', 'total_sales': 756},
                  {'car_make': 'Acura', 'car_model': 'Integra', 'total_sales': 200},
                  {'car_make': 'BMW', 'car_model': '5 Series', 'total_sales': 830}}

以下是我的代码,我在嵌套字典中进行迭代并累加销售额。
total_sales = {'car_make':{}}

for car in cars:
    if car['car']['car_make'] in total_sales['car_make'] and car['car']['car_model'] in 
    total_sales['car_model']:
        total_sales['total_sales'] = total_sales['total_sales'] + car['total_sales']
else:
    total_sales['car_make'] = car['car']['car_make']
    total_sales['car_model'] = car['car']['car_model']
    total_sales['total_sales'] = car['total_sales']
    print(total_sales)

然而,我得到了每个车型和车款的累计销售额,而不是最终总销售额。
    {'car_make': 'Acura', 'car_model': 'TL', 'total_sales': 589}
    {'car_make': 'Acura', 'car_model': 'TL', 'total_sales': 756}
    {'car_make': 'Acura', 'car_model': 'Integra', 'total_sales': 200}
    {'car_make': 'BMW', 'car_model': '5 Series', 'total_sales': 824}
    {'car_make': 'BMW', 'car_model': '5 Series', 'total_sales': 830}

我是Python的新手,希望有人能够解释一下我做错了什么。我也查看了其他主题,包括遍历嵌套字典,但似乎都不适用于我的情况。

4个回答

3
您可以使用collections.defaultdict
cars = [{'id': 2, 'car': {'car_make': 'Acura', 'car_model': 'TL', 'car_year': 2005}, 'total_sales': 589}, {'id': 30, 'car': {'car_make': 'Acura', 'car_model': 'TL', 'car_year': 2004}, 'total_sales': 167}, {'id': 31, 'car': {'car_make': 'Acura', 'car_model': 'Integra', 'car_year': 2008}, 'total_sales': 200}, {'id': 71, 'car': {'car_make': 'BMW', 'car_model': '5 Series', 'car_year': 2011}, 'total_sales': 824}, {'id': 72, 'car': {'car_make': 'BMW', 'car_model': '5 Series', 'car_year': 2001}, 'total_sales': 6}]
from collections import defaultdict
d = defaultdict(int)
for i in cars:
   d[(i['car']['car_make'], i['car']['car_model'])] += i['total_sales']

r = [{'car_make':a, 'car_model':b, 'total_sales':c} for (a, b), c in d.items()]

输出:

[{'car_make': 'Acura', 'car_model': 'TL', 'total_sales': 756}, 
 {'car_make': 'Acura', 'car_model': 'Integra', 'total_sales': 200}, 
 {'car_make': 'BMW', 'car_model': '5 Series', 'total_sales': 830}]

0

这是其中一种做法:

models=set([(i['car']['car_make'], i['car']['car_model']) for i in cars])

d={i:0 for i in models}

for i in cars:
    d[(i['car']['car_make'], i['car']['car_model'])]+=i['total_sales']
    
total_sales=[{'car_make':key[0], 'car_model':key[1], 'total_sales':val} for key, val in d.items()]

print(total_sales)

输出

[{'car_make': 'BMW', 'car_model': '5 Series', 'total_sales': 830}, {'car_make': 'Acura', 'car_model': 'TL', 'total_sales': 756}, {'car_make': 'Acura', 'car_model': 'Integra', 'total_sales': 200}]

0

根据您的字典变得多么复杂以及您想在这种类型的统计信息上获得多么细致,您可能需要考虑重构您的结构以使用pandas,这将为数据操作、切片等打开更多的门。然而,对于初学者来说,它确实有一定的学习曲线,所以我会避免通常的建议“嘿,只需使用这个库”。如果您感兴趣,可以阅读一些文档,https://pandas.pydata.org/docs/

直接回答您的问题,您可能需要重新构造您的总销售额字典。您可以使用一个“total_sales_by_make_and_model”字典,然后使用您的cars列表中列出的制造商键作为该字典的键——这使其更易于阅读,但我不确定它是否符合您的整体“业务”逻辑。

我还建议您扩展代码,将关键名称存储在变量中,至少在您看到您的求和出了问题的地方。

cars = [
    {'id': 2, 'car': {'car_make':'Acura', 'car_model':'TL', 'car_year':2005},'total_sales':589},
    {'id': 30, 'car': {'car_make':'Acura', 'car_model':'TL', 'car_year':2004}, 'total_sales':167},
    {'id': 31, 'car': {'car_make':'Acura', 'car_model':'Integra', 'car_year':2008}, 'total_sales':200},
    {'id': 71, 'car': {'car_make':'BMW', 'car_model':'5 Series', 'car_year':2011},'total_sales':824},
    {'id': 72, 'car': {'car_make':'BMW', 'car_model':'5 Series', 'car_year':2001}, 'total_sales':6}
]

total_sales_by_make_and_model = {}

for car in cars:
    car_make = car['car']['car_make']
    car_model = car['car']['car_model']
    total = car['total_sales']

    # if the make key doesn't exist, create it
    if car_make not in total_sales_by_make_and_model:
        total_sales_by_make_and_model[car_make] = {}

    # use get to set the value to "total" if the key doesn't exist
    # otherwise this will increment the current value by "total"
    total_sales_by_make_and_model[car_make][car_model] = total_sales_by_make_and_model[car_make].get(car_model, 0) + total

这个结果将使您能够按照制造商键查询模型,例如:

print(total_sales_by_make_and_model['Acura'])
print(total_sales_by_make_and_model['BMW']['5 Series'])

输出:

{'TL': 756, 'Integra': 200}
830

如果您想获取每个制造商的总销售额,可以使用简单的循环遍历每个键并求和其对应的值:
for make in total_sales_by_make_and_model:
    total = sum(total_sales_by_make_and_model[make].values())
    print(f"Total sales for '{make}': {total}")

输出:

Total sales for 'Acura': 956
Total sales for 'BMW': 830

编辑: 不得不修复一些导致错误的重大错别字:)


0
import operator
import pprint
from itertools import groupby

cars =  [{'id': 2, 'car': 
                    {'car_make':'Acura', 'car_model':'TL', 'car_year':2005},'total_sales':589}, 
    {'id': 30, 'car': 
                    {'car_make':'Acura', 'car_model':'TL', 'car_year':2004}, 'total_sales':167},
    {'id': 31, 'car': 
                    {'car_make':'Acura', 'car_model':'Integra', 'car_year':2008}, 'total_sales':200},
    {'id': 71, 'car':
                    {'car_make':'BMW', 'car_model':'5 Series', 'car_year':2011},'total_sales':824},
    {'id': 72, 'car':
                    {'car_make':'BMW', 'car_model':'5 Series', 'car_year':2001}, 'total_sales':6}]

def map_car(item):
    item['car']['total_sales'] = item['total_sales']
    return item['car']

def get_total(key, item):
    car_make, car_model = key
    total = sum(i['total_sales'] for i in item)

    return {'car_make': car_make, 'car_model':car_model,  'total_sales': total}


mapped_car = list(map(map_car, cars))
key=operator.itemgetter('car_make', 'car_model')
grouped_cars = groupby(sorted(mapped_car, key=key), key=key)
total = [get_total(key, item) for key, item in grouped_cars]
pprint.pprint(total)

结果:

[{'car_make': 'Acura', 'car_model': 'Integra', 'total_sales': 200},
 {'car_make': 'Acura', 'car_model': 'TL', 'total_sales': 756},
 {'car_make': 'BMW', 'car_model': '5 Series', 'total_sales': 830}]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接