我有几个元组的Python列表:
[(0, 61), (1, 30), (5, 198), (4, 61), (0, 30), (5, 200)]
[(1, 72), (2, 19), (3, 31), (4, 192), (6, 72), (5, 75)]
[(3, 12), (0, 51)]
...
创建每个元组,使其格式为(key, value)
:
有七个键:0,1,2,3,4,5,6
预期输出是一个pandas DataFrame,每个列都由键命名:
import pandas as pd
print(df)
0 1 2 3 4 5 6
91 30 0 0 61 198 0
0 72 19 31 192 75 72
51 0 0 12 0 0 0
现在,我在概念上遇到的问题是如何添加几个元组"值"如果他们的钥匙是相同的。
我可以访问给定列表的这些值,例如
mylist = [(0, 61), (1, 30), (5, 198), (4, 61), (0, 30), (5, 200)]
keys = [x[0] for x in mylist]
和
print(keys)
[0, 1, 5, 4, 0, 5]
我不确定如何制作,例如密钥的字典:值对,我可以将其加载到pandas DataFrame
中答案 0 :(得分:4)
以名称tups
tups = [
[(0, 61), (1, 30), (5, 198), (4, 61), (0, 30), (5, 200)],
[(1, 72), (2, 19), (3, 31), (4, 192), (6, 72), (5, 75)],
[(3, 12), (0, 51)]
]
选项0
使用np.bincount
和疯狂的地图,拉链和splats
这是有效的,因为np.bincount
的前两个参数是位置数组和添加时使用的可选权重数组。
pd.DataFrame(
list(map(lambda t: np.bincount(*zip(*t)), tups))
).fillna(0, downcast='infer')
0 1 2 3 4 5 6
0 91 30 0 0 61 398 0
1 0 72 19 31 192 75 72
2 51 0 0 12 0 0 0
选项1
在轴级上使用理解和求和。
pd.Series({
(i, j, k): v
for i, row in enumerate(tups)
for k, (j, v) in enumerate(row)
}).sum(level=[0, 1]).unstack(fill_value=0)
0 1 2 3 4 5 6
0 91 30 0 0 61 398 0
1 0 72 19 31 192 75 72
2 51 0 0 12 0 0 0
选项2
您可以对使用defaultdict的结果使用DataFrame
构造函数:
from collections import defaultdict
d = defaultdict(lambda: defaultdict(int))
for i, row in enumerate(tups):
for j, v in row:
d[j][i] += v
pd.DataFrame(d).fillna(0, downcast='infer')
0 1 2 3 4 5 6
0 91 30 0 0 61 398 0
1 0 72 19 31 192 75 72
2 51 0 0 12 0 0 0
选项3
创建零数据帧并通过迭代更新它
n, m = len(tups), max(j for row in tups for j, _ in row) + 1
df = pd.DataFrame(0, range(n), range(m))
for i, row in enumerate(tups):
for j, v in row:
df.at[i, j] += v
df
0 1 2 3 4 5 6
0 91 30 0 0 61 398 0
1 0 72 19 31 192 75 72
2 51 0 0 12 0 0 0
答案 1 :(得分:3)
使用piRSquared的例子:
tups = [
[(0, 61), (1, 30), (5, 198), (4, 61), (0, 30), (5, 200)],
[(1, 72), (2, 19), (3, 31), (4, 192), (6, 72), (5, 75)],
[(3, 12), (0, 51)]
]
#First build a dict for each row with unique keys.
data = [{f[0]:[] for f in e} for e in tups]
#add values to the dict as list which can capture multiple values.
[[data[k][e[0]].append(e[1]) for e in v] for k,v in enumerate(tups)]
#sum values for each key for each row.
data = [{k:sum(v) for k,v in e.items()} for e in data]
# build a df and fillna with 0
pd.DataFrame(data).fillna(0, downcast='infer')
Out[127]:
0 1 2 3 4 5 6
0 91 30 0 0 61 398 0
1 0 72 19 31 192 75 72
2 51 0 0 12 0 0 0
答案 2 :(得分:2)
我会:
NaN
s import pandas as pd
data = [ [(0, 61), (1, 30), (5, 198), (4, 61), (0, 30), (5, 200)],
[(1, 72), (2, 19), (3, 31), (4, 192), (6, 72), (5, 75)],
[(0, 71), (1, 40), (5, 98), (4, 21), (0, 10), (5, 21200)], # addon
[(1, 702), (2, 190), (3, 310), (4, 1092), (6, 702), (5, 705)], # addon
]
consolidated = []
for li in data:
row = {} # instead of replacing NaNs you could prefill: row = {k:0 for k in range(7)}
for tup in li:
key,val = tup
row.setdefault(key,0)
row[key]+=val
consolidated.append (row)
df = pd.DataFrame(consolidated)
df = df.fillna(0) # replace NaN's with 0
print(df)
输出:
0 1 2 3 4 5 6
0 91.0 30 0.0 0.0 61 398 0.0
1 0.0 72 19.0 31.0 192 75 72.0
2 81.0 40 0.0 0.0 21 21298 0.0
3 0.0 702 190.0 310.0 1092 705 702.0
答案 3 :(得分:2)
您可以先为每个元素应用groupby
按键加值,然后使用pandas
转换为数据帧。 注意您必须在求和之前先按键排序。
import pandas as pd
from itertools import groupby
data = [
[(0, 61), (1, 30), (5, 198), (4, 61), (0, 30), (5, 200)],
[(1, 72), (2, 19), (3, 31), (4, 192), (6, 72), (5, 75)],
[(0, 71), (1, 40), (5, 98), (4, 21), (0, 10), (5, 21200)],
[(1, 702), (2, 190), (3, 310), (4, 1092), (6, 702), (5, 705)],
] # copying example from @PatrickArtnerz solution
def group_sum(data):
"""given list, return dictionary of summation based on initial key"""
data_dict = {k: sum(v_[1] for v_ in v) for k, v in groupby(sorted(data, key=lambda x: x[0]), lambda x: x[0])}
return data_dict
df = pd.DataFrame(list(map(group_sum, data))).fillna(0)