質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
ソート

複数のデータを、順序性に従って並べ替えること。 データ処理を行う際に頻繁に用いられ、多くのアルゴリズムが存在します。速度、容量、複雑さなどに違いがあり、高速性に特化したものにクイックソートがあります。

データ構造

データ構造とは、データの集まりをコンピュータの中で効果的に扱うために、一定の形式に系統立てて格納する形式を指します。(配列/連想配列/木構造など)

コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

3回答

1623閲覧

python 配列 高速ソート

bobslay

総合スコア32

ソート

複数のデータを、順序性に従って並べ替えること。 データ処理を行う際に頻繁に用いられ、多くのアルゴリズムが存在します。速度、容量、複雑さなどに違いがあり、高速性に特化したものにクイックソートがあります。

データ構造

データ構造とは、データの集まりをコンピュータの中で効果的に扱うために、一定の形式に系統立てて格納する形式を指します。(配列/連想配列/木構造など)

コードレビュー

コードレビューは、ソフトウェア開発の一工程で、 ソースコードの検査を行い、開発工程で見過ごされた誤りを検出する事で、 ソフトウェア品質を高めるためのものです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

0クリップ

投稿2021/10/11 03:45

次のような配列xがあり(実際に使用するデータはもっと大きい),そのデータから次のソースコードで得られる結果resul1,result2を得たいです.実際のデータにおいても配列x[0],x[1]...はそれぞれソートされているものとします.
得たい結果は

  • xの全要素をソートした結果のうち5以下のものからなる配列result1
  • result1の要素がxの何番目の要素であったかを表す配列result2

です.

次のソースコードを用いても欲しい結果は得られますが,扱うデータが巨大なため,実行に時間がかかりすぎてしまいます.
リスト内包表記を用いる方法など,何か高速な方法はありますでしょうか?

扱うデータ

python

1import numpy as np 2 3a = np.array([1, 2.3, 3.1, 4.6, 6.7]) 4b = np.array([2.3, 4.2]) 5c = np.array([]) 6d = np.array([2.5, 3.2, 4.3, 4.4, 4.8, 5.0]) 7x = [a, b, c, d]

自作コード

python

1import numpy as np 2 3result1 = [] 4result2 = [] 5append1 = result1.append 6append2 = result2.append 7 8while True: 9 value = 6 10 for i in range(len(x)): 11 if x[i].size and value > x[i][0]: 12 value = x[i][0] 13 index = i 14 15 if value > 5: 16 break 17 18 append1(value) 19 append2(index) 20 x[index] = np.delete(x[index], 0)

自作コードで得られる結果かつ得たい結果
result1=[1.0, 2.3, 2.3, 2.5, 3.1, 3.2, 4.2, 4.3, 4.4, 4.6, 4.8, 5.0]
result2=[0, 0, 1, 3, 0, 3, 1, 3, 3, 0, 3, 3]

以前にも似たような質問をさせていただきましたが,xのそれぞれの要素x[0],x[1]...がソート済みであると明示せずに,質問させていただいたので,ソート済みであればより早い方法があるのではないかと思い質問させていただきました.

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

データ量が10**6程度までであれば、過去のやりとりで出てきているnumpy.argsortで十分高速だと思います。

python

1import numpy as np 2 3# オリジナル 4def solve1(x): 5 result1 = [] 6 result2 = [] 7 append1 = result1.append 8 append2 = result2.append 9 10 while True: 11 value = 6 12 for i in range(len(x)): 13 if x[i].size and value > x[i][0]: 14 value = x[i][0] 15 index = i 16 if value > 5: 17 break 18 19 append1(value) 20 append2(index) 21 x[index] = np.delete(x[index], 0) 22 return result1, result2 23 24# numpy.argsort()使用 25def solve2(x, limit=5.0): 26 x = [arr[:np.searchsorted(arr, limit, side='right')] for arr in x] 27 result1 = np.concatenate(x) 28 result2 = np.concatenate([np.full(arr.size, i) for i, arr in enumerate(x)]) 29 idx = np.argsort(result1, kind='mergesort') 30 return result1[idx], result2[idx] 31 32 33np.random.seed(123) 34size = 10**5 # テスト用のデータサイズ 35a = np.sort(np.random.rand(size) * 10) 36b = np.sort(np.random.rand(size) * 10) 37c = np.sort(np.random.rand(size) * 10) 38d = np.sort(np.random.rand(size) * 10) 39 40x = [a, b, c, d] 41r11, r12 = solve1(x) 42 43x = [a, b, c, d] 44r21, r22 = solve2(x) 45 46print(r11 == r21.tolist() and r12 == r22.tolist()) # 結果が同じかチェック

投稿2021/10/11 13:56

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

bobslay

2021/10/12 05:42

ご回答ありがとうございます. 実際に使用したいデータを見たところ,サイズが10^10ほどでした. そもそもデータ量が大きすぎてこれ以上高速に実行できないのではないかと思ってきました...
退会済みユーザー

退会済みユーザー

2021/10/12 06:31

10^10は大きいですね。確認ですが、お使いのマシンでは10^10のデータでもオンメモリで処理できるだけのRAMを搭載しているんですよね? 私の環境(RAM 32GB)だと size=10**8で処理時間が4.5秒、size=5*10**8で144秒(ただしRAM不足でスワップ発生)でした。データサイズを少しずつ大きくしながら試してみてはどうでしょうか。
guest

0

投稿2021/10/11 06:34

coffeebar

総合スコア140

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

bobslay

2021/10/11 10:54

ご回答ありがとうございます. 並列化について勉強してみようと思います.
bobslay

2021/10/12 12:30

複数のデータを引数として,同じ関数を何度も呼び出すような処理に対して並列化は有効であるようでしたが,すべてのデータに対してソートを行いたい場合には,うまく並列化する方法は見つかりませんでした. (データを分割し,それぞれについてソートした後に全体についてソートしていくマージソートのようなことをすると高速化可能?)
guest

0

実際のデータ量が不明ですが、以下で実用的な速度は出ないでしょうか?
各リストがソート済みであることを生かして、itertools.takewhileにて値の抽出とマージソートを利用しています。

Python

1import numpy as np 2from heapq import merge 3import itertools 4 5a = np.array([1, 2.3, 3.1, 4.6, 6.7]) 6b = np.array([2.3, 4.2]) 7c = np.array([]) 8d = np.array([2.5, 3.2, 4.3, 4.4, 4.8, 5.0]) 9x = [a, b, c, d] 10 11#x = [np.sort(np.random.random((100,)))*10 for _ in range(100)] 12 13l = [[(v, i) for v in itertools.takewhile( lambda e : e <= 5, ary)] for i, ary in enumerate(x)] 14r1, r2 = itertools.tee(merge(*l)) # ソート済みを生かしてマージソートする 15result1 = [e[0] for e in r1] 16result2 = [e[1] for e in r2] 17 18print(result1)# [1.0, 2.3, 2.3, 2.5, 3.1, 3.2, 4.2, 4.3, 4.4, 4.6, 4.8, 5.0] 19print(result2)# [0, 0, 1, 3, 0, 3, 1, 3, 3, 0, 3, 3]

投稿2021/10/11 04:32

編集2021/10/11 09:14
can110

総合スコア38341

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

bobslay

2021/10/12 05:41

ご回答ありがとうございます. 実際に使用したいデータを見たところ,サイズが10^10ほどでした. そもそもデータ量が大きすぎてこれ以上高速に実行できないのではないかと思ってきました...
can110

2021/10/12 08:51

そのサイズだと私の回答の「l = [[(v, i) for v in」での値とインデックスの組を作る部分で、すでに時間がかかりすぎてしまいますね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問