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

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

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

NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

並列処理

複数の計算が同時に実行される手法

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

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

pandas

Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

Q&A

2回答

1056閲覧

並列処理の偏りを防ぎつつ、任意の数でハッシュをバケット分割できるキー名を求める方法

y-ken

総合スコア1

NumPy

NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

並列処理

複数の計算が同時に実行される手法

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Python

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

pandas

Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

0グッド

0クリップ

投稿2021/09/28 15:48

編集2021/09/28 23:25

背景・実現したいこと

並列計算を行うために、偏りが少ない形で分割処理するための前処理が行えるPython3での記述方法を探しています。

下記の入出力データ例と共に、どのような処理を行いたいかの説明をさせてください。

######入出力データ例

configの中に、aaa, bbb, cccという添え字があり、aaaの中には4つ、bbbには1つ、cccには3つ要素があります。
concurrency_limit=2ということで、単純に2つに分割すると [['aaa','bbb'],['ccc']]となります。
これではaaaとbbbの要素数は4+1=5、もう一方のcccの要素数は3となり、偏ってしまいます。

そうではなく、中の要素数を考慮した分割を行い、要素数の多い順に[['aaa'], ['ccc','bbb']]という結果を得られる方法が知りたく、お力添え頂けますでしょうか。
外部ライブラリを用いる方法も含めて探しております。

python

1# 入力パラメータ (この結果を用いて並列上限数として作用させるため、この名称です) 2concurrency_limit = 2 3 4# 入力データ例 (k:vの箇所はそれぞれ異なる計算したい内容が記されている想定です) 5config = { 6 'aaa': { 7 'aaa1': {'k': 'v'}, 8 'aaa2': {'k': 'v'}, 9 'aaa3': {'k': 'v'}, 10 'aaa4': {'k': 'v'}}, 11 'bbb': {'bbb1': {'k': 'v'}}, 12 'ccc': { 13 'ccc1': {'k': 'v'}, 14 'ccc2': {'k': 'v'}, 15 'ccc3': {'k': 'v'}} 16 } 17 18# 出力データ例 (できるならば要素の多い順に並んで欲しいが、[['aaa'], ['bbb','ccc']]という順番でも可です) 19[['aaa'], ['ccc','bbb']]

考えたこと

おそらく次のようなステップで行うのだろうと想像できたのですが、不勉強で記述方法が分かりませんでした。
もし、別の最適解を求められるスマートな手法があるとしたら、よりよい形での処理方法を学びたいです。

  1. 要素数を計算済のデータ構造を作り大きい順にソートする 'aaa':4, 'ccc':3, 'bbb':1
  2. concurrency_limit: Nのループで、新たに作ったハッシュ配列に先頭N件を格納する [{'item':['aaa'],'sum':4},{'item':['ccc'],'sum':3}]
  3. 2周目のループでcountが少ない順に残った要素を追記する [{'item':['aaa'],'sum':4},{'item':['ccc','bbb'],'sum':4}]
  4. itemの中身を出力する [['aaa'], ['ccc','bbb']]

検算として、 10, 7, 5, 4, 3, 2 という数列を2つに分割するとき、上記の方法だと次の分割となります。

  1. 1ループ目 [10], [7]
  2. 2ループ目 [10,4], [7,5]
  3. 3ループ目 [10,4,2], [7,5,3]

合計値が左辺は10+4+2=16、右辺は7+5+3=15となり、おおむね均等配分出来ていると確認ができました。

しかし、 [3, 3, 2, 2, 2] に対して同じ手法で2分割すると、3 + 2 + 2 = 73 + 2 = 5 となります。
最適解である 3 + 3 = 62 + 2 + 2 = 6 とは異なる事にppaulさんのご指摘で気づきました。

試してみたこと

1次元配列を指定の数に分割する時に numpy や pandas を使ったことがあったので、関連する関数を探しました。
しかし入力データの形式を変えたとしても要件に合う物がなさそうに思えました。

また、teratailやGoogleで 均等 配分 分割などのキーワードで探しましたが、見つけられませんでした。

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

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

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

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

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

ppaul

2021/09/28 22:20

次のようなステップの方法で[3, 3, 2, 2, 2]をやると、 3 + 2 + 2 = 7 と3 + 2 = 5 となりますね。 最適解は 3 + 3 = 6 と 2 + 2 + 2 = 6 ですが、最適解でなくても良いのですか?
y-ken

2021/09/28 23:20

素晴らしいご指摘ありがとうございます。 確かにおっしゃるとおりで、最適解である方がもちろん好ましいです。
y-ken

2021/09/29 00:36 編集

その誤差を埋めるためにコード量がとても増えてしまう場合には、多少の偏りは許容したいと考えてます
guest

回答2

0

また、teratailやGoogleで 均等 配分 分割などのキーワードで探しましたが、見つけられませんでした。

回答というか参考情報として。
問題としてはMultiway number partitioningに該当すると思います。

the problem of partitioning a multiset of numbers into a fixed number of subsets, such that the sums of the subsets are as similar as possible.

この問題はNP困難なのでconfigに含まれる要素数にもよりますが、厳密解ではなく近似解を求める手法をとるのが現実的かと思います。

投稿2021/09/29 00:42

can110

総合スコア38341

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

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

y-ken

2021/09/29 02:33

ありがとうございます。奥が深いのですね。 シンプルなアプローチで近似解を求める方向でサンプルを頂くことは出来ますでしょうか
can110

2021/09/29 03:58

シンプルなアプローチとしては ・最初に値リストを降順にソート ・リストの先頭から、値の合計の最も少ない箱に詰めていく といった感じでしょうか。 難しくないと思いますので、ご自身で実装できるかと思います。
y-ken

2021/09/29 07:53

ありがとうございます、拙いながらも実践してみました。コードレビューいただけると、嬉しいです。
guest

0

頂いた手法を元に、実装しました。
もし、こんな風に書いた方がもっと賢いですよ、というフィードバックございましたら、いただけると大変ありがたいです。

python

1from operator import itemgetter 2In [26]: groups = [[[], 0] for _ in range(concurrency_limit)] 3 ...: 4 ...: item_list = dict(sorted({category: len(config[category]) for category in config}.items(), key=lambda x:x[1 5 ...: ], reverse = True)) 6 ...: 7 ...: for item in item_list: 8 ...: print(f"item:{item} count:{item_list[item]}") 9 ...: smallest_group = min(groups, key=itemgetter(1)) 10 ...: smallest_group[0].append(item) 11 ...: smallest_group[1] += item_list[item] 12 ...: 13 ...: print([item[0] for item in groups]) 14item:aaa count:4 15item:ccc count:3 16item:bbb count:1 17[['aaa'], ['ccc', 'bbb']]

投稿2021/09/29 07:52

編集2021/09/29 08:22
y-ken

総合スコア1

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問