【问题标题】:Breaking down numpy array into smaller arrays of same value [Python]将 numpy 数组分解为具有相同值的较小数组 [Python]
【发布时间】:2018-07-10 15:27:35
【问题描述】:

我有以下 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:]

将数组分解为具有相等/相同值的较小数组的有效方法是什么?

【问题讨论】:

  • 你期待/关心像[1,1,2,2,1,1]这样的数组吗?你关心列表中子数组的顺序吗? (应该和原来的顺序一致吗?)

标签: python arrays


【解决方案1】:

浮点数和整数的 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】:

    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】:

      这是使用 Pandas 的一种方法:

      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 属性将一系列列表转换为列表列表。

      【讨论】:

      • 这仅适用于不重复值的范围(如 [1,1,2,2,1,1])。而且它不保留顺序。
      • @DyZ 不确定我是否在跟踪 - 你的意思是它只有在一系列值不重复的情况下才有效? OP 要求“具有相同值的较小数组”。在您的示例中,我的方法正确地将 1 列表和 2 列表分组。据我所知,OP 也没有要求保留订单。你能澄清一下吗?
      • 当我将您的方法应用于我的示例时,我得到两个范围:[1,1,1,1] 和 [2,2] - 而不是三个范围 [1,1], [2 ,2] 和 [1,1]。我不确定它对 OP 有多重要,只是说明这一点。
      • 啊,好吧-在您的示例中,我将 OP 的请求解释为需要两个范围,而不是三个。感谢您的澄清!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-01
      • 2012-04-12
      • 1970-01-01
      • 2021-07-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多