【问题标题】:Calculate percentage of count for a list of arrays计算数组列表的计数百分比
【发布时间】:2016-07-21 12:49:23
【问题描述】:

简单的问题,但我似乎无法让它工作。我想计算一个数字在数组列表中出现的百分比,并相应地输出这个百分比。 我有一个数组列表,如下所示:

import numpy as np

# Create some data   
listvalues = []

arr1 = np.array([0, 0, 2])
arr2 = np.array([1, 1, 2, 2])
arr3 = np.array([0, 2, 2])

listvalues.append(arr1)
listvalues.append(arr2)
listvalues.append(arr3)

listvalues
>[array([0, 0, 2]), array([1, 1, 2, 2]), array([0, 2, 2])]

现在我使用集合来计算出现次数,它返回一个集合列表。计数器:

import collections 

counter = []
for i in xrange(len(listvalues)):
    counter.append(collections.Counter(listvalues[i]))

counter
>[Counter({0: 2, 2: 1}), Counter({1: 2, 2: 2}), Counter({0: 1, 2: 2})]

我要查找的结果是一个包含 3 列的数组,分别表示值 0 到 2 和行的 len(listvalues)。每个单元格都应填充数组中该值的百分比:

# Result
66.66    0      33.33
0        50     50
33.33    0      66.66

所以 0 在数组 1 中出现 66.66%,在数组 2 中出现 0%,在数组 3 中出现 33.33%,依此类推..

实现这一目标的最佳方法是什么? 非常感谢!

【问题讨论】:

    标签: python arrays list numpy


    【解决方案1】:

    这是一种方法 -

    # Get lengths of each element in input list
    lens = np.array([len(item) for item in listvalues])
    
    # Form group ID array to ID elements in flattened listvalues
    ID_arr = np.repeat(np.arange(len(lens)),lens)
    
    # Extract all values & considering each row as an indexing perform counting
    vals = np.concatenate(listvalues)
    out_shp = [ID_arr.max()+1,vals.max()+1]
    counts = np.bincount(ID_arr*out_shp[1] + vals)
    
    # Finally get the percentages with dividing by group counts
    out = 100*np.true_divide(counts.reshape(out_shp),lens[:,None])
    

    在输入列表中使用额外的第四个数组运行示例 -

    In [316]: listvalues
    Out[316]: [array([0, 0, 2]),array([1, 1, 2, 2]),array([0, 2, 2]),array([4, 0, 1])]
    
    In [317]: print out
    [[ 66.66666667   0.          33.33333333   0.           0.        ]
     [  0.          50.          50.           0.           0.        ]
     [ 33.33333333   0.          66.66666667   0.           0.        ]
     [ 33.33333333  33.33333333   0.           0.          33.33333333]]
    

    【讨论】:

    • 完美运行,速度很快!感谢您的回答,非常感谢。
    【解决方案2】:

    numpy_indexed 包为此提供了一个实用函数,称为 count_table,可用于有效解决您的问题:

    import numpy_indexed as npi
    arrs = [arr1, arr2, arr3]
    idx = [np.ones(len(a))*i for i, a in enumerate(arrs)]
    (rows, cols), table = npi.count_table(np.concatenate(idx), np.concatenate(arrs))
    table = table / table.sum(axis=1, keepdims=True)
    print(table * 100)
    

    【讨论】:

    • 谢谢!我喜欢你快速而优雅的解决方案,但是我得到的结果只是 0 和 1,而不是实际的百分比。我尝试了整数和浮点数组作为输入,但结果是一样的。有什么解决办法吗?
    • 在我的机器上工作;赢得 py35 numpy 1.10。确保在划分之前转换为浮动,无论平台如何都应该解决它
    • 没错,我使用浮点数作为输入(数组),但忘记将表格转换为浮点数。现在工作得很好,谢谢!
    【解决方案3】:

    您可以获取所有值的列表,然后简单地遍历各个数组以获得百分比:

    values = set([y for row in listvalues for y in row]) print [[(a==x).sum()*100.0/len(a) for x in values] for a in listvalues]

    【讨论】:

      【解决方案4】:

      您可以使用以下代码创建一个包含百分比的列表:

      percentage_list = [((counter[i].get(j) if counter[i].get(j) else 0)*10000)//len(listvalues[i])/100.0 for i in range(len(listvalues)) for j in range(3)]
      

      之后,从该列表创建一个 np 数组:

      results = np.array(percentage_list)
      

      重塑它,这样我们就有了好的结果:

      results = results.reshape(3,3)
      

      这应该可以让你得到你想要的。
      这很可能效率不高,也不是最好的方法,但它具有工作的优点。

      如果您有任何问题,请不要犹豫。

      【讨论】:

      • 感谢您的解决方案!但是输出似乎不正确。在我的示例中,我得到的值为 266
      • 你在使用 python2.x 吗?使用 Python3.4.2,我得到 array([[ 66.66, 0. , 33.33],[ 0. , 50. , 50. ],[ 33.33, 0. , 66.66]]) 的结果值
      • 我确实在使用 python2.x。这是我的百分比列表输出:[33, 0, 0, 0, 0, 75, 166, 0, 266, 33, 0, 33, 25, 0, 50, 100, 0, 33]。是因为python2.x吗?
      • 好吧,使用 python 2.7.9,我得到[66, 0, 33, 0, 50, 50, 33, 0, 66] 作为percentage_list 的输出。在 python 2.x 中,int 除法的结果始终是 int,而在 python 3.x 中它可以是浮点数(删除逗号后的所有内容)。除以100.0 而不是100 可以绕过这个。
      【解决方案5】:

      我想使用功能范式来解决这个问题。例如:

      >>> import numpy as np
      >>> import pprint
      >>> 
      >>> arr1 = np.array([0, 0, 2])
      >>> arr2 = np.array([1, 1, 2, 2])
      >>> arr3 = np.array([0, 2, 2])
      >>> 
      >>> arrays = (arr1, arr2, arr3)
      >>> 
      >>> u = np.unique(np.hstack(arrays))
      >>> 
      >>> result = [[1.0 * c.get(uk, 0) / l
      ...            for l, c in ((len(arr), dict(zip(*np.unique(arr, return_counts=True))))
      ...            for arr in arrays)] for uk in u]
      >>> 
      >>> pprint.pprint(result)
      [[0.6666666666666666, 0.0, 0.3333333333333333],
       [0.0, 0.5, 0.0],
       [0.3333333333333333, 0.5, 0.6666666666666666]]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-03-09
        • 1970-01-01
        • 2014-01-29
        • 2013-11-14
        • 1970-01-01
        • 1970-01-01
        • 2013-12-27
        相关资源
        最近更新 更多