【问题标题】:calculate duplicate average python计算重复平均python
【发布时间】:2016-05-22 12:59:40
【问题描述】:

我有一个二维数组:

 [[2,1],[2,32],[4,4512],[1,34],[2,323],[2,42],[1,23],[4,123]...]

最后,我想计算平均值并得到数组,如 [ [1,mean],[2,mean],[3,mean]...],

谁有好的解决方案?我用过:

for i in range(len(array)):
    temp =[]
    for j in range(len(array)):
        if Table[i][0] == Table[j][0]:
                temp.append(Table[j])

然后计算temp的平均值,但效率不高。

有没有人有使用pandas 库的解决方案?

【问题讨论】:

  • 你能在[ [1,mean],[2,mean],[3,mean]..] 中给出mean 的值吗?
  • @Slslam like [1,(34+23)/2],[2,(1+32+323+42)/4,...] 来自当前示例数组

标签: python arrays python-2.7 pandas


【解决方案1】:

你可以使用函数式风格来解决这个问题

data = [[1, 2], [2, 3], [1, 4], [2, 5], ...]

def make_filter(n):
  def filter_n(d):
    return d[0] == n
  return filter_n

def calculate(n, data):
  data_n = filter(make_filter(n), data)
  s = reduce(lambda acc, d: acc + d[1], data_n, 0)
  n = len(data_n)
  if n > 0:
    return float(s) / n
  else:
    raise Exception

然后您调用calculate 函数并应将Exception 替换为合适的函数。

【讨论】:

    【解决方案2】:

    使用 pandas 和 groupby:

    df = pd.DataFrame([[2,1],[2,32],[4,4512],[1,34],[2,323],[2,42],[1,23],[4,123]])
    df.groupby(0).mean()
    
            1
    0        
    1    28.5
    2    99.5
    4  2317.5
    

    【讨论】:

    • 但这会返回一个pandas变量,如何将它分配回numpy变量
    【解决方案3】:

    编辑:将reduce替换为sum

    您可以使用内置的 map 和 reduce 函数:

    from __future__ import division
    array = [[2,1],[2,32],[4,4512],[1,34],[2,323],[2,42],[1,23],[4,123]]
    d = dict()
    l = list() # result
    map(lambda i:(d.setdefault(i[0],[]).append(i[1])), array)
    map(lambda key: l.append([key, sum(d[key])/len(d[key])]), d.iterkeys())
    print(l)
    

    你会得到:

    [[1, 28.5], [2, 99.5], [4, 2317.5]]
    

    说明: 首先,您必须按键对所有值进行分组(在您的情况下,键是嵌套数组的第一个值)。 其次,您必须计算平均值并创建结果数组。

    【讨论】:

    • 您不应该使用map 来获得副作用!这段代码不适用于Python 3,因为map 是一个生成器,而那些lambdas 只有在生成器被消耗后才会执行。而不是第一个map,一个常规的for 循环会更好。对于第二个map,只需使用列表理解创建l。此外,reduce 可以替换为 sum
    • 是的,你对 Python 3 的看法是对的,但是这个问题有 python-2.7 标签。
    • 好吧,使用map 处理副作用并丢弃实际结果仍然是不好的做法。为什么不直接使用结果? l = map(lambda key: [key, sum(d[key])/len(d[key])], d) 或作为列表理解:l = [[key, sum(d[key])/len(d[key])] for key in d]
    【解决方案4】:

    您可以尝试Counterdefaultdict 以获得更快的性能,如下所示-

    from collections import Counter,defaultdict
    
    sm = defaultdict(float)
    
    data = [[2,1],[2,32],[4,4512],[1,34],[2,323],[2,42],[1,23],[4,123]]
    
    #generate sum of second elements for all the keys (first elements)
    for i in data:
        sm[i[0]]+=i[1]
    
    #Count the occurrances of the keys (first occurrances)
    c = Counter([i[0] for i in data])
    
    #Produce data
    print [[k,sm[k]/c[k]]for k in sm.keys()]
    

    输出-

    [[1, 28.5], [2, 99.5], [4, 2317.5]]
    

    【讨论】:

      【解决方案5】:

      您应该创建一个字典,收集每个键(第一项)的所有值(第二项)。然后,您可以计算字典中每个条目的平均值。

      from __future__ import division # use floating-point division by default
      values = [[2,1],[2,32],[4,4512],[1,34],[2,323],[2,42],[1,23],[4,123]]
      
      values_by_key = collections.defaultdict(list)
      for k, v in values:
          values_by_key[k].append(v)
      means = sorted([(k, sum(v) / len(v)) for k, v in values_by_key.items()])
      

      或者,您可以使用groupby 对具有相同键的项目进行分组(记得先排序)并使用(有些复杂的)嵌套列表推导。

      means = [(k, sum(v)/len(v)) 
               for k, v in ((k, [v[1] for v in vals]) 
                            for k, vals in itertools.groupby(sorted(values), key=lambda t: t[0]))]
      

      在这两种情况下,means 都以 [(1, 28.5), (2, 99.5), (4, 2317.5)] 结尾。复杂度应该是 O(nlogn) (用于排序;如果不需要排序输出,那么使用 dict 的第一种方法的复杂度只是 O(n) )。

      就个人而言,我会采用字典方法。虽然另一个可以在“一行”中完成,但 dict 更清晰也更快(即使需要排序,因为在这种情况下排序是在合并之后完成的,即使用更少的元素)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-01-10
        • 1970-01-01
        • 2020-05-05
        • 2014-04-20
        • 2015-11-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多