この配列を最初の列で下にグループ化する関数は 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) であることに注目してください。