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

将numpy数组分解为具有相同值的较小数组[python]

  •  2
  • listener  · 技术社区  · 6 年前

    我有以下numpy数组:

    array=[1,1,1,1,2,2,3,3,3,5,6,6,6,6,6,6,7]
    

    我需要将这个数组分解为具有相同值的较小数组,例如

    [1,1,1,1] and [3,3,3]
    

    我的代码如下,但不起作用:

    def chunker(seq, size):
        return (seq[pos:pos + size] for pos in range(0, len(seq)-size))
    counter=0
    sub_arr=[]
    arr=[]
    for i in range(len(array)):
        if(array[i]==array[i+1]):
            counter+=1
        else:
            break
            subarr=chunker(array,counter)
        arr.append(sub_arr)
        array=array[counter:]
    

    将数组分解为相等/相同值的较小数组的效率是什么?

    3 回复  |  直到 6 年前
        1
  •  3
  •   Mr. T Andres Pinzon    6 年前

    浮点数和整数的numpy解决方案:

    import numpy as np
    a = np.asarray([1,1,1,1,2,2,3,3,3,5,6,6,6,6,6,6,7])
    #calculate differences between neighbouring elements and get index where element changes
    #sample output for index would be [ 4  6  9 10 16]
    index = np.where(np.diff(a) != 0)[0] + 1
    #separate arrays
    print(np.split(a, index))
    

    样品输出:

    [array([1, 1, 1, 1]), array([2, 2]), array([3, 3, 3]), array([5]), array([6, 6, 6, 6, 6, 6]), array([7])]
    

    如果您有字符串,这个方法自然不会工作。那你应该和DYZ一起去 itertools 接近。

        2
  •  2
  •   DYZ    6 年前

    numpy对这种分组的支持很差。我建议使用 itertools 按列表操作。

    from itertools import groupby
    [np.array(list(data)) for _,data in itertools.groupby(array)]
    #[array([1, 1, 1, 1]), array([2, 2]), array([3, 3, 3]), \
    # array([5]), array([6, 6, 6, 6, 6, 6]), array([7])]
    

    这不一定是最有效的方法,因为它涉及到与列表之间的转换。

        3
  •  0
  •   andrew_reece    6 年前

    以下是使用熊猫的方法:

    import pandas as pd 
    
    (pd.Series(array)
       .value_counts()
       .reset_index()
       .apply(lambda x: [x["index"]] * x[0], axis=1))  
    

    说明:
    首先,转换 array 到一个系列,并使用 value_counts() 要获取每个唯一条目的计数:

    counts = pd.Series(array).value_counts().reset_index()
       index  0
    0      6  6
    1      1  4
    2      3  3
    3      2  2
    4      7  1
    5      5  1
    

    然后重新创建每个重复的元素列表,使用 apply() :

    counts.apply(lambda x: [x["index"]] * x[0], axis=1)
    
    0    [6, 6, 6, 6, 6, 6]
    1          [1, 1, 1, 1]
    2             [3, 3, 3]
    3                [2, 2]
    4                   [7]
    5                   [5]
    dtype: object
    

    您可以使用 .values 属性从一系列列表转换为列表列表列表(如果需要)。