功能上有没有numpy组?

Joh*_*Dow 36 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]])
Run Code Online (Sandbox Code Playgroud)

通缉输出:

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

Vin*_*t J 16

灵感来自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])]
Run Code Online (Sandbox Code Playgroud)

我没有"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]))
Run Code Online (Sandbox Code Playgroud)

  • 如果您必须进行排序,如果项目尚未排序,复杂度是否会增加到 O(n log n) ? (2认同)

Eel*_*orn 15

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

import numpy_indexed as npi
npi.group_by(a[:, 0]).split(a[:, 1])
Run Code Online (Sandbox Code Playgroud)

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

  • 谢谢 。我的意思是,使用 On2 算法本质上是痛苦的,即使对于所述算法本身也是如此。但是,是的,我想你必须假设 On2 算法也能自我意识到它的自卑性,这样句子才有意义。 (2认同)

小智 13

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]})
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)


Gio*_*elm 7

n = np.unique(a[:,0])
np.array( [ list(a[a[:,0]==i,1]) for i in n] )
Run Code Online (Sandbox Code Playgroud)

输出:

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

  • 请注意,此解决方案需要O(n ^ 2)个运算,因此效率非常低。 (7认同)

小智 6

简化Vincent J答案,您可以使用return_index = True代替return_counts = True和摆脱cumsum

np.split(a[:,1], np.unique(idx,return_index = True)[1][1:])
Run Code Online (Sandbox Code Playgroud)

输出量

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