2013-08-06 3 views
10

파이썬으로 히스토그램을 작성하는 것에 대한 개념적인 질문이 있습니다. 나는 좋은 알고리즘이 있는지 아니면 기존 패키지가 있는지 알아 내려고 노력 중이다.파이썬으로 몬테카를로 시뮬레이션 : 즉석에서 막대 그래프 만들기

몬테카를로 시뮬레이션을 실행하는 함수를 작성하여 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'로 표시 열을 갖는 팬더의 dataframe 개체입니다 : 아래는 말했다 기능입니다. head은 두 개의 연속적인 트럭 사이의 거리이고, span은 교량 길이입니다. 이 기능은 트럭 열차의 전체 길이가 교량 길이보다 작은 한 트럭을 교량에 무작위로 배치합니다. 마지막으로 다리 당 기존 트럭의 평균 중량 (다리에있는 총 무게를 다리 길이로 나눈 값)을 계산합니다.

결과로 반환 값의 분포를 보여주는 표 히스토그램을 작성하고 싶습니다.이 값은 나중에 플롯 할 수 있습니다. 내가 마음에 몇 가지 아이디어를 가지고 :

  1. 보관할은 몬테카를로 분석이 완료되면 다음 기존의 히스토그램 기능을 사용하는 NumPy와 벡터에 반환 된 값을 수집. 계산이 정확하다면 해당 벡터에만 7.5GB의 메모리가 필요합니다 (1,000,000,000 64 비트 부동 소수점 ~ 7.5GB)

  2. 주어진 범위와 빈 수를 사용하여 numpy 배열을 초기화하십시오. . 매 실행이 끝날 때마다 일치하는 저장소의 항목 수를 하나씩 늘리십시오. 문제는 내가 얻을 수있는 가치의 범위를 모른다는 것입니다. 범위와 적절한 크기의 막대 그래프를 설정하는 것은 알 수 없습니다. 또한 정확한 bin에 값을 할당하는 방법을 알아야하지만, 그것이 가능하다고 생각합니다.

  3. 어떻게 든 비행 중에하세요. 함수가 숫자를 반환 할 때마다 범위와 빈 크기를 수정하십시오. 이것은 생각하기에는 너무 까다로울 것입니다.

글쎄,이 문제를 해결할 수있는 더 좋은 방법이있을 것입니다. 어떤 아이디어라도 환영받을 것입니다!

두 번째 메모에서 위의 함수를 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 답변에 감사드립니다. 나는 performace 문제와 관련하여 게시물을 약간 편집했지만, 히스토그램 문제와 비교할 때 우선 순위는 낮습니다. 나는 이것을 할 수있는 과학적 패키지가있을 것이라는 다소 희망적이었습니다. – marillion

+0

정렬 목록 대신 해시 테이블을 사용하면 훨씬 빠르고 구현이 간단합니다 (훨씬 간단합니다). –

답변

2

고정 빈 크기와 [k * 크기, (k + 1) * 크기 [ finalizebins 함수는 bin 카운트 (a)와 bin 목록 (binsize를 더하여 상한값이 추측 됨)이있는 다른 (b)의 두 목록을 반환합니다. 큰 상자에 값을 할당

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

관련 문제