Python列表对所有出现项求和(保持顺序)

crcmnpdw  于 2022-12-15  发布在  Python
关注(0)|答案(4)|浏览(166)

给定一个表格数据结构,我已经调用了pop(0),但是为了清楚起见,将显示标题。基本上它是一个字符串格式的id和两个浮点格式的值条目。

#header
['id','value1','value2']

data=
['1001',25,10],
['1001',25,0],
['1002',100,0],
['1002',100,0],
['1002',100,0],
['1003',150,10]...

并且给定仅包含唯一ids的向量:

ids = ['1001','1002','1003']

我的目标是创建另一个向量来存储所有value1的总和(现在可以忽略value2),同时保持ids中的顺序。

print(ids, sum_result)
1001 50
1002 300
1003 150


我在使用dict方法方面取得了一些进展,但后来我痛苦地意识到顺序没有得到保留。

问题

我们如何迭代'ids'中的每个唯一元素,并对'data'中出现的所有id求和?在我的实际数据中,'value1s'也有一些“Nones”和“NaN“,如果这有助于缩小任何人的解集的话。

**注意:**更喜欢原生Python

eqqqjvef

eqqqjvef1#

itertools.groupby要求首先按键对输入进行排序。一种更通用、可读性更强的方法是遍历记录列表,然后通过聚合相同键的值来生成dict。使用collections.defaultdict可以轻松地初始化新键:

from collections import defaultdict

data = [
    ['1001', 25, 10],
    ['1001', 25, 0],
    ['1002', 100, 0],
    ['1002', 100, 0],
    ['1002', 100, 0],
    ['1003', 150, 10]
]

output = defaultdict(int)
for id, *values in data:
    output[id] += values[0] if values else 0

for id, sum_result in output.items():
    print(id, sum_result)

这将输出:

1001 50
1002 300
1003 150
y53ybaqx

y53ybaqx2#

我建议使用Pandas模块(https://pandas.pydata.org/),首先将数据加载到DataFrame中,然后使用list进行过滤和分组,顺序保持不变。

import pandas as pd
data=[
    ['1001',25,10],
    ['1001',25,0],
    ['1002',100,0],
    ['1002',100,0],
    ['1002',100,0],
    ['1003',150,10]
  ]
ids = ['1001','1002']

#load list into dataframe; there are many ways to create dataframe;
df_data = pd.DataFrame(data)
#lets add column names
df_data.columns=['id','value1','value2']

#filter using isin and group by first column (0), use sum
result = df_data[df_data['id'].isin(ids)].groupby(by=['id']).agg(sum)

输出:#结果头()

value1  value2
id
1001    50      10
1002    300     0

按索引和列名访问结果

print(result.loc['1001']['value1'])
bqucvtff

bqucvtff3#

您可以使用itertools.groupby()
创建一个迭代器,从可迭代对象中返回连续的键和组。键是一个函数,为每个元素计算一个键值。[...]这种行为不同于SQL的GROUP BY,后者聚合公共元素而不管它们的输入顺序。
这在您的情况下非常方便,因为itertools.groupby()使用相同的键对连续的元素进行分组。

>>> print([list(g) for k, g in groupby('AAAABBBCCDAA')]) 
[
    ['A', 'A', 'A', 'A'], 
    ['B', 'B', 'B'], 
    ['C', 'C'], 
    ['D'], 
    ['A', 'A']
]

回答您的问题:

from itertools import groupby

data=[
    ['1001',25,10],
    ['1001',25,0],
    ['1002',100,0],
    ['1002',100,0],
    ['1002',100,0],
    ['1003',150,10]
]

DEFAULT_VALUE_WHEN_NONE = 0

result = [(key, sum(map(lambda x: DEFAULT_VALUE_WHEN_NONE if x[1] is None or math.isnan(x[1]) else x[1], group))) 
          for key, group in groupby(data, key=lambda x: x[0])]
    
print(result)

输出:

[('1001', 50), ('1002', 300), ('1003', 150)]
2eafrhcq

2eafrhcq4#

您可以使用嵌套的for循环自己完成:

data = [
    ['1001', 25, 10],
    ['1001', 25, 0],
    ['1002', 100, 0],
    ['1002', 100, 0],
    ['1002', 100, 0],
    ['1003', 150, 10]
]

ids = ['1003','1001', '1003']

result = [[id, 0] for id in ids]

for row in data:
    for idx in range(len(result)):
        if row[0] == result[idx][0]:
            result[idx][1] += row[1]

print(result)

请注意,使用Pandas来做这种事要慢得多。

相关问题