【问题标题】:How do I calculate the mean of elements in a list across columns?如何计算跨列列表中元素的平均值?
【发布时间】:2013-06-07 07:27:37
【问题描述】:

假设我有一个列表数组

B = [[1,2,3],[1,2,3,4],[1,2]]

我想计算列中列表中元素的平均值。我该怎么做?

即

如何获得一个等于最长列表的最终平均值数组:

[(1+1+1)/3,(2+2+2)/3,(3+3)/2,4/1] = [1,2,3,4]

我试过了:

final_array = np.array([mean(a) for a in zip(*(B))])

但这给了我一个数组,只要我的最短列表。这是口罩派上用场了吗?如果一系列列表让您感到畏缩,我深表歉意,我还在习惯 Python。

【问题讨论】:

    标签: python list numpy mean


    【解决方案1】:

    你可以使用熊猫的DataFrame。

    from pandas import DataFrame
    
    B = [[1,2,3],[1,2,3,4],[1,2]]
    df = DataFrame(B)
    df.mean(axis=0)
    """"
    df
       0  1   2   3
    0  1  2   3 NaN
    1  1  2   3   4
    2  1  2 NaN NaN
    
    df.mean(axis=0)
    0    1
    1    2
    2    3
    3    4
    """
    

    【讨论】:

      【解决方案2】:

      您需要用一些标记值(我使用 NaN)填充您的列表,然后使用该标记创建一个掩码数组。一旦有了掩码数组,就可以毫无问题地计算平均值。

      >>> import numpy as np
      >>> B = [[1,2,3],[1,2,3,4],[1,2]]
      >>> 
      >>> maxlen = max(len(x) for x in B)
      >>> C = np.array([l+[np.nan]*(maxlen-len(l)) for l in B])
      >>> C
      array([[  1.,   2.,   3.,  nan],
             [  1.,   2.,   3.,   4.],
             [  1.,   2.,  nan,  nan]])
      >>> dat = np.ma.fix_invalid(C)
      >>> np.mean(dat,axis=0)
      masked_array(data = [1.0 2.0 3.0 4.0],
                   mask = [False False False False],
             fill_value = 1e+20)
      

      【讨论】:

      • 有更好的方法来屏蔽NAN: np.ma.fix_invalid(C)
      【解决方案3】:

      另一种方式,使用cmp 和izip_longest

      from itertools import izip_longest
      [float(sum(col)) / sum(cmp(x,0) for x in col) for col in izip_longest(*B, fillvalue=0)]
      

      这假设你的价值观是积极的。

      【讨论】:

      • 注意 cmp 在 Python 3 中消失了
      • 如果您使用的是 Python 2.X,请将sum(col) 更改为float(sum(col)),或使用from __future__ import division,或进行其他更改以确保除法不是整数除法。否则,当值都是整数时,您通常会得到错误的答案。
      • @WarrenWeckesser 谢谢,很好。我已经更新了我的答案。
      【解决方案4】:

      使用itertools.izip_longest 和itertools.takewhile:

      >>> from itertools import takewhile, izip_longest
      def means(lis):
          fill = object()
          for item in izip_longest(*lis,fillvalue = fill):
              vals = list(takewhile( lambda x : x!=fill , item))
              yield sum(vals)/float(len(vals))
      ...         
      >>> lis = [[1,2,3],[1,2,3,4],[1,2]]
      >>> lis.sort( key = len, reverse = True) #reverse sort the list based on length of items
      >>> list(means(lis))
      [1.0, 2.0, 3.0, 4.0]
      

      【讨论】:

        【解决方案5】:

        你可以在没有任何外部库的情况下做到这一点:

        B = [[1,2,3],[1,2,3,4],[1,2]]
        #compute max length of sub list
        maxLen = max([len(x) for x in B])
        #new list with number of empty lists equals to number of columns
        transList = [[] for i in range(maxLen)]
        #transforming list to new structure
        for row in B:
            for col in row:
                transList[col-1].append(col)
        #transList = [[1, 1, 1], [2, 2, 2], [3, 3], [4]] from now one its simple to get mean of the elements ;)
        meanB = [float(sum(i))/len(i) for i in transList]
        

        【讨论】:

          【解决方案6】:
          B = [[1,2,3],[1,2,3,4],[1,2]]
          data = {}
          max_len = 0
          
          for alist in B:
              length = len(alist)
              max_len = length if (length > max_len) else max_len
          
              for i in range(length):
                  data.setdefault(i, []).append(alist[i])
          
          
          results = []
          
          for i in range(max_len):
              vals = data[i]
              results.append(sum(vals) / len(vals) )
          
          print results
          
          --output:--
          [1, 2, 3, 4]
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2018-06-21
            • 2021-12-03
            • 2018-03-19
            • 1970-01-01
            • 1970-01-01
            • 2021-09-29
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多