2016-02-29 56 views
2
from numpy import * 
import matplotlib.pyplot as plt 
import numpy as np 

# This is my data set 
x = [15, 30, 45, 60, 75, 90, 105, 120, 135, 150, 165, 180, 195, 210, 225, 240] 
y = [1, 0.9, 0.8, 0.7, 0.6, 0.55, 0.5, 0.45, 0.4, 0.35, 0.33, 0.31, 0.29, 0.27, 0.25, 0.23] 

我想爲此數據集添加3個線性迴歸。通過用pyplot繪製我的數據集,我可以直觀地看到扭結開始形成的位置(大約x = 105,x = 165)。所以我可以創建3個線性迴歸(從0到105,105到165,165到240)。但是,我如何科學地做到這一點?換句話說,我想爲我的數據添加3個線性迴歸,以最小化卡方。有沒有辦法用代碼來實現這一點?如何將3線性擬合的卡方最小化

+0

我沒有得到你想要達到的。你想得到三個不同的參數集(每個線性迴歸一個)? – Cleb

+0

我知道如何爲我的數據創建3個單獨的線性擬合併計算出相應的卡方值,但我只是通過分割我的x,y列表來完成此操作。我想創建一個算法來分割列表,這樣卡方的最小化對於所有3個線性擬合。 – PiccolMan

+0

我更新了我的答案;它現在會自動分割x和y,並且我還在for循環中添加了更多的細節。讓我知道你是否還有其他問題! – Cleb

回答

1

您可以在下面找到使用scipy.stats.linregress的自動程序的代碼和輸出;解釋可以在代碼的下面找到。輸出如下所示:

enter image description here

的斜率和攔截條件是:

  • 曲線1:-0.0066 * X + 1.10
  • 曲線2:-0.0033 * X + 0.85
  • 曲線3:-0.0013 * X + 0.55

下面是代碼:

from scipy import stats 
import matplotlib.pyplot as plt 
import numpy as np 

x = np.array([15, 30, 45, 60, 75, 90, 105, 120, 135, 150, 165, 180, 195, 210, 225, 240]) 
y = np.array([1, 0.9, 0.8, 0.7, 0.6, 0.55, 0.5, 0.45, 0.4, 0.35, 0.33, 0.31, 0.29, 0.27, 0.25, 0.23]) 

# get slope of your data 
dif = np.diff(y)/np.diff(x) 

# determine the change of the slope 
difdif = np.diff(dif) 

# define a threshold for the allowed change of the slope 
threshold = 0.001 

# get indices where the diff returns value larger than a threshold 
indNZ = np.where(abs(difdif) > threshold)[0] 

# this makes plotting easier and avoids a couple of if clauses 
indNZ += 1 
indNZ = np.append(indNZ, len(x)) 
indNZ = np.insert(indNZ, 0, 0) 

# plot the data 
plt.scatter(x, y) 

for indi, ind in enumerate(indNZ): 

    if ind < len(x): 
     slope, intercept, r_value, p_value, std_err = stats.linregress(x[ind:indNZ[indi+1]], y[ind:indNZ[indi+1]]) 
     plt.plot(x[ind:indNZ[indi+1]], slope * x[ind:indNZ[indi+1]] + intercept) 

plt.show() 

首先,可以使用np.diff來計算斜率。在坡度上應用np.diff可以顯示坡度顯着變化的點;在上面的代碼中,我使用了一個閾值(如果你總是處理完美的線條,那麼可以設置一個非常小的值;如果你有嘈雜的數據,你將不得不調整這個值)。

當斜率發生顯着變化時,可以在各個部分進行線性迴歸並相應地繪製結果。

for循環的詳細信息:

indNZ 

array([ 0, 4, 9, 16]) 

,讓你的三條線的間隔。所以藍線對應於從x[0]x[3],綠線到從x[4]x[8]的部分以及從x[9]x[15]的部分的紅線。在for循環中,選擇這些範圍,使用scipy.stats.linregress(如果您更喜歡的話,也可以用polyfit代替)進行線性擬合,然後使用方程slope * x + intercept繪製該線。

+0

對不起,我的問題可能不是很清楚。我不想爲我的3個線性擬合選擇範圍。我想創建一個算法,爲我做這個。例如,假設我錯誤地選擇了x範圍爲0到100,100到200和200到240。此範圍的卡方值將過大。我希望算法能夠找到將卡方最小化的3個範圍。我有點想法如何做到這一點,但對我來說這太複雜了。謝謝你嘗試! – PiccolMan

+0

我更新了代碼。請讓我知道現在是解決問題還是需要修改。 – Cleb

+0

我不熟悉stats.linregress。我使用polyfit來創建線性擬合。你能解釋一下你在for循環中做什麼嗎?謝謝! – PiccolMan