Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python sum dict values based on keys

How to sum values from dict where values are string. I mean how to sum values where multiply key is same in dictionary.

dict

values = [
    {
        "rashod": 0,
        "prihod": 230.0,
        "prod_name": "r",
        "prod_hola": "t"
    },
    {
        "rashod": 0,
        "prihod": 230.0,
        "prod_name": "r",
        "prod_hola": "t"
    },
    {
        "rashod": 0.0,
        "prihod": 0,
        "prod_name": "c",
        "prod_hola": "f"
    },
    {
        "rashod": 0,
        "prihod": 100.0,
        "prod_name": "c",
        "prod_hola": "f"
    },
    {
        "rashod": 0.0,
        "prihod": 0,
        "prod_name": "a",
        "prod_hola": "b"
    },
    {
        "rashod": 0,
        "prihod": 1500.0,
        "prod_name": "a",
        "prod_hola": "b"
    }]

python

dictf = reduce(lambda x, y: dict((k, v + y[k]) for k, v in x.iteritems()), values)
print dictf

But this sum all values in dict, and output is like:

{'rashod': 1930.0, 'prihod': -17020.0, 'prod_name': 'abcfrtabcfrtabcfrt'}

What I want is output like this:

[{'rashod': 1930.0, 'prihod': -17020.0, 'prod_name': 'a','prod_hola':'b},
{'rashod': 1930.0, 'prihod': -17020.0, 'prod_name': 'c','prod_hola':'f},
{'rashod': 1930.0, 'prihod': -17020.0, 'prod_name': 'r','prod_hola':'t},]
like image 525
Marin Avatar asked May 27 '26 09:05

Marin


2 Answers

Specific solution, with no attempt at cleverness:

def regroup(values):
    groups = dict()
    for d in values:
        key = (d["prod_name"], d["prod_hola"])
        if key in groups:
            group = groups[key]
            group["rashod"] += d["rashod"]
            group["prihod"] += d["prihod"]
        else:
            groups[key] = d.copy()
    return list(groups.values())

And a slightly more generic solution:

def generic_regroup(values, keys):
    groups = dict()
    valkeys = [k for k in values[0] if k not in key]
    for d in values:
        key = tuple(d[k] for k in keys)
        if key in groups:
            group = groups[key]
            for k in valkeys:
                group[k] += d[k]
        else:
            groups[key] = d.copy()
    return list(groups.values())

results = generic_regroup(values, ("prod_name", "prod_hola"))

Now someone will certainly chime in with a much more clever solution involving itertools...

like image 79
bruno desthuilliers Avatar answered May 30 '26 02:05

bruno desthuilliers


This is a simple and specific solution, I am sure there are more general and cleverer ones. :)

from collections import defaultdict

pr = defaultdict(float)
ra = defaultdict(float)
for el in values:
    combi = (el['prod_name'], el['prod_hola'])
    pr[combi] += el['prihod']
    ra[combi] += el['rashod']

results = [dict(rashod=r, prihod=p, \
                prod_name=nh[0], prod_hola=nh[1]) \
           for r,p,nh in zip(ra.values(), pr.values(), pr)]
print results

gives

[{'rashod': 0.0, 'prihod': 100.0, 'prod_name': 'c', 'prod_hola': 'f'},
 {'rashod': 0.0, 'prihod': 1500.0, 'prod_name': 'a', 'prod_hola': 'b'},
 {'rashod': 0.0, 'prihod': 460.0, 'prod_name': 'r', 'prod_hola': 't'}]
like image 44
Pynchia Avatar answered May 30 '26 03:05

Pynchia



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!