使用复合键的多列 Python 聚合

我想知道如何使用一个键聚合多个列。我有用于聚合单个列的工作代码,但我想将其扩展到多个列。


下面是一些示例数据。实际求和意义不大,数据是为了说明问题。


下面的代码在 Tm、Lg、Pos 上创建一个键并总结 PTS。


我想总结 PTS 和 G 为同一个键。


我可以在熊猫中轻松做到这一点,但想使用 Python 而不是熊猫。


$ cat test-file.csv

Season,Age,Tm,Lg,Pos,G,FGA,PTS

2003-04,22,MIA,NBA,PG,61,13.1,16.2

2004-05,23,MIA,NBA,SG,77,17.1,24.1

2005-06,24,MIA,NBA,SG,75,18.8,27.2

2006-07,25,MIA,NBA,SG,51,18.9,27.4

2007-08,26,MIA,NBA,SG,51,18.4,24.6

2008-09,27,MIA,NBA,SG,79,22.0,30.2

2009-10,28,MIA,NBA,SG,77,19.6,26.6

2010-11,29,MIA,NBA,SG,76,18.2,25.5

2011-12,30,MIA,NBA,SG,49,17.1,22.1

2012-13,31,MIA,NBA,SG,69,15.8,21.2

2013-14,32,MIA,NBA,SG,54,14.1,19.0

2014-15,33,MIA,NBA,SG,62,17.5,21.5

2015-16,34,MIA,NBA,SG,74,16.0,19.0

2016-17,35,CHI,NBA,SG,60,15.9,18.3

2017-18,36,CLE,NBA,SG,46,9.5,11.2

2017-18,36,MIA,NBA,SG,21,11.8,12.0

2018-19,37,MIA,NBA,SG,72,13.3,15.0



import csv

import re

from collections import namedtuple


totals = {}


with open ('/home/test-file.csv', 'r') as input_file:

    reader = csv.reader(input_file, delimiter=',')

    header = next(reader)


    record = namedtuple('record', header)


    for rec in (record._make(row) for row in reader):

        totals[rec.Tm, rec.Lg, rec.Pos] = \

            (totals.get((rec.Tm, rec.Lg, rec.Pos), 0.0) + \

            float(rec.PTS))

    for key, value in sorted(totals.items()):

        row = list(key) + [value]

        print(row)


['CHI', 'NBA', 'SG', 18.3]

['CLE', 'NBA', 'SG', 11.2]

['MIA', 'NBA', 'PG', 16.2]

['MIA', 'NBA', 'SG', 315.4]

我正在寻找如下输出,即两个聚合列。


['CHI', 'NBA', 'SG', 60, 18.3]

['CLE', 'NBA', 'SG', 46, 11.2]

['MIA', 'NBA', 'PG', 61, 16.2]

['MIA', 'NBA', 'SG', 887, 315.4]

编辑:错字,“总和”到“总和不”。


大话西游666
浏览 111回答 1
1回答

撒科打诨

正如@BlueSheepToken 所建议的那样,来自 itertools 的 group by 是您的朋友。其他 python 本机和高性能解决方案在其中一个funcy或toolz包中实现。这里有一个解决方案toolzimport csvfrom operator import itemgetterimport toolzimport toolz.currieddef stream_file(fp):    with open(fp) as file:        for line in csv.DictReader(file):            res = dict(line)            res['G'] = float(res['G'])            res['PTS'] = float(res['PTS'])            yield res# groups from streamgroups = toolz.groupby(['Tm', 'Lg', 'Pos'], stream_file('test_file.csv'))# aggregation functions: get some value from list, then sum it uppts_counter = toolz.compose_left(toolz.curried.map(itemgetter('PTS')), sum)g_counter = toolz.compose_left(toolz.curried.map(itemgetter('G')), sum)# apply both functions to the inputaggregations = toolz.juxt(pts_counter, g_counter)# for each group's value compute aggregations toolz.valmap(aggregations, groups)输出:{('CHI', 'NBA', 'SG'): (18.3, 60.0), ('CLE', 'NBA', 'SG'): (11.2, 46.0), ('MIA', 'NBA', 'PG'): (16.2, 61.0), ('MIA', 'NBA', 'SG'): (315.4, 887.0)}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python