2013-08-06 16 views
10

Pythonでヒストグラムを作成するという概念的な質問があります。私は良いアルゴリズムがあるか、あるいは既存のパッケージがあるかどうかを調べようとしています。Pythonを使ったモンテカルロシミュレーション:ヒストグラムを素早く作成する

私は、モンテカルロシミュレーションを実行する関数を書いて、1,000,000,000回呼び出され、各実行の最後に64ビットの浮動小数点数を返します。

def MonteCarlo(df,head,span): 
    # Pick initial truck 
    rnd_truck = np.random.randint(0,len(df)) 
    full_length = df['length'][rnd_truck] 
    full_weight = df['gvw'][rnd_truck] 

    # Loop using other random trucks until the bridge is full 
    while True: 
     rnd_truck = np.random.randint(0,len(df)) 
     full_length += head + df['length'][rnd_truck] 
     if full_length > span: 
      break 
     else: 
      full_weight += df['gvw'][rnd_truck] 

    # Return average weight per feet on the bridge 
    return(full_weight/span) 
df

は、それぞれ、トラックの長さと重みで'length''gvw'として標識された列を有するパンダのデータフレームのオブジェクトである:以下の前記関数です。 headは、2つの連続するトラック間の距離であり、spanはブリッジの長さです。この機能は、トラック列車の全長が橋梁の長さより短い限り、橋にトラックをランダムに配置します。最後に、ブリッジ上に存在するトラックの平均重量を足当たり(ブリッジ上に存在する総重量をブリッジ長で除したもの)計算する。

結果として、返された値の分布を示す表形式のヒストグラムを作成したいと思います。後でプロットすることができます。私は心の中でいくつかのアイデアを持っていた:

  1. は、モンテカルロ解析が完了すると、既存のヒストグラム機能を使用し、その後、numpyのベクトルで返された値を収集してください。私の計算が正しければ、そのベクトルには7.5GBのメモリが必要です(1000,000,000の64ビット浮動小数点数〜7.5GB)

  2. 与えられた範囲とビン数でnumpy配列を初期化します。各実行の最後に、一致するビン内の項目の数を1つ増やします。問題は、私が得る価値の範囲がわからないことです。範囲と適切なビンサイズのヒストグラムを設定することは不明です。また、正しいビンに値を割り当てる方法を理解する必要がありますが、それは実行可能だと思います。

  3. 何となくその場で行ってください。関数が数値を返すたびに範囲とビンのサイズを変更します。これはあまりにも手間がかかり、最初から書き込むと思います。

この問題を処理するには、より良い方法があると思います。どんなアイデアも大歓迎です!

2番目の注釈では、上記の関数を1,000,000,000回実行して、計算された最大値(コードスニペットが下にあります)を取得することのみをテストしました。そして、これはspan = 200の時に約1時間かかります。私は長いスパンのためにそれを実行すると計算時間が増加します(whileループはトラックでブリッジを埋めるために長く実行されます)。あなたはこれを最適化する方法はありますか?

max_w = 0 
i = 1 
    while i < 1000000000: 
     if max_w < MonteCarlo(df_basic, 15., 200.): 
      max_w = MonteCarlo(df_basic, 15., 200.) 
    i += 1 
print max_w 

ありがとう!

+0

は、単純にバイナリ検索です。ただし、その場でレンジを変更することはできません。つまり、事前に知っておくか、すべてを保存する必要があります。または、少なくとも、いくつかの前提を実行します。指定されたサイズの小さなビンでデータを集計し(あまりにも多くのデータを格納する必要はありません)、データがオーバーフローするたびにビンリストを展開します。 –

+0

@arbautjcは答えに感謝します。私は演技問題に関連して最後にポストを編集しましたが、私が持っているヒストグラムの問題と比較して低い優先順位です。私は、これを可能にする科学的なパッケージがあるかもしれないと若干期待していました。 – marillion

+0

ソート済みリストの代わりにハッシュテーブルを使用して(もっと簡単に)、素早く汚れた実装を提供します。 –

答えて

2

ここでは、固定ビンサイズと[k *サイズ、(k + 1)*サイズ[関数finalizebinsは、ビンカウントを持つもの(a)とbinの下限を持つもの(b)(binsizeを加えることによって上限を導きます)の2つのリストを返します。ビンに値を代入

import math, random 

def updatebins(bins, binsize, x): 
    i = math.floor(x/binsize) 
    if i in bins: 
     bins[i] += 1 
    else: 
     bins[i] = 1 

def finalizebins(bins, binsize): 
    imin = min(bins.keys()) 
    imax = max(bins.keys()) 
    a = [0] * (imax - imin + 1) 
    b = [binsize * k for k in range(imin, imax + 1)] 
    for i in range(imin, imax + 1): 
     if i in bins: 
      a[i - imin] = bins[i] 
    return a, b 

# A test with a mixture of gaussian distributions 

def check(n): 
    bins = {} 
    binsize = 5.0 
    for i in range(n): 
     if random.random() > 0.5: 
      x = random.gauss(100, 50) 
     else: 
      x = random.gauss(-200, 150) 
     updatebins(bins, binsize, x) 
    return finalizebins(bins, binsize) 

a, b = check(10000) 

# This must be 10000 
sum(a) 

# Plot the data 
from matplotlib.pyplot import * 
bar(b,a) 
show() 

enter image description here

関連する問題