Đây có thể là quá mức cần thiết và dựa trên nhận xét của bạn
Cả đường cong lý thuyết và các điểm dữ liệu là mảng của độ dài khác nhau.
tôi sẽ làm như sau:
- Truncate dữ liệu thiết lập để cho giá trị x của nó nằm trong tối đa và giá trị tối thiểu của tập lý thuyết.
- Nội suy đường cong lý thuyết bằng cách sử dụng
scipy.interpolate.interp1d
và các giá trị x dữ liệu cắt ngắn ở trên. Lý do cho bước (1) là để đáp ứng các ràng buộc của interp1d
.
- Sử dụng
numpy.where
để tìm giá trị y dữ liệu nằm ngoài phạm vi giá trị lý thuyết có thể chấp nhận được.
- DONT loại bỏ các giá trị này, như đã được đề xuất trong các nhận xét và các câu trả lời khác. Nếu bạn muốn cho rõ ràng, chỉ cho họ ra bằng cách vẽ 'inliners' một màu và 'ngoại lệ' một màu khác.
Đây là tập lệnh gần với những gì bạn đang tìm kiếm, tôi nghĩ vậy. Nó hy vọng sẽ giúp bạn thực hiện những gì bạn muốn:
import numpy as np
import scipy.interpolate as interpolate
import matplotlib.pyplot as plt
# make up data
def makeUpData():
'''Make many more data points (x,y,yerr) than theory (x,y),
with theory yerr corresponding to a constant "sigma" in y,
about x,y value'''
NX= 150
dataX = (np.random.rand(NX)*1.1)**2
dataY = (1.5*dataX+np.random.rand(NX)**2)*dataX
dataErr = np.random.rand(NX)*dataX*1.3
theoryX = np.arange(0,1,0.1)
theoryY = theoryX*theoryX*1.5
theoryErr = 0.5
return dataX,dataY,dataErr,theoryX,theoryY,theoryErr
def makeSameXrange(theoryX,dataX,dataY):
'''
Truncate the dataX and dataY ranges so that dataX min and max are with in
the max and min of theoryX.
'''
minT,maxT = theoryX.min(),theoryX.max()
goodIdxMax = np.where(dataX<maxT)
goodIdxMin = np.where(dataX[goodIdxMax]>minT)
return (dataX[goodIdxMax])[goodIdxMin],(dataY[goodIdxMax])[goodIdxMin]
# take 'theory' and get values at every 'data' x point
def theoryYatDataX(theoryX,theoryY,dataX):
'''For every dataX point, find interpolated thoeryY value. theoryx needed
for interpolation.'''
f = interpolate.interp1d(theoryX,theoryY)
return f(dataX[np.where(dataX<np.max(theoryX))])
# collect valid points
def findInlierSet(dataX,dataY,interpTheoryY,thoeryErr):
'''Find where theoryY-theoryErr < dataY theoryY+theoryErr and return
valid indicies.'''
withinUpper = np.where(dataY<(interpTheoryY+theoryErr))
withinLower = np.where(dataY[withinUpper]
>(interpTheoryY[withinUpper]-theoryErr))
return (dataX[withinUpper])[withinLower],(dataY[withinUpper])[withinLower]
def findOutlierSet(dataX,dataY,interpTheoryY,thoeryErr):
'''Find where theoryY-theoryErr < dataY theoryY+theoryErr and return
valid indicies.'''
withinUpper = np.where(dataY>(interpTheoryY+theoryErr))
withinLower = np.where(dataY<(interpTheoryY-theoryErr))
return (dataX[withinUpper],dataY[withinUpper],
dataX[withinLower],dataY[withinLower])
if __name__ == "__main__":
dataX,dataY,dataErr,theoryX,theoryY,theoryErr = makeUpData()
TruncDataX,TruncDataY = makeSameXrange(theoryX,dataX,dataY)
interpTheoryY = theoryYatDataX(theoryX,theoryY,TruncDataX)
inDataX,inDataY = findInlierSet(TruncDataX,TruncDataY,interpTheoryY,
theoryErr)
outUpX,outUpY,outDownX,outDownY = findOutlierSet(TruncDataX,
TruncDataY,
interpTheoryY,
theoryErr)
#print inlierIndex
fig = plt.figure()
ax = fig.add_subplot(211)
ax.errorbar(dataX,dataY,dataErr,fmt='.',color='k')
ax.plot(theoryX,theoryY,'r-')
ax.plot(theoryX,theoryY+theoryErr,'r--')
ax.plot(theoryX,theoryY-theoryErr,'r--')
ax.set_xlim(0,1.4)
ax.set_ylim(-.5,3)
ax = fig.add_subplot(212)
ax.plot(inDataX,inDataY,'ko')
ax.plot(outUpX,outUpY,'bo')
ax.plot(outDownX,outDownY,'ro')
ax.plot(theoryX,theoryY,'r-')
ax.plot(theoryX,theoryY+theoryErr,'r--')
ax.plot(theoryX,theoryY-theoryErr,'r--')
ax.set_xlim(0,1.4)
ax.set_ylim(-.5,3)
fig.savefig('findInliers.png')
Con số này là kết quả:
Chỉ cần hoàn toàn từ quan điểm khoa học, tôi sẽ không loại bỏ các điểm trừ khi có lý do hợp lệ R that RÀNG mà bạn cho rằng chúng sai. Bạn có đủ dữ liệu mà các điểm bên ngoài sẽ không có bất kỳ ảnh hưởng nào đến mức phù hợp, vì vậy việc xóa chúng chỉ phục vụ để làm cho biểu đồ trông đẹp, không phục vụ bất kỳ mục đích khoa học nào. – NickLH
Bạn nói đúng, nhưng tôi đã được bảo. –