功能上有没有numpy组?

时间:2016-06-24 12:45:15

标签: python arrays numpy

numpy中是否有任何函数可以将第一列下面的数组分组?

我在互联网上找不到任何好的答案..

>>> a
array([[  1, 275],
       [  1, 441],
       [  1, 494],
       [  1, 593],
       [  2, 679],
       [  2, 533],
       [  2, 686],
       [  3, 559],
       [  3, 219],
       [  3, 455],
       [  4, 605],
       [  4, 468],
       [  4, 692],
       [  4, 613]])

通缉输出:

array([[[275, 441, 494, 593]],
       [[679, 533, 686]],
       [[559, 219, 455]],
       [[605, 468, 692, 613]]], dtype=object)

9 个答案:

答案 0 :(得分:12)

受到Eelco Hoogendoorn图书馆的启发,但没有他的库,并且使用了阵列的第一列总是在不断增加的事实。

>>> np.split(a[:, 1], np.cumsum(np.unique(a[:, 0], return_counts=True)[1])[:-1])
[array([275, 441, 494, 593]),
 array([679, 533, 686]),
 array([559, 219, 455]),
 array([605, 468, 692, 613])]

我没有“timeit”,但这可能是解决问题的更快方式:

  • 没有python原生循环
  • 结果列表是numpy数组,如果你需要对它们进行其他numpy操作,则不需要新的转换
  • 复杂性如O(n)
PS:我写过类似的一行,因为我需要“分组”np.nonzero的结果:

>>> indexes, values = np.nonzero(...)
>>> np.split(values, np.cumsum(np.unique(indexes, return_counts=True)[1]))

答案 1 :(得分:12)

Numpy在这里不是很方便,因为所需的输出不是整数数组(它是一个列表对象数组)。

我建议使用纯Python方式......

from collections import defaultdict

%%timeit
d = defaultdict(list)
for key, val in a:
    d[key].append(val)
10.7 µs ± 156 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

# result:
defaultdict(list,
        {1: [275, 441, 494, 593],
         2: [679, 533, 686],
         3: [559, 219, 455],
         4: [605, 468, 692, 613]})

......或者是熊猫的方式:

import pandas as pd

%%timeit
df = pd.DataFrame(a, columns=["key", "val"])
df.groupby("key").val.apply(pd.Series.tolist)
979 µs ± 3.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

# result:
key
1    [275, 441, 494, 593]
2         [679, 533, 686]
3         [559, 219, 455]
4    [605, 468, 692, 613]
Name: val, dtype: object

答案 2 :(得分:10)

numpy_indexed包(免责声明:我是它的作者)旨在填补这个差距。 numpy-indexed中的所有操作都是完全矢量化的,并且在制作这个库时没有O(n ^ 2)算法受到损害。

import numpy_indexed as npi
npi.group_by(a[:, 0]).split(a[:, 1])

请注意,直接计算这些组的相关属性(即group_by(keys).mean(values))通常更有效,而不是先拆分成列表/锯齿状数组。

答案 3 :(得分:5)

n = unique(a[:,0])
array( [ list(a[a[:,0]==i,1]) for i in n] )

输出:

array([[275, 441, 494, 593], [679, 533, 686], [559, 219, 455],
       [605, 468, 692, 613]], dtype=object)

答案 4 :(得分:5)

简化answer of Vincent J可以使用return_index = True代替return_counts = True并摆脱cumsum

np.split(a[:,1], np.unique(idx,return_index = True)[1][1:])

输出

[array([275, 441, 494, 593]),
 array([679, 533, 686]),
 array([559, 219, 455]),
 array([605, 468, 692, 613])]

答案 5 :(得分:0)

我使用了np.unique(),后跟np.extract()

unique = np.unique(a[:, 0:1])
answer = []
for element in unique:
    present = a[:,0]==element
    answer.append(np.extract(present,a[:,-1]))
print (answer)

[array([275, 441, 494, 593]), array([679, 533, 686]), array([559, 219, 455]), array([605, 468, 692, 613])]

答案 6 :(得分:0)

将X表示为要分组的项目数组,将y(一维数组)作为相应的分组,以下功能使用 numpy 进行分组:

def groupby(X, y):
    y = np.asarray(y)
    X = np.asarray(X)
    y_uniques = np.unique(y)
    return [X[y==yi] for yi in y_uniques]

因此,groupby(a[:,1], a[:,0])返回 [array([275, 441, 494, 593]), array([679, 533, 686]), array([559, 219, 455]), array([605, 468, 692, 613])]

答案 7 :(得分:0)

我们可能还会发现生成dict很有用:

def groupby(X): 
    X = np.asarray(X) 
    x_uniques = np.unique(X) 
    return {xi:X[X==xi] for xi in x_uniques} 

让我们尝试一下:

X=[1,1,2,2,3,3,3,3,4,5,6,7,7,8,9,9,1,1,1]
groupby(X)                                                                                                      
Out[9]: 
{1: array([1, 1, 1, 1, 1]),
 2: array([2, 2]),
 3: array([3, 3, 3, 3]),
 4: array([4]),
 5: array([5]),
 6: array([6]),
 7: array([7, 7]),
 8: array([8]),
 9: array([9, 9])}

请注意,这本身并不是超级引人注目的内容-但是,如果我们将X设为objectnamedtuple,然后提供groupby函数,它将变得更加有趣。以后再放。

答案 8 :(得分:0)

聚会迟到了,但无论如何。如果您不仅打算对数组进行分组,而且还想对它们进行求和、均值等运算,并且考虑到速度,那么您可能还需要考虑 numpy_groupies。所有这些组操作都使用 numba 进行了优化和抖动。它们很容易胜过其他提到的解决方案。

from numpy_groupies.aggregate_numpy import aggregate
aggregate(a[:,0], a[:,1], "array", fill_value=[])
>>> array([array([], dtype=int64), array([275, 441, 494, 593]),
           array([679, 533, 686]), array([559, 219, 455]),
           array([605, 468, 692, 613])], dtype=object)
aggregate(a[:,0], a[:,1], "sum")
>>> array([   0, 1803, 1898, 1233, 2378])