NumPyのグループ化関数はありますか? 質問する

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)

ベストアンサー1

に触発されたEelco Hoogendoorn のライブラリただし、ライブラリは使用せず、配列の最初の列は常に増加するという事実を使用します(そうでない場合は、最初に でソートしますa = a[a[:, 0].argsort()])。

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

私は「時間を計りませんでした」([編集]下記参照)が、これはおそらく質問を達成するためのより速い方法です:

  • Pythonネイティブループなし
  • 結果リストはNumPy配列なので、他のNumPy操作を行う必要がある場合でも、新たな変換は必要ありません。
  • 複雑さは O(n) のように見えます (ソートすると O(n log(n))

[2021 年 9 月編集] Macbook M1 で、10,000 個のランダムな整数のテーブルに対して timeit を実行しました。期間は 1000 回の呼び出しです。

>>> a = np.random.randint(5, size=(10000, 2))  # 5 different "groups"

# Only the sort
>>> a = a[a[:, 0].argsort()]
⏱ 116.9 ms

# Group by on the already sorted table
>>> np.split(a[:, 1], np.unique(a[:, 0], return_index=True)[1][1:])
⏱ 35.5 ms

# Total sort + groupby
>>> a = a[a[:, 0].argsort()]
>>> np.split(a[:, 1], np.unique(a[:, 0], return_index=True)[1][1:])
⏱ 153.0 ms ��

# With numpy-indexed package (cf Eelco answer)
>>> npi.group_by(a[:, 0]).split(a[:, 1])
⏱ 353.3 ms

# With pandas (cf Piotr answer)
>>> df = pd.DataFrame(a, columns=["key", "val"]) # no timer for this line
>>> df.groupby("key").val.apply(pd.Series.tolist) 
⏱ 362.3 ms

# With defaultdict, the python native way (cf Piotr answer)
>>> d = defaultdict(list)
for key, val in a:
    d[key].append(val)
⏱ 3543.2 ms

# With numpy_groupies (cf Michael answer)
>>> aggregate(a[:,0], a[:,1], "array", fill_value=[])
⏱ 376.4 ms

2 回目の timeit シナリオでは、5 つのグループではなく 500 の異なるグループを使用します。パンダについては驚きました。何度か実行しましたが、このシナリオでは動作が悪くなります。

>>> a = np.random.randint(500, size=(10000, 2))

just the sort  141.1 ms
already_sorted 392.0 ms
sort+groupby   542.4 ms
pandas        2695.8 ms
numpy-indexed  800.6 ms
defaultdict   3707.3 ms
numpy_groupies 836.7 ms

[編集] 回答を改善しました。ns63srの回答そしてベザド・シャイエグ(コメント参照)ありがとうTMBaileyargsort の複雑さは n log(n) であることに注目してください。

おすすめ記事