список словаря: совокупное значение путем группировки по внутреннему ключу словаря - PullRequest
1 голос
/ 18 февраля 2020

У меня есть эта подпись:

def aggregate_by_player_id(input, playerid, fields):

Под «полями» я подразумеваю поля для суммирования группировки по «playerID» внутри «input».

Я вызываю функцию следующим образом:

aggregate_by_player_id(input, 'player', ['stat1','stat3'])

Вход выглядит так:

[{'player': '1', 'stat1': '3', 'stat2': '4', 'stat3': '5'},
{'player': '1', 'stat1': '1', 'stat2': '4', 'stat3': '1'},
{'player': '2', 'stat1': '1', 'stat2': '2', 'stat3': '3'},
{'player': '2', 'stat1': '1', 'stat2': '2', 'stat3': '1'},
{'player': '3', 'stat1': '4', 'stat2': '1', 'stat3': '6'}]

Моя структура вывода :

nested_dic = {value_of_playerid1: {'playerid': value_of_playerid1, 'stat1': value_of_stat1, 'stat2': value_of_stat2}, 
              value_of_playerid2: {'playerid': value_of_playerid2, 'stat2': value_of_stat2, 'stat2': value_of_stat2}, 
              value_of_playerid3: {'playerid': value_of_playerid3, 'stat3': value_of_stat3, 'stat3': value_of_stat3}}

Следовательно, результат должен выглядеть следующим образом:

{'1': {'player': '1', 'stat1': 4, 'stat3': 6}, 
 '2': {'player': '2', 'stat1': 2, 'stat3': 4}, 
 '3': {'player': '3', 'stat1': 4, 'stat3': 6}} 

Ответы [ 2 ]

2 голосов
/ 18 февраля 2020

Мы можем использовать itertools.groupby, чтобы сгруппировать по playerid и затем суммировать значения по полям.

from itertools import groupby
from operator import itemgetter

def aggregate_by_player_id(input_, playerid, fields):
    player = itemgetter(playerid)
    output = {}

    for k, v in groupby(input_, key=player):
        data = list(v)
        stats = {playerid: k}

        for field in fields:
            stats[field] = sum(int(d.get(field, 0)) for d in data)
        output[k] = stats
    return output

data.sort(key=player) # data must be pre-sorted on grouping key
results = aggregate_by_player_id(data, 'player', ['stat1', 'stat3'])

{'1': {'player': '1', 'stat1': 4, 'stat3': 6},
 '2': {'player': '2', 'stat1': 2, 'stat3': 4},
 '3': {'player': '3', 'stat1': 4, 'stat3': 6}}
1 голос
/ 18 февраля 2020

Захват результата, которого вы достигаете, в одном понимании может быть возможным, но, вероятно, не очень читабельным. Вот простая функция, которая выполняет эту работу:

data = [
    {'player': '1', 'stat1': '3', 'stat2': '4', 'stat3': '5'},
    {'player': '1', 'stat1': '1', 'stat2': '4', 'stat3': '1'},
    {'player': '2', 'stat1': '1', 'stat2': '2', 'stat3': '3'},
    {'player': '2', 'stat1': '1', 'stat2': '2', 'stat3': '1'},
    {'player': '3', 'stat1': '4', 'stat2': '1', 'stat3': '6'}
]


def aggregate_dicts(ds, id_field, aggr_fields):
    result = {}
    for d in ds:
        identifier = d[id_field]
        if identifier not in result:
            result[identifier] = {f: 0 for f in aggr_fields}
        for f in aggr_fields:
            result[identifier][f] += int(d[f])
    return result


print(aggregate_dicts(data, 'player', ['stat1', 'stat3']))

Результат:

{'1': {'stat1': 4, 'stat3': 6}, '2': {'stat1': 2, 'stat3': 4}, '3': {'stat1': 4, 'stat3': 6}}

Если вы хотите повторить идентификатор внутри dict, просто добавьте эту строку в блок if :

            result[identifier][id_field] = identifier
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...