元组列表中具有相同索引的所有元素的平均值
Average of all elements in tuple list having the same index
我有一个非常奇怪的数据结构,它是一个元组列表。每个元组有五个元素,其中第一个是标识字符串,其他四个字符串是浮点数(很奇怪,它们不仅仅是浮点数)。
抱歉,我是从别人那里得到的数据。
我想对第一个索引相同的 2-5 个数字的所有数字进行平均。
示例:
[('ch', ' 0.8307', '0.8583', '0.8047', ' 0.969'),
('de', ' 0.721', '0.7529', '0.6917', ' 0.968'),
('en', ' 0.8441', '0.8732', '0.8168', ' 0.9569'),
('fn', ' 0.8207', '0.8574', '0.7870', ' 0.9609'),
('ch', ' 0.466', '0.572', '0.7733', ' 0.969'),
('de', ' 0.322', '0.385', '0.5431', ' 0.968'),
('sp', ' 0.7609', '0.7893', '0.7344', ' 0.9663'),
('ti', ' 0.8135', '0.8430', '0.7860', ' 0.9662')]
输出应该只是将具有相同第一个索引的所有元素收缩在一起并对它们的值进行平均,所以它会是这样的(我在这里的示例输出中没有对值进行平均):
[('ch', ' 0.8307', '0.8583', '0.8047', ' 0.969'),
('de', ' 0.721', '0.7529', '0.6917', ' 0.968'),
('en', ' 0.8441', '0.8732', '0.8168', ' 0.9569'),
('fn', ' 0.8207', '0.8574', '0.7870', ' 0.9609'),
('sp', ' 0.7609', '0.7893', '0.7344', ' 0.9663'),
('ti', ' 0.8135', '0.8430', '0.7860', ' 0.9662')]
这里有什么我可以做的非常聪明的事情,而不是制作一个巨大的 for 循环来提取所有内容吗?
可以先创建一个dict,收集每个id相关的所有值,然后计算均值:
from collections import defaultdict
data = [('ch', ' 0.8307', '0.8583', '0.8047', ' 0.969'),
('de', ' 0.721', '0.7529', '0.6917', ' 0.968'),
('en', ' 0.8441', '0.8732', '0.8168', ' 0.9569'),
('fn', ' 0.8207', '0.8574', '0.7870', ' 0.9609'),
('ch', ' 0.466', '0.572', '0.7733', ' 0.969'),
('de', ' 0.322', '0.385', '0.5431', ' 0.968'),
('sp', ' 0.7609', '0.7893', '0.7344', ' 0.9663'),
('ti', ' 0.8135', '0.8430', '0.7860', ' 0.9662')]
def mean(lst):
return sum(lst)/len(lst)
d = defaultdict(list)
for id, *values in data:
d[id].append(list(map(float, values)))
out = {id: [mean(column) for column in zip(*values)] for id, values in d.items() }
print(out)
# {'ch': [0.64835, 0.71515, 0.7889999999999999, 0.969],
# 'de': [0.5215, 0.5689500000000001, 0.6174, 0.968],
# 'en': [0.8441, 0.8732, 0.8168, 0.9569],
# 'fn': [0.8207, 0.8574, 0.787, 0.9609],
# 'sp': [0.7609, 0.7893, 0.7344, 0.9663],
# 'ti': [0.8135, 0.843, 0.786, 0.9662]}
在for id, *values in data:
中,我们迭代data
的元组,并将元组的第一项放入id
,其余值放入values
。
此外,使用 defaultdict(list)
允许我们简单地为每个键附加新的值列表,因为如果列表尚不存在,将自动创建一个空列表。
一些数字争论:
- 使用正确的键和实际浮点数的列表列表创建 defaultdict
- 检查是否需要平均并利用 zip()
data = [('ch', ' 0.8307', '0.8583', '0.8047', ' 0.969'),
('de', ' 0.721', '0.7529', '0.6917', ' 0.968'),
('en', ' 0.8441', '0.8732', '0.8168', ' 0.9569'),
('fn', ' 0.8207', '0.8574', '0.7870', ' 0.9609'),
('ch', ' 0.466', '0.572', '0.7733', ' 0.969'),
('de', ' 0.322', '0.385', '0.5431', ' 0.968'),
('sp', ' 0.7609', '0.7893', '0.7344', ' 0.9663'),
('ti', ' 0.8135', '0.8430', '0.7860', ' 0.9662')]
from pprint import pprint
from collections import defaultdict
d = defaultdict(list)
for t in data:
d[t[0]].append(list(map(float, t[1:])))
pprint(d)
for key, values in d.items():
w = len(values)
if w > 1:
d[key] = [sum(numbers) / w for numbers in zip(*values)]
else:
d[key] = d[key][0]
pprint(d)
输出:
# after converting to float and collecting into lists
defaultdict(<class 'list'>,
{'ch': [[0.8307, 0.8583, 0.8047, 0.969],
[0.466, 0.572, 0.7733, 0.969]],
'de': [[0.721, 0.7529, 0.6917, 0.968],
[0.322, 0.385, 0.5431, 0.968]],
'en': [[0.8441, 0.8732, 0.8168, 0.9569]],
'fn': [[0.8207, 0.8574, 0.787, 0.9609]],
'sp': [[0.7609, 0.7893, 0.7344, 0.9663]],
'ti': [[0.8135, 0.843, 0.786, 0.9662]]})
# after averaging
defaultdict(<class 'list'>,
{'ch': [0.64835, 0.71515, 0.7889999999999999, 0.969],
'de': [0.5215, 0.5689500000000001, 0.6174, 0.968],
'en': [0.8441, 0.8732, 0.8168, 0.9569],
'fn': [0.8207, 0.8574, 0.787, 0.9609],
'sp': [0.7609, 0.7893, 0.7344, 0.9663],
'ti': [0.8135, 0.843, 0.786, 0.9662]})
有了pandas就更简单了:
data = [('ch', ' 0.8307', '0.8583', '0.8047', ' 0.969'),
('de', ' 0.721', '0.7529', '0.6917', ' 0.968'),
('en', ' 0.8441', '0.8732', '0.8168', ' 0.9569'),
('fn', ' 0.8207', '0.8574', '0.7870', ' 0.9609'),
('ch', ' 0.466', '0.572', '0.7733', ' 0.969'),
('de', ' 0.322', '0.385', '0.5431', ' 0.968'),
('sp', ' 0.7609', '0.7893', '0.7344', ' 0.9663'),
('ti', ' 0.8135', '0.8430', '0.7860', ' 0.9662')]
import pandas as pd
df = pd.DataFrame(data, dtype=float)
print(df.groupby(0).mean())
输出:
1 2 3 4
0
ch 0.64835 0.71515 0.7890 0.9690 # pandas displays "nice" numbers,
de 0.52150 0.56895 0.6174 0.9680 # it contains the "correct" ones
en 0.84410 0.87320 0.8168 0.9569
fn 0.82070 0.85740 0.7870 0.9609
sp 0.76090 0.78930 0.7344 0.9663
ti 0.81350 0.84300 0.7860 0.9662
类似下面的内容(基于零进口的解决方案)
avg_data = {}
data = [('ch', ' 0.8307', '0.8583', '0.8047', ' 0.969'),
('de', ' 0.721', '0.7529', '0.6917', ' 0.968'),
('en', ' 0.8441', '0.8732', '0.8168', ' 0.9569'),
('fn', ' 0.8207', '0.8574', '0.7870', ' 0.9609'),
('ch', ' 0.466', '0.572', '0.7733', ' 0.969'),
('de', ' 0.322', '0.385', '0.5431', ' 0.968'),
('sp', ' 0.7609', '0.7893', '0.7344', ' 0.9663'),
('ti', ' 0.8135', '0.8430', '0.7860', ' 0.9662')]
for entry in data:
if entry[0] not in avg_data:
avg_data[entry[0]] = [0, [0, 0, 0, 0]]
for idx, x in enumerate(entry[1:]):
avg_data[entry[0]][1][idx] += float(x)
avg_data[entry[0]][0] += 1
result = []
for k, v in avg_data.items():
result.append([k])
result[-1].extend([x / v[0] for x in v[1]])
result[-1] = tuple(result[-1])
print(result)
输出
[('ch', 0.64835, 0.71515, 0.7889999999999999, 0.969), ('de', 0.5215, 0.5689500000000001, 0.6174, 0.968), ('en', 0.8441, 0.8732, 0.8168, 0.9569), ('fn', 0.8207, 0.8574, 0.787, 0.9609), ('sp', 0.7609, 0.7893, 0.7344, 0.9663), ('ti', 0.8135, 0.843, 0.786, 0.9662)]
我有一个非常奇怪的数据结构,它是一个元组列表。每个元组有五个元素,其中第一个是标识字符串,其他四个字符串是浮点数(很奇怪,它们不仅仅是浮点数)。 抱歉,我是从别人那里得到的数据。
我想对第一个索引相同的 2-5 个数字的所有数字进行平均。 示例:
[('ch', ' 0.8307', '0.8583', '0.8047', ' 0.969'),
('de', ' 0.721', '0.7529', '0.6917', ' 0.968'),
('en', ' 0.8441', '0.8732', '0.8168', ' 0.9569'),
('fn', ' 0.8207', '0.8574', '0.7870', ' 0.9609'),
('ch', ' 0.466', '0.572', '0.7733', ' 0.969'),
('de', ' 0.322', '0.385', '0.5431', ' 0.968'),
('sp', ' 0.7609', '0.7893', '0.7344', ' 0.9663'),
('ti', ' 0.8135', '0.8430', '0.7860', ' 0.9662')]
输出应该只是将具有相同第一个索引的所有元素收缩在一起并对它们的值进行平均,所以它会是这样的(我在这里的示例输出中没有对值进行平均):
[('ch', ' 0.8307', '0.8583', '0.8047', ' 0.969'),
('de', ' 0.721', '0.7529', '0.6917', ' 0.968'),
('en', ' 0.8441', '0.8732', '0.8168', ' 0.9569'),
('fn', ' 0.8207', '0.8574', '0.7870', ' 0.9609'),
('sp', ' 0.7609', '0.7893', '0.7344', ' 0.9663'),
('ti', ' 0.8135', '0.8430', '0.7860', ' 0.9662')]
这里有什么我可以做的非常聪明的事情,而不是制作一个巨大的 for 循环来提取所有内容吗?
可以先创建一个dict,收集每个id相关的所有值,然后计算均值:
from collections import defaultdict
data = [('ch', ' 0.8307', '0.8583', '0.8047', ' 0.969'),
('de', ' 0.721', '0.7529', '0.6917', ' 0.968'),
('en', ' 0.8441', '0.8732', '0.8168', ' 0.9569'),
('fn', ' 0.8207', '0.8574', '0.7870', ' 0.9609'),
('ch', ' 0.466', '0.572', '0.7733', ' 0.969'),
('de', ' 0.322', '0.385', '0.5431', ' 0.968'),
('sp', ' 0.7609', '0.7893', '0.7344', ' 0.9663'),
('ti', ' 0.8135', '0.8430', '0.7860', ' 0.9662')]
def mean(lst):
return sum(lst)/len(lst)
d = defaultdict(list)
for id, *values in data:
d[id].append(list(map(float, values)))
out = {id: [mean(column) for column in zip(*values)] for id, values in d.items() }
print(out)
# {'ch': [0.64835, 0.71515, 0.7889999999999999, 0.969],
# 'de': [0.5215, 0.5689500000000001, 0.6174, 0.968],
# 'en': [0.8441, 0.8732, 0.8168, 0.9569],
# 'fn': [0.8207, 0.8574, 0.787, 0.9609],
# 'sp': [0.7609, 0.7893, 0.7344, 0.9663],
# 'ti': [0.8135, 0.843, 0.786, 0.9662]}
在for id, *values in data:
中,我们迭代data
的元组,并将元组的第一项放入id
,其余值放入values
。
此外,使用 defaultdict(list)
允许我们简单地为每个键附加新的值列表,因为如果列表尚不存在,将自动创建一个空列表。
一些数字争论:
- 使用正确的键和实际浮点数的列表列表创建 defaultdict
- 检查是否需要平均并利用 zip()
data = [('ch', ' 0.8307', '0.8583', '0.8047', ' 0.969'),
('de', ' 0.721', '0.7529', '0.6917', ' 0.968'),
('en', ' 0.8441', '0.8732', '0.8168', ' 0.9569'),
('fn', ' 0.8207', '0.8574', '0.7870', ' 0.9609'),
('ch', ' 0.466', '0.572', '0.7733', ' 0.969'),
('de', ' 0.322', '0.385', '0.5431', ' 0.968'),
('sp', ' 0.7609', '0.7893', '0.7344', ' 0.9663'),
('ti', ' 0.8135', '0.8430', '0.7860', ' 0.9662')]
from pprint import pprint
from collections import defaultdict
d = defaultdict(list)
for t in data:
d[t[0]].append(list(map(float, t[1:])))
pprint(d)
for key, values in d.items():
w = len(values)
if w > 1:
d[key] = [sum(numbers) / w for numbers in zip(*values)]
else:
d[key] = d[key][0]
pprint(d)
输出:
# after converting to float and collecting into lists
defaultdict(<class 'list'>,
{'ch': [[0.8307, 0.8583, 0.8047, 0.969],
[0.466, 0.572, 0.7733, 0.969]],
'de': [[0.721, 0.7529, 0.6917, 0.968],
[0.322, 0.385, 0.5431, 0.968]],
'en': [[0.8441, 0.8732, 0.8168, 0.9569]],
'fn': [[0.8207, 0.8574, 0.787, 0.9609]],
'sp': [[0.7609, 0.7893, 0.7344, 0.9663]],
'ti': [[0.8135, 0.843, 0.786, 0.9662]]})
# after averaging
defaultdict(<class 'list'>,
{'ch': [0.64835, 0.71515, 0.7889999999999999, 0.969],
'de': [0.5215, 0.5689500000000001, 0.6174, 0.968],
'en': [0.8441, 0.8732, 0.8168, 0.9569],
'fn': [0.8207, 0.8574, 0.787, 0.9609],
'sp': [0.7609, 0.7893, 0.7344, 0.9663],
'ti': [0.8135, 0.843, 0.786, 0.9662]})
有了pandas就更简单了:
data = [('ch', ' 0.8307', '0.8583', '0.8047', ' 0.969'),
('de', ' 0.721', '0.7529', '0.6917', ' 0.968'),
('en', ' 0.8441', '0.8732', '0.8168', ' 0.9569'),
('fn', ' 0.8207', '0.8574', '0.7870', ' 0.9609'),
('ch', ' 0.466', '0.572', '0.7733', ' 0.969'),
('de', ' 0.322', '0.385', '0.5431', ' 0.968'),
('sp', ' 0.7609', '0.7893', '0.7344', ' 0.9663'),
('ti', ' 0.8135', '0.8430', '0.7860', ' 0.9662')]
import pandas as pd
df = pd.DataFrame(data, dtype=float)
print(df.groupby(0).mean())
输出:
1 2 3 4
0
ch 0.64835 0.71515 0.7890 0.9690 # pandas displays "nice" numbers,
de 0.52150 0.56895 0.6174 0.9680 # it contains the "correct" ones
en 0.84410 0.87320 0.8168 0.9569
fn 0.82070 0.85740 0.7870 0.9609
sp 0.76090 0.78930 0.7344 0.9663
ti 0.81350 0.84300 0.7860 0.9662
类似下面的内容(基于零进口的解决方案)
avg_data = {}
data = [('ch', ' 0.8307', '0.8583', '0.8047', ' 0.969'),
('de', ' 0.721', '0.7529', '0.6917', ' 0.968'),
('en', ' 0.8441', '0.8732', '0.8168', ' 0.9569'),
('fn', ' 0.8207', '0.8574', '0.7870', ' 0.9609'),
('ch', ' 0.466', '0.572', '0.7733', ' 0.969'),
('de', ' 0.322', '0.385', '0.5431', ' 0.968'),
('sp', ' 0.7609', '0.7893', '0.7344', ' 0.9663'),
('ti', ' 0.8135', '0.8430', '0.7860', ' 0.9662')]
for entry in data:
if entry[0] not in avg_data:
avg_data[entry[0]] = [0, [0, 0, 0, 0]]
for idx, x in enumerate(entry[1:]):
avg_data[entry[0]][1][idx] += float(x)
avg_data[entry[0]][0] += 1
result = []
for k, v in avg_data.items():
result.append([k])
result[-1].extend([x / v[0] for x in v[1]])
result[-1] = tuple(result[-1])
print(result)
输出
[('ch', 0.64835, 0.71515, 0.7889999999999999, 0.969), ('de', 0.5215, 0.5689500000000001, 0.6174, 0.968), ('en', 0.8441, 0.8732, 0.8168, 0.9569), ('fn', 0.8207, 0.8574, 0.787, 0.9609), ('sp', 0.7609, 0.7893, 0.7344, 0.9663), ('ti', 0.8135, 0.843, 0.786, 0.9662)]