【问题标题】:Average calculation in PythonPython中的平均计算
【发布时间】:2018-12-23 19:02:32
【问题描述】:

我正在尝试加速 python sn-p。

给定两个大小相等(numpy)的数组,目标是找到一个数组(例如 a)中的值的平均值,对应于另一个数组(例如 b)的值。数组的索引是同步的。

例如;

a = np.array([1, 1, 1, 2, 2, 2])
b = np.array([10, 10, 10, 20, 20, 20])

a 中有两个不同的值,1 和 2。b 中同一索引处a 中有“1”的值是 [10,10,10]。因此,average(1) 为 10。类似地,average(2) 为 20。

我们可以假设a 中的不同值集是先验已知的。 a 中的值不必连续,顺序是随机的。我选择这样的例子只是为了简化描述。

我是这样处理的:

   # Accumulate the total sum and count
    for index, val in np.ndenumerate(a):
        val_to_sum[val] += b[index]
        val_to_count[val] += 1

    # Calculate the mean
    for val in val_to_sum.keys():
        if val_to_count[val]:  # skip vals with zero count
            val_to_mean[val] = val_to_sum[val] / val_to_count[val]

这里的val_to_sumval_to_count 是根据a 中可以看到的已知值列表(在本例中为1 和2)初始化为零的字典。

我怀疑这是计算它的最快方法。我预计列表会很长,比如几百万,而可能值的集合大约是几十。

如何加快计算速度?

可以解决吗? 受以下答案之一的启发,这可能会做到:

for val in a 
  b[a==val].mean() 

【问题讨论】:

  • 给出的链接是一个普通的平均计算,这里不是这样。
  • 如果是这种情况,您可以通过删除重复项来做到这一点。
  • 您希望a 中有多少不同的值?
  • “我预计列表会很长,比如几百万,而可能值的集合大约是几十。”说〜100个不同的值

标签: python performance numpy average


【解决方案1】:

也许这样的事情会起作用:

import numpy as np

a = np.array([1, 1, 1, 2, 2, 2])
b = np.array([10, 10, 10, 20, 20, 20])

np.average(b[a==1])
np.average(b[a==2])

对于更大的数据集:

import numpy as np

a = np.random.randint(1,30,1000000)
b = np.random.random(size=1000000)

for x in set(a):
  print("Average for values marked {0}: {1}".format(x,np.average(b[a==x])))

【讨论】:

  • b[a] 返回 >> array([10, 10, 10, 10, 10, 10]) 不确定这是什么意思。 np.average(b[a]) 返回 >> 10.0 我需要两个输出。在这种情况下,平均值(1)= 10 和平均值(2)= 20
  • 可能是 b[a==1].mean() b[a==2).mean()
  • @skadio:a==1a==2 应该可以工作。查看修改后的答案。
  • @skadio:这也可以很好地扩展到更大的数据集。我已经添加了第二个展示这个的部分。
  • 这很好用!谢谢。使用 np.average(b[a==x]) 与 b[a==x].mean() 之间的任何特殊优势
【解决方案2】:

您可以浏览一次列表:

means_dict = {}
for i in range(len(a)):
    val = a[i]
    n = b[i]
    if val not in means_dict.keys():
        means_dict[val] = np.array([0.0,0.0])
    arr = means_dict[val]
    arr[0] = arr[0] * (arr[1] / (arr[1] + 1)) + n * (1 / (arr[1] + 1))
    arr[1] = arr[1] + 1

计算每个值的运行平均值。最后你会得到一个字典,每个值的平均值和计数。

编辑:
实际上,到处玩,表明这是最好的结果:

def f3(a,b):
    means = {}
    for val in set(a):
      means[val] = np.average(b[a==val]) 
    return means

这和你建议的差不多,只是遍历set,节省了很多时间。

【讨论】:

  • 谢谢!您能否详细说明为什么 np.average() 比 .mean() 快?
  • 其实不是,纠正了自己,是这么想的,而且一些经验测试表明它更快,但是现在在查看源代码时似乎我错了。
【解决方案3】:

可以通过删除重复项来完成: 所以,试试这个:

from collections import OrderedDict
import numpy as np
a = np.array([1, 1, 1, 2, 2, 2])
b = np.array([10, 10, 10, 20, 20, 20])

a=list(OrderedDict.fromkeys(a))
b=list(OrderedDict.fromkeys(b))  
print(b)  

如果你在 b 中有不同的元素,那么使用这个

import pandas as pd
import numpy as np
a = np.array([1, 1, 1, 2, 2, 2])
b = np.array([10, 10, 10, 20, 20, 20])   
d = {}

for l, n in zip(a, b):
    d.setdefault(l, []).append(n)

for key in d:
    print key, sum(d[key])/len(d[key])

代码:https://onlinegdb.com/BJih3DplE

【讨论】:

  • 我不确定数据框选项是否比使用 numpy 数组操作更快?
  • 运行第二个。
猜你喜欢
  • 2011-12-04
  • 2016-05-22
  • 2020-06-10
  • 2016-02-15
  • 1970-01-01
  • 2021-05-30
  • 1970-01-01
  • 2013-01-14
  • 2019-09-27
相关资源
最近更新 更多