【问题标题】:Is there any pythonic way to find average of specific tuple elements in array?有没有任何pythonic方法可以找到数组中特定元组元素的平均值?
【发布时间】:2019-09-14 13:13:44
【问题描述】:

我想把这段代码写成pythonic。我的真实数组比这个例子大得多。

(5+10+20+3+2) / 5

print(np.mean(array,key=lambda x:x[1])) TypeError: mean() 得到了一个意外的关键字参数 'key'

array = [('a', 5) , ('b', 10), ('c', 20), ('d', 3), ('e', 2)]

sum = 0
for i in range(len(array)):
    sum = sum + array[i][1]

average = sum / len(array)
print(average)

import numpy as np
print(np.mean(array,key=lambda x:x[1]))

如何避免这种情况? 我想用第二个例子。

我正在使用 Python 3.7

【问题讨论】:

    标签: python arrays python-3.x tuples average


    【解决方案1】:

    你可以简单地使用:

    print(sum(tup[1] for tup in array) / len(array))
    

    或者对于 Python 2:

    print(sum(tup[1] for tup in array) / float(len(array)))
    

    或者对于 Python 2 来说更简洁一点:

    from math import fsum
    
    print(fsum(tup[1] for tup in array) / len(array))
    

    【讨论】:

    【解决方案2】:

    你可以使用map:

    np.mean(list(map(lambda x: x[1], array)))

    【讨论】:

      【解决方案3】:

      使用纯 Python:

      from operator import itemgetter
      
      acc = 0
      count = 0
      
      for value in map(itemgetter(1), array):
          acc += value
          count += 1
      
      mean = acc / count
      

      如果您的数据无法以list 的形式放入内存中(因为您说它很大),那么迭代方法可能更可取。如果可以的话,更喜欢声明式方法:

      data = [sub[1] for sub in array]
      mean = sum(data) / len(data)
      

      如果你愿意使用numpy,我觉得这个更干净:

      a = np.array(array)
      
      mean = a[:, 1].astype(int).mean()
      

      【讨论】:

        【解决方案4】:

        如果您使用的是 Python 3.4 或更高版本,则可以使用 statistics 模块:

        from statistics import mean
        
        average = mean(value[1] for value in array)
        

        或者,如果您使用的 Python 版本早于 3.4:

        average = sum(value[1] for value in array) / len(array)
        

        这些解决方案都使用了 Python 的一个很好的特性,称为生成器表达式。循环

        value[1] for value in array
        

        以一种及时且高效的方式创建一个新序列。见PEP 289 -- Generator Expressions

        如果您使用的是 Python 2,并且您正在对整数求和,我们将进行整数除法,这将截断结果,例如:

        >>> 25 / 4
        6
        
        >>> 25 / float(4)
        6.25
        

        为了确保我们没有整数除法,我们可以将sum 的起始值设置为float0.0。但是,这也意味着我们必须用括号明确生成器表达式,否则会出现语法错误,并且不太美观,如 cmets 中所述:

        average = sum((value[1] for value in array), 0.0) / len(array)
        

        最好使用math 模块中的fsum,它将返回float

        from math import fsum
        
        average = fsum(value[1] for value in array) / len(array)
        

        【讨论】:

        • 我意识到有更好的方法来编写 Python 2 代码。 sum 接受一个参数作为起始值。如果您将0.0 传递给它,那么分子将始终为浮点数,无需担心。另外,math 模块中有一个函数,fsum
        • 我会说float 转换方式比为sum 传递一个奇怪的0.0 值参数更容易解释。
        • @ruohola 我认为使用 fsum 可能最适合 Python 2。
        • 你不能from __future__ import division吗?
        • @DanielSank 是的,这是另一种选择。使用fsum 的另一个优点是,如果您对浮点数求和,它会跟踪部分和,从而弥补浮点表示中的精度不足。所以,如果我们继续使用fsum,我们根本不需要考虑整数除法,而且通常也是更好的解决方案。在c++ 中查看我对Kahan Summation 的回答。
        【解决方案5】:

        只需使用列表元素的总和和数量求平均值。

        array = [('a', 5) , ('b', 10), ('c', 20), ('d', 3), ('e', 2)]
        avg = float(sum(value[1] for value in array)) / float(len(array))
        print(avg)
        #8.0
        

        【讨论】:

          【解决方案6】:

          您可以使用map 代替列表理解

          sum(map(lambda x:int(x[1]), array)) / len(array)
          

          functools.reduce(如果您使用Python2.X,只需reduce 而不是functools.reduce

          import functools
          functools.reduce(lambda acc, y: acc + y[1], array, 0) / len(array)
          

          【讨论】:

          • 第一个给出这个错误:'int' object is not callable
          • @ŞevvalKahraman 如果数组的定义如您的问题所示 - 第一个给出 8.0(在同一版本上测试和验证)。所以要么你使用的数组在某处有不同的值,要么你打错了
          • x[1]已经是整数了,为什么还要调用int()
          • 使用 lambda 比生成器理解慢 30%。但如果你更喜欢map,我建议使用operator.itemgetter(1) 而不是lambda。
          • 类似地,functools.reduce 比生成器理解和 sum 慢 72%。
          【解决方案7】:

          如果您确实想使用 numpy,请将其转换为 numpy.array 并使用 numpy 索引选择您想要的轴:

          import numpy as np
          
          array = np.array([('a', 5) , ('b', 10), ('c', 20), ('d', 3), ('e', 2)])
          print(array[:,1].astype(float).mean())
          # 8.0
          

          需要转换为数字类型,因为原始数组包含字符串和数字,因此类型为 object。在这种情况下,您可以使用floatint,没有区别。

          【讨论】:

            【解决方案8】:

            如果您愿意接受更多类似高尔夫的解决方案,您可以使用 vanilla python 转置您的数组,获取仅包含数字的列表,然后计算平均值

            sum(zip(*array)[1])/len(array)
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2013-12-29
              • 2019-02-19
              • 2020-09-25
              • 1970-01-01
              • 2016-01-04
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多