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

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

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

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

Q&A

解決済

1回答

3405閲覧

Python 組み合わせ 高速化を行いたい

tomatocco

総合スコア24

Python

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

0グッド

1クリップ

投稿2020/04/20 05:16

編集2020/04/20 21:06

###行いたいこと
品物の組み合わせと、個数の組み合わせを実施し、それを掛け合わせた合計金額を表として得たいです。

コードは作成することができましたが、品物のカテゴリーを増やすと計算時間が膨大になってしまいます。
(本当は品物として10個のカテゴリーを利用したい)

素人なりになんとかコード作成することができました。高速化を可能にしたいとnumbaを用いてみましたがうまくいきません。
numba以外の方法での高速化でもかまいません。
ご教授頂きたくよろしくお願いいたします。

発生している問題・エラーメッセージ

<ipython-input-34-fd31c87fef52>:23: NumbaWarning: Compilation is falling back to object mode WITH looplifting enabled because Function "kumiawase_numba" failed type inference due to: Untyped global name 'item_kumiawase_list': Cannot type empty list File "<ipython-input-34-fd31c87fef52>", line 56: def kumiawase_numba(): <source elided> for Df_quantity_list_number_bangou in df_quantity_list_number_bangou: item_kumiawase_list.append(item_select) ^ @jit <ipython-input-34-fd31c87fef52>:23: NumbaWarning: Compilation is falling back to object mode WITHOUT looplifting enabled because Function "kumiawase_numba" failed type inference due to: cannot determine Numba type of <class 'numba.dispatcher.LiftedLoop'> File "<ipython-input-34-fd31c87fef52>", line 49: def kumiawase_numba(): <source elided> for Df_cost_list_number_bangou in df_cost_list_number_bangou: ^

該当のソースコード

〈行いたいこと〉 組み合わせたいデータはexcel表に記載し、pythonを動かすことで結果表が得られるようなシステムを作成したい。 野菜と果物と飲み物の組み合わせを作成。購入個数の組み合わせも作成。それの掛け合わせたものの合計金額を出したい。 1. 3つのカテゴリーの品物掛け合わせを作成。   A_data,B_data,C_data=[tomato,apple,milk],[tomato,apple,coffee]・・・・  全27通り 2. 3つのカテゴリーの個数の組み合わせを作成(B,Cの個数候補はあり、全部たして15になるようにAを変動) A,B,C=[11,1,3],[10,1,4]・・・・・・・全9通り 3. 品物と個数を組み合わせを作成   [tomato:11個,apple:1個,milk:3個], [tomato:10個,apple:1個,milk:4個],・・・・・・・全243通り(27×9) 4. それぞれの金額から、合計金額を算出して一覧表を作成したい。 [tomato:11個,apple:1個,milk:3個]=2800円, [tomato:10個,apple:1個,milk:4個]=2810円,・・・・・・・全243通り 以下、作成したコードになります。 #〈組み合わせたいデータ〉 #品物 item A_data=['tomato','lettuce','carrot'] B_data=['apple','banana','orange'] C_data=['milk','coffee','beer'] #購入個数 quantity A=15-(B+C) B=[1,2,3] C=[3,4,7] #値段 cost A_2=[100,200,300] B_2=[10,30,50] C_2=[200,500,300] #Xは1~10の場合がある。今回は10の場合のみ記載 X=10 # 〈求めたいもの〉品物の組み合わせと購入個数の組み合わせと合計金額 item_kumiawase_list=list() 最終に得たい表の品物の組み合わせ部分 quantity_kumiawase_list=list() 最終に得たい表の個数の組み合わせ部分 allcost_list=list() 合計金額 if X==10:                                     ※個数の組み合わせを実施   quantity_list=list(itertools.product(B,C))                BとCの組み合わせを実施 df_quantity_list= pd.DataFrame(quantity_list,columns=['b', 'c'])     BとCの組み合わせを表に変換   Q=df_quantity_list.sum(axis=1)                      15-(B+C)よりAの個数を追加 df_quantity_list["total"]=Q P=15-Q df_quantity_list["a"]=P #並び替え df_quantity_list=df_quantity_list.ix[:,['a',"b","c"]] item_list=list(itertools.product(A_data, B_data,C_data)) ※品物の組み合わせを実施→表に変換 df_item_list= pd.DataFrame(item_list) df_item_list.columns = ['A', 'B', 'C'] cost_list=list(itertools.product(A_2,B_2,C_2))             ※コストの組み合わせを実施→表に変換 df_cost_list= pd.DataFrame(cost_list) df_cost_list.columns = ['a2',"b2","c2"] df_quantity_list_number=len(df_quantity_list)              ※個数の組み合わせ表を上から番号指定できるよう番号を入手 df_quantity_list_number_bangou=np.arange(0,df_quantity_list_number,1)   df_cost_list_number=len(df_cost_list)                  ※コストの組み合わせ表を上から番号指定できるよう番号を入手 df_cost_list_number_bangou=np.arange(0,df_cost_list_number,1) for Df_cost_list_number_bangou in df_cost_list_number_bangou:     cost_select=df_cost_list.iloc[Df_cost_list_number_bangou,:]    ※コスト組み合わせ表のデータを上から順に指定。 a_cost=cost_select[0]                          Aのコスト b_cost=cost_select[1]                          Bのコスト c_cost=cost_select[2]                          Cのコスト      item_select=df_item_list.iloc[Df_cost_list_number_bangou,:] ※品物の組み合わせ表のデータを上から順に指定。 for Df_quantity_list_number_bangou in df_quantity_list_number_bangou: item_kumiawase_list.append(item_select)                   ※品物の組み合わせリストを記載 quantity_select=df_quantity_list.iloc[Df_quantity_list_number_bangou,:]  ※個数組み合わせ表のデータを上から順に指定。 quantity_kumiawase_list.append(quantity_select2)              ※個数組み合わせリストを記載 a_quantity=quantity_select[0]                          Aの個数 b_quantity=quantity_select[1]                          Bの個数 c_quantity=quantity_select[2]                          Cの個数 allcost= a_cost*a_quantity+b_cost*b_quantity+c_cost*c_quantity      ※合計金額計算 allcost_list.append(allcost)                         ※合計金額をリストに記載 df_item_kumiawase= pd.DataFrame(item_kumiawase_list) df_quantity_kumiawase= pd.DataFrame(quantity_kumiawase_list) df_allcost_list=pd.DataFrame(allcost_list)

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

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

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

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

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

hayataka2049

2020/04/20 11:28

コードがいりくんでいていて読むのがしんどいので、やりたいことを日本語で解説していただいた方が回答しやすくなります。
tomatocco

2020/04/20 20:19

ご指摘ありがとうございます。書き直します。
guest

回答1

0

ベストアンサー

コードは複雑なので理解できていませんが、いくつかアドバイスを書いてみます。

numbaは添字アクセスによる計算などnumba向きの処理を記述すると高速になるというもので、普通に書いたpythonコードにはまず効きません。numbaを使うことを前提にぜんぶ組み替えないといけませんし、効率的に最適化するのであればボトルネックを見つけてそこを実装するような形になります。

また、pandasのデータフレームから要素を出し入れしたりする処理は、だいたいどうやっても遅くなります。データフレームを使わないで書くだけでもたぶん数倍くらいは速くなるでしょう。

追記

愚直にやって0.1秒を切る程度なのですが、これで「遅い」ですか?

python

1A_data=['tomato','lettuce','carrot'] 2B_data=['apple','banana','orange'] 3C_data=['milk','coffee','beer'] 4 5B=[1,2,3] 6C=[3,4,7] 7 8A_2=[100,200,300] 9B_2=[10,30,50] 10C_2=[200,500,300] 11 12quantities = [] 13for b in B: 14 for c in C: 15 quantities.append([15 - b - c, b, c]) 16 17idx = [] 18for i in range(3): 19 for j in range(3): 20 for k in range(3): 21 idx.append([i, j, k]) 22 23 24result = [] 25for ai, bi, ci in idx: 26 for aq, bq, cq in quantities: 27 result.append(((A_data[ai], B_data[bi], C_data[ci]), 28 (aq, bq, cq), 29 A_2[ai] * aq + B_2[bi] * bq + C_2[ci] * cq)) 30print(result) 31

投稿2020/04/20 13:46

編集2020/04/22 01:39
hayataka2049

総合スコア30935

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

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

tomatocco

2020/04/20 20:25

アドバイスありがとうございます。 エクセルの表を書き替えても利用できるシステムを作成したくて、データフレームを多用しました。 データフレームを利用しないとは、リストのまま計算に用いるということでしょうか?
tomatocco

2020/04/21 21:04

if文以下で使用しているデータフレームをすべてリストに変換しました。 早くなったようですが、もっと早くしたいです。ほかにも何か方法があれば教えていただきたいです。
hayataka2049

2020/04/22 01:40 編集

追記しました。これで「遅い」ですか? どれくらいの要求水準なのかも書くといいかもしれません。
tomatocco

2020/04/26 21:45

お礼が遅くなり申し訳ありません。本当はカテゴリー10個、個数も各5の計算を行いたかったため、計算時間が長く困っていました。教えていただいたコードにさらにfor文の中にfor文を入れることで約3倍に速くなりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問