如何有效地获取Python中两个列表列表中元素的均值

EmJ*_*EmJ 50 python list mean

我有两个列表如下。

mylist1 = [["lemon", 0.1], ["egg", 0.1], ["muffin", 0.3], ["chocolate", 0.5]]
mylist2 = [["chocolate", 0.5], ["milk", 0.2], ["carrot", 0.8], ["egg", 0.8]]
Run Code Online (Sandbox Code Playgroud)

我想得到两个列表中公共元素的平均值,如下所示。

myoutput = [["chocolate", 0.5], ["egg", 0.45]]
Run Code Online (Sandbox Code Playgroud)

我目前的代码如下

for item1 in mylist1:
    for item2 in mylist2:
        if item1[0] == item2[0]:
             print(np.mean([item1[1], item2[1]]))
Run Code Online (Sandbox Code Playgroud)

然而,由于有两个for循环(O(n^2)复杂性),这对于很长的列表来说效率很低。我想知道在 Python 中是否有更标准/更有效的方法来做到这一点。

Ada*_*Er8 38

您可以通过将 1 转换为 dict,然后在第二个列表中的每个项目访问该 dict(在 O(1) 中),在 O(n)(单次遍历每个列表)中完成它,如下所示:

mylist1 = [["lemon", 0.1], ["egg", 0.1], ["muffin", 0.3], ["chocolate", 0.5]]
mylist2 = [["chocolate", 0.5], ["milk", 0.2], ["carrot", 0.8], ["egg", 0.8]]

l1_as_dict = dict(mylist1)

myoutput = []
for item,price2 in mylist2:
    if item in l1_as_dict:
        price1 = l1_as_dict[item]
        myoutput.append([item, (price1+price2)/2])

print(myoutput)
Run Code Online (Sandbox Code Playgroud)

输出:

[['chocolate', 0.5], ['egg', 0.45]]
Run Code Online (Sandbox Code Playgroud)


ACh*_*ion 17

O(n)将平均所有项目的解决方案。
构造一个包含值列表的字典,然后平均该字典:

In []:
d = {}
for lst in (mylist1, mylist2):
    for i, v in lst:
        d.setdefault(i, []).append(v)   # alternative use collections.defaultdict

[(k, sum(v)/len(v)) for k, v in d.items()]

Out[]:
[('lemon', 0.1), ('egg', 0.45), ('muffin', 0.3), ('chocolate', 0.5), ('milk', 0.2), ('carrot', 0.8)]
Run Code Online (Sandbox Code Playgroud)

然后,如果你只想要普通的,你可以添加一个守卫:

In []:
[(k, sum(v)/len(v)) for k, v in d.items() if len(v) > 1]

Out[]:
[('egg', 0.45), ('chocolate', 0.5)]
Run Code Online (Sandbox Code Playgroud)

这扩展到任意数量的列表,并且不对公共元素的数量进行假设。


Roa*_*ner 9

这是一种用于collections.defaultdict对项目进行分组并计算平均值的解决方案statistics.mean

from collections import defaultdict
from statistics import mean

mylist1 = [["lemon", 0.1], ["egg", 0.1], ["muffin", 0.3], ["chocolate", 0.5]]
mylist2 = [["chocolate", 0.5], ["milk", 0.2], ["carrot", 0.8], ["egg", 0.8]]

d = defaultdict(list)
for lst in (mylist1, mylist2):
    for k, v in lst:
        d[k].append(v)

result = [[k, mean(v)] for k, v in d.items()]

print(result)
# [['lemon', 0.1], ['egg', 0.45], ['muffin', 0.3], ['chocolate', 0.5], ['milk', 0.2], ['carrot', 0.8]]
Run Code Online (Sandbox Code Playgroud)

如果我们只想要公共键,只需检查值是否大于 1:

result = [[k, mean(v)] for k, v in d.items() if len(v) > 1]

print(result)
# [['egg', 0.45], ['chocolate', 0.5]]
Run Code Online (Sandbox Code Playgroud)

我们也可以从集合交集构建结果:

mylist1 = [["lemon", 0.1], ["egg", 0.1], ["muffin", 0.3], ["chocolate", 0.5]]
mylist2 = [["chocolate", 0.5], ["milk", 0.2], ["carrot", 0.8], ["egg", 0.8]]

d1, d2 = dict(mylist1), dict(mylist2)

result = [[k, (d1[k] + d2[k]) / 2] for k in d1.keys() & d2.keys()]

print(result)
# [['egg', 0.45], ['chocolate', 0.5]]
Run Code Online (Sandbox Code Playgroud)


May*_*wal 8

您可以使用Pandas库来避免自己编写任何类型的循环。

您的代码将非常简洁和干净。

像安装熊猫:pip install pandas

然后试试这个:

In [132]: import pandas as pd

In [109]: df1 = pd.DataFrame(mylist1)

In [110]: df2 = pd.DataFrame(mylist2)

In [117]: res = pd.merge(df1, df2, on=0)

In [121]: res['mean'] = res.mean(axis=1)

In [125]: res.drop(['1_x', '1_y'], 1, inplace=True)

In [131]: res.values.tolist()
Out[131]: [['egg', 0.45], ['chocolate', 0.5]]
Run Code Online (Sandbox Code Playgroud)

编辑

Pandas 非常快,因为它numpy在幕后使用。Numpy 实现了高效的数组操作。

请查看帖子:为什么 Pandas 的速度如此之快?有关mean通过计算的更多详细信息pure Python vs Pandas


azr*_*zro 7

为了轻松操纵您的值,我建议使用 a dict,找到公共键并计算平均值:

mylist1 = [["lemon", 0.1], ["egg", 0.1], ["muffin", 0.3], ["chocolate", 0.5]]
mylist2 = [["chocolate", 0.5], ["milk", 0.2], ["carrot", 0.8], ["egg", 0.8]]

recipe_1 = dict(mylist1)  # {'lemon': 0.1, 'egg': 0.1, 'muffin': 0.3, 'chocolate': 0.5}
recipe_2 = dict(mylist2)  # {'chocolate': 0.5, 'milk': 0.2, 'carrot': 0.8, 'egg': 0.8}

common_keys = recipe_1.keys() & recipe_2.keys()  # {'chocolate', 'egg'}

myoutput = [[item, np.mean((recipe_1[item], recipe_2[item]))] for item in common_keys]
myoutput = [[item, (recipe_1[item] + recipe_2[item]) / 2] for item in common_keys]
Run Code Online (Sandbox Code Playgroud)


Tra*_*man 6

将列表转换为字典

d_list1 = dict(mylist1)
d_list2 = dict(mylist2)

[[k, (v+d_list2[k])/2] for k, v in d_list1.items() if k in d_list2]
#[['egg', 0.45], ['chocolate', 0.5]]
Run Code Online (Sandbox Code Playgroud)


Ful*_*Guy 6

您可以使用set intersection方法从两个列表中获取公共键,然后使用列表推导计算平均值:

mylist1 = [["lemon", 0.1], ["egg", 0.1], ["muffin", 0.3], ["chocolate", 0.5]]
mylist2 = [["chocolate", 0.5], ["milk", 0.2], ["carrot", 0.8], ["egg", 0.8]]

dict1 = dict(mylist1)
dict2 = dict(mylist2)
res = [[key, (dict1.get(key)+dict2.get(key))/2] for key in set(dict1.keys()).intersection(set(dict2.keys()))]
print(res)
Run Code Online (Sandbox Code Playgroud)

输出:

>> [['chocolate', 0.5], ['egg', 0.45]]
Run Code Online (Sandbox Code Playgroud)


jer*_*man 5

您可以在交换集合交集所需的时间内完成,这显然是 O(min(N1,N2)) 其中 N1, N2 是列表长度。

intersect = set([a[0] for a in mylist1]).intersection([a[0] for a in mylist2])
d1=dict(mylist1)
d2=dict(mylist2)
{i:(d1[i]+d2[i])/2 for i in intersect}
Run Code Online (Sandbox Code Playgroud)