2011-09-08 16 views
13

मैं प्रोग्रामिंग के लिए बिल्कुल नया हूं और सोचा कि मैं एक रैखिक-इंटरपोलेशन फ़ंक्शन लिखने का प्रयास करूंगा। एक्स = [1, 2.5, 3.4, 5.8, 6] y = एक समारोह [2, 4, 5.8, 4.3, 4]रैखिक इंटरपोलेशन - पायथन

मैं डिजाइन करने के लिए करना चाहते हैं:

इस प्रकार मैं दिए गए आंकड़ों हूँ कहो जो पाइथन का उपयोग करने पर 1 और 2.5, 2.5 से 3.4 के बीच रैखिक रूप से अंतरण करेगा।

मैंने http://docs.python.org/tutorial/ के माध्यम से देखने का प्रयास किया है, लेकिन मैं अभी भी इसके चारों ओर अपना सिर नहीं ढूंढ पा रहा हूं।

+0

यह ... आसान नहीं है। आपने क्या प्रयास किया है – zellio

+0

-1 बहुत सामान्य तरीके से। आप समझ नहीं पाते कि प्रोग्राम कैसे करें, या अजगर में एल्गोरिदम कैसे करें ?? – steabert

+0

अच्छी तरह से एक नया शिक्षार्थी होने के नाते मैंने खुद को गहरे छोर में फेंक दिया है ताकि बोल सकें। मैं एल्गोरिदम में 'for' या 'if' कथन का उपयोग करने के बारे में सोच रहा था। तो एक्स की कई श्रेणियों के बीच। – Helpless

उत्तर

13

जैसा कि मैं आपका प्रश्न समझता हूं, आप कुछ फ़ंक्शन y = interpolate(x_values, y_values, x) लिखना चाहते हैं, जो आपको पर y मान देगा?

  1. x_values में मूल्यों का सूचकांक जो x युक्त एक अंतराल परिभाषित खोजें: मूल विचार तो इन चरणों का अनुसरण करता है। उदाहरण के लिए, अपने उदाहरण सूचियों के साथ x=3 के लिए, युक्त अंतराल [x1,x2]=[2.5,3.4] होगा, और सूचकांक होगा i1=1, i2=2
  2. द्वारा (y_values[i2]-y_values[i1])/(x_values[i2]-x_values[i1]) (यानी dy/dx) इस अंतराल पर ढलान की गणना।
  3. x पर मूल्य अब x1 पर मूल्य है और ढलान x1 से दूरी से गुणा किया गया है।

इसके अतिरिक्त आपके, तय करने के लिए क्या होता है अगर xx_values के अंतराल के बाहर है की आवश्यकता होगी या तो यह एक त्रुटि है, या आप "पीछे की ओर" अंतर्वेशन सकता है, ढलान संभालने प्रथम/अंतिम अंतराल के समान है।

क्या यह मदद मिली, या आपको अधिक विशिष्ट सलाह की आवश्यकता है?

+0

कोई भी सही नहीं है, बहुत बहुत धन्यवाद! – Helpless

+3

यह y_values ​​[i2] को अपने आप से घटाए जाने का अधिकार नहीं हो सकता है। क्या यह होना चाहिए '(y_values ​​[i2] -y_values ​​[i1]) '? –

+3

@ मार्टिनबर्च: कुछ साल बाद, लेकिन ... धन्यवाद, तय! :) – carlpett

10

मैं एक नहीं बल्कि सुरुचिपूर्ण समाधान (IMHO) सोचा, तो मैं यह पोस्टिंग का विरोध नहीं कर सकते हैं:

from bisect import bisect_left 

class Interpolate(object): 
    def __init__(self, x_list, y_list): 
     if any(y - x <= 0 for x, y in zip(x_list, x_list[1:])): 
      raise ValueError("x_list must be in strictly ascending order!") 
     x_list = self.x_list = map(float, x_list) 
     y_list = self.y_list = map(float, y_list) 
     intervals = zip(x_list, x_list[1:], y_list, y_list[1:]) 
     self.slopes = [(y2 - y1)/(x2 - x1) for x1, x2, y1, y2 in intervals] 

    def __getitem__(self, x): 
     i = bisect_left(self.x_list, x) - 1 
     return self.y_list[i] + self.slopes[i] * (x - self.x_list[i]) 

मैं float ताकि पूर्णांक प्रभाग (अजगर < = 2.7) के लिए नक्शे में लात नहीं होगा और अगर x1, x2, y1 और y2 कुछ इटर्वल के लिए सभी पूर्णांक हैं तो चीजें बर्बाद करें।

__getitem__ में मैं तथ्य यह है कि self.x_list को bisect_left का उपयोग करके आरोही क्रम में सॉर्ट है का लाभ ले रहा हूँ (बहुत) जल्दी से सबसे बड़ा तत्व self.x_list से छोटा x के सूचकांक पाते हैं।

इस तरह वर्ग का उपयोग करें:

i = Interpolate([1, 2.5, 3.4, 5.8, 6], [2, 4, 5.8, 4.3, 4]) 
# Get the interpolated value at x = 4: 
y = i[4] 

मैं यहाँ सीमा की स्थिति से नहीं निपटा गया है, सादगी के लिए। जैसा कि है, i[x]x < 1 के लिए काम करेगा जैसे कि (2.5, 4) से (1, 2) की रेखा को शून्य से अनंत तक बढ़ा दिया गया है, जबकि i[x]x == 1 या x > 6IndexError बढ़ाएगा। सभी मामलों में इंडेक्स एरर बढ़ाने के लिए बेहतर होगा, लेकिन यह पाठक के लिए एक अभ्यास के रूप में छोड़ दिया गया है।:)

+1

मैं सामान्य रूप से प्राथमिकता के लिए '__getitem__' के बजाय' __call__' का उपयोग करना चाहता हूं, आमतौर पर यह एक इंटरपोलेशन * फ़ंक्शन * होता है। – Dave

23
import scipy.interpolate 
y_interp = scipy.interpolate.interp1d(x, y) 
print y_interp(5.0) 

scipy.interpolate.interp1d द्वारा रैखिक प्रक्षेप करता है और त्रुटि की स्थिति को संभालने के लिए अनुकूलित किया जा सकता।

1

आपका समाधान पायथन 2.7 में काम नहीं करता है। एक्स तत्वों के क्रम की जांच करते समय एक त्रुटि हुई थी।

from bisect import bisect_left 
class Interpolate(object): 
    def __init__(self, x_list, y_list): 
     if any([y - x <= 0 for x, y in zip(x_list, x_list[1:])]): 
      raise ValueError("x_list must be in strictly ascending order!") 
     x_list = self.x_list = map(float, x_list) 
     y_list = self.y_list = map(float, y_list) 
     intervals = zip(x_list, x_list[1:], y_list, y_list[1:]) 
     self.slopes = [(y2 - y1)/(x2 - x1) for x1, x2, y1, y2 in intervals] 
    def __getitem__(self, x): 
     i = bisect_left(self.x_list, x) - 1 
     return self.y_list[i] + self.slopes[i] * (x - self.x_list[i]) 
1

इसके बजाय समाप्त होता है बंद extrapolating की, आप y_list के विस्तार लौट सकते हैं: मैं इस के लिए कोड को बदलने के लिए यह काम करने के लिए पाने के लिए था। अधिकांश समय आपका एप्लिकेशन अच्छी तरह व्यवहार करता है, और Interpolate[x]x_list में होगा। (अनुमानतः) अंतराल से बाहर निकलने के रैखिक प्रभाव आपको विश्वास करने के लिए गुमराह कर सकते हैं कि आपका डेटा अच्छी तरह व्यवहार करता है।

  • एक गैर रेखीय परिणाम (x_list और y_list की सामग्री से घिरा) रिटर्निंग अपने कार्यक्रम के व्यवहार आप x_list बाहर बहुत मूल्यों के लिए एक मुद्दे पर सतर्क कर सकते हैं। (रैखिक व्यवहार केले जब गैर रेखीय आदानों दिया है!)

  • x_list की Interpolate[x] बाहर के लिए y_list के विस्तार रिटर्निंग भी आप अपने उत्पादन मूल्य की सीमा पता है इसका मतलब है। यदि आप x पर आधारित हैं, तो x_list[0] या x से बहुत कम, x_list[-1] से अधिक, आपका रिटर्न परिणाम आपके द्वारा अपेक्षित मानों की सीमा के बाहर हो सकता है।

    def __getitem__(self, x): 
        if x <= self.x_list[0]: 
         return self.y_list[0] 
        elif x >= self.x_list[-1]: 
         return self.y_list[-1] 
        else: 
         i = bisect_left(self.x_list, x) - 1 
         return self.y_list[i] + self.slopes[i] * (x - self.x_list[i]) 
    
+0

मैं सामान्य रूप से प्राथमिकता के लिए '__getitem__' के बजाय '__call__' का उपयोग करना चाहता हूं, आमतौर पर यह एक इंटरपोलेशन * फ़ंक्शन * होता है। – Dave

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