代码之家  ›  专栏  ›  技术社区  ›  horcle_buzz

如何在多个1-d numpy数组中的元素之间采用模式

  •  0
  • horcle_buzz  · 技术社区  · 4 年前

    我能够按以下方式逐元素计算多个列表/数组的总和

    sum([np.array([1,2,3,4,5]), np.array([1,2,3,4,5])]) = array([ 2,  4,  6,  8, 10])
    

    mode([np.array([1,2,3,4,5]), np.array([1,2,3,4,5])]) = array([ 1, 2, 3, 4, 5] )

    mode([np.array([0,2,3,4,0]), np.array([1,2,9,4,5])]) = array([ 1, 2, 9, 4, 0]

    最后,我希望能够跨任意数量的等长数组执行此操作。

    注意:我尝试使用统计库模式,但出现以下错误:

    >>> mode([np.array([1,2,3,4,5]), np.array([1,2,3,4,5])])
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/anaconda3/lib/python3.7/statistics.py", line 501, in mode
        table = _counts(data)
      File "/anaconda3/lib/python3.7/statistics.py", line 252, in _counts
        table = collections.Counter(iter(data)).most_common()
      File "/anaconda3/lib/python3.7/collections/__init__.py", line 566, in __init__
        self.update(*args, **kwds)
      File "/anaconda3/lib/python3.7/collections/__init__.py", line 653, in update
        _count_elements(self, iterable)
    TypeError: unhashable type: 'numpy.ndarray'
    

    因此,我正在寻找实现这一目标的方法。

    1 回复  |  直到 4 年前
        1
  •  2
  •   jkr    4 年前

    您可以使用 scipy.stats.mode . 您还可以将多个numpy数组连接到单个数组中,然后将其馈送到模式。

    import numpy as np
    import scipy.stats
    
    arrays = [np.array([0,2,3,4,0]), np.array([1,2,9,4,5])]
    
    result = scipy.stats.mode(np.concatenate(arrays))
    # ModeResult(mode=array([0]), count=array([2]))
    
    result.mode
    # array([0])
    

    的返回值 希皮。统计数据。模式 这是一对夫妇 ModeResult

    arrays = [
        np.array([0, 2, 3, 4, 0]), 
        np.array([1, 2, 9, 4, 5]), 
        np.array([0, 9, 9, 4, 1])]
    result = scipy.stats.mode(np.stack(arrays), axis=0)
    result.mode
    # array([[0, 2, 9, 4, 0]])
    
        2
  •  1
  •   hpaulj    4 年前

    举两个例子:

    In [358]: alist = [np.array([1,2,3,4,5]), np.array([1,2,3,4,5])]                        
    In [359]: alist1 = [np.array([0,2,3,4,0]), np.array([1,2,9,4,5])]                       
    

    In [360]: import statistics                                                             
    In [361]: from scipy import stats                                                       
    

    具有 zip(*alist) 我们可以采取相应的“配对”模式:

    In [362]: [statistics.mode(foo) for foo in zip(*alist)]                                 
    Out[362]: [1, 2, 3, 4, 5]
    In [363]: [statistics.mode(foo) for foo in zip(*alist1)]                                
    ....
    StatisticsError: no unique mode; found 2 equally common values
    

    mode docs警告此错误。

    这个 scipy 版本将列表转换为2d数组;哪一个

    In [365]: stats.mode(alist,axis=0)                                                      
    Out[365]: ModeResult(mode=array([[1, 2, 3, 4, 5]]), count=array([[2, 2, 2, 2, 2]]))
    In [366]: stats.mode(alist1,axis=0)                                                     
    Out[366]: ModeResult(mode=array([[0, 2, 3, 4, 0]]), count=array([[1, 2, 1, 2, 1]]))
    In [367]: np.array(alist1)                                                              
    Out[367]: 
    array([[0, 2, 3, 4, 0],
           [1, 2, 9, 4, 5]])
    

    stats.mode 代码是Python,因此可以对其进行研究。对于这样的轴选择,它显然会在列上迭代,在每个列上采用1d模式。因此,速度将与列表理解情况相当。但是如何处理呢 StatsError 情况不同。

    但我们可以使用一点实用功能来处理错误情况:

    In [375]: def myfn(foo): 
         ...:     try: 
         ...:         return statistics.mode(foo) 
         ...:     except statistics.StatisticsError: 
         ...:         return None # or a random value 
         ...:                                                                               
    In [376]: [myfn(foo) for foo in zip(*alist)]                                            
    Out[376]: [1, 2, 3, 4, 5]
    In [377]: [myfn(foo) for foo in zip(*alist1)]                                           
    Out[377]: [None, 2, None, 4, None]
    

    列表理解时间是有利的:

    In [378]: timeit [myfn(foo) for foo in zip(*alist1)]                                    
    73.6 µs ± 278 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
    In [379]: timeit stats.mode(alist1,axis=0)                                              
    384 µs ± 1.09 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)