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 एक पांडा dataframe 'length' और 'gvw' के रूप में लेबल कॉलम, जो क्रमशः ट्रक लंबाई और वजन रहे हैं, होने वस्तु है: नीचे कहा कार्य है। head लगातार दो ट्रकों के बीच की दूरी है, span पुल की लंबाई है। समारोह तब तक पुल पर ट्रक रखता है जब तक कि ट्रक ट्रेन की कुल लंबाई पुल की लंबाई से कम न हो। अंत में, प्रति पैर पुल पर मौजूद ट्रकों के औसत वजन की गणना करता है (पुल की लंबाई से विभाजित पुल पर कुल वजन)।

नतीजतन मैं एक सारणीबद्ध हिस्टोग्राम बनाना चाहता हूं जो लौटाए गए मूल्यों के वितरण को दिखाता है, जिसे बाद में प्लॉट किया जा सकता है। मेरे मन में कुछ विचार था:

  1. रखें एक numpy वेक्टर में लौटे मूल्यों का संग्रह है, तो का उपयोग मौजूदा हिस्टोग्राम कार्यों एक बार मोंटेकार्लो विश्लेषण पूरा हो गया है। यह व्यवहार्य नहीं होगा, क्योंकि अगर मेरी गणना सही है, तो मुझे केवल वेक्टर के लिए 7.5 जीबी मेमोरी की आवश्यकता होगी (1,000,000,000 64 बिट फ्लोट ~ 7.5 जीबी)

  2. किसी दिए गए रेंज और डिब्बे की संख्या के साथ एक numpy सरणी शुरू करें । प्रत्येक रन के अंत में मिलान बिन में आइटम की संख्या बढ़ाएं। समस्या यह है कि, मुझे उन मूल्यों की सीमा नहीं है जो मुझे मिलेंगे। एक श्रेणी और उचित बिन आकार के साथ एक हिस्टोग्राम स्थापित करना अज्ञात है। मुझे यह भी पता लगाना होगा कि सही डिब्बे को मूल्य कैसे असाइन करना है, लेकिन मुझे लगता है कि यह करने योग्य है।

  3. इसे किसी भी तरह फ्लाई पर करें। जब भी फ़ंक्शन एक संख्या देता है तो श्रेणियों और बिन आकारों को संशोधित करें। मुझे लगता है कि स्क्रैच से लिखना बहुत मुश्किल होगा।

ठीक है, मुझे यकीन है कि इस समस्या को संभालने का एक बेहतर तरीका हो सकता है। किसी भी विचार का स्वागत है!

एक दूसरे नोट पर, मैं केवल सबसे बड़ा मान है कि गणना की जाती है (कोड स्निपेट से कम है) प्राप्त करने के लिए 1,000,000,000 समय के लिए ऊपर समारोह चल रहा है परीक्षण किया गया। और यह लगभग एक घंटे लगते हैं जब span = 200। गणना समय बढ़ेगा यदि मैं इसे लंबे समय तक चलाता हूं (जबकि लूप ट्रक के साथ पुल को भरने के लिए अधिक समय तक चलता है)। क्या आपको लगता है कि इसे अनुकूलित करने का कोई तरीका है?

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) * आकार [के डिब्बे। फंक्शन फाइनलाइजिन दो सूचियों को लौटाता है: एक बिन मायने रखता है (ए), और दूसरा (बी) बिन निचले सीमाओं के साथ (ऊपरी बाउंड को बिन्सइज जोड़कर घटाया जाता है)।

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

संबंधित मुद्दे