2013-12-10 3 views
3

У меня есть следующие пунктыКак установить в логарифмической шкале

0 4194304 
1 497420 
2 76230 
3 17220 
4 3595 
5 1697 
6 491 
7 184 
8 54 
9 15 
10 4 
11 4 
12 1 
13 1 
14 1 
15 1 
16 1 
17 1 
18 1 
19 1 
20 1 
21 1 

Если я сюжет их в логарифмическом масштабе по оси ординат они выглядят примерно линейна. Как я могу поместить прямую линию в этот масштаб журнала, чтобы я мог поместиться в данные?

Мой текущий код очень груб. Для каждой пары x, y я делаю.

xcoords.append(x) 
ycoords.append(math.log(y)) 

А потом в конце я

plt.plot(xcoords,ycoords) 
plt.show() 
+0

Ваш код сейчас? –

+0

IIRC, это называется _logarithmic regression_, или что-то в этом роде. – rodrigo

+2

Это может быть актуально: http://stackoverflow.com/questions/3433486/how-to-do-exponential-and-logarithmic-curve-fitting-in-python-i-found-only-poly –

ответ

1

Это решение использует метод наименьших квадратов посаженные от Numpy (docs).

Эта страница содержит линейную регрессию example usage по линейным данным.

Поскольку у вас есть логарифмически-линейные данные, здесь мы сначала преобразуем данные, затем выполняем линейную подгонку.

import numpy as np 
import matplotlib.pyplot as plt 

d = ''' 
0 4194304 
1 497420 
... (put all the rest of the data in here) 
''' 

D = np.loadtxt(d.split('\n')) 

x = D[:,0] 
y = D[:,1] 
y_ln = np.log(y) 

n = D.shape[0] 

A = np.array(([[x[j], 1] for j in range(n)])) 
B = np.array(y_ln[0:n]) 

X = np.linalg.lstsq(A,B)[0] 
a=X[0]; b=X[1] 

# so now your fitted line is log(y) = a*x + b 
# lets show it on a graph. 
plt.figure() 
plt.plot(x, a*x+b, '--') 
plt.plot(x, y_ln, 'o') 
plt.ylabel('log y') 
plt.xlabel('x values') 
plt.show() 

# or use the original scales by transforming the data back again: 

plt.figure() 
plt.plot(x, np.exp(a*x+b), '--') 
plt.plot(x, y, 'o') 
plt.ylabel('y') 
plt.xlabel('x values') 
plt.yscale('log') 
plt.show() 

fitting all the data

Однако ваши данные, кажется, есть два режима, поэтому одна линейная подгонка не хорошо захватить данные. Вы могли бы вместо этого описать это как два разных режима: , которые могут быть или не быть подходящими в зависимости от того, откуда ваши данные, и , можете ли вы объяснить, в какой момент изменились два режима.

Так давайте первую часть ваших данных и просто подходят, что

n = 13 
A = np.array(([[x[j], 1] for j in range(n)])) 
B = np.array(yl[0:n]) 
A = np.array(([[x[j], 1] for j in range(n)])) 
B = np.array(y_ln[0:n]) 

X = np.linalg.lstsq(A,B)[0] 
a=X[0]; b=X[1] 

plt.figure() 
plt.plot(x[0:n], np.exp(a*x[0:n]+b), '--') 
plt.plot(x, y, 'o') 
plt.ylabel('y') 
plt.xlabel('x values') 
plt.yscale('log') 
plt.show() 

fitting part of the data

Это лучше подходит к первой части данных (но это не может быть особенно значимым - - это зависит от того, какой процесс генерировал точки данных).

0

Вы можете попытаться сократить нули (х [0:12]), генерировать функцию интерполяции из (х [0:12], log_y [0 : 12]), генерировать большее линейное пространство в том же диапазоне x - 12 элементов. New_x - 50 единиц в пространстве (не индекс предмета) 0, x [11] и график с f (new_x) следующим образом:

>>> x 
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21] 
>>> y 
[4194304, 497420, 76230, 17220, 3595, 1697, 491, 184, 54, 15, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] 
>>> log_y 
[15.249237972318797, 13.117190018630332, 11.24151036498232, 9.753826777981722, 8.187299270155147, 7.436617265234227, 6.19644412779452, 5.214935757608986, 3.9889840465642745, 2.70805020110221, 1.3862943611198906, 1.3862943611198906, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] 
>>> f2=interp1d(x[0:12],log_y[0:12],kind='cubic') 
>>> x_new_fit=np.linspace(0,x[11],50) 
>>> plt.plot(x_new_fit,f2(x_new_fit),'-') 
[<matplotlib.lines.Line2D object at 0x3a6e950>] 
>>> plt.show() 

эксперимент с различными видами интерполяции, для достижения разного рода smoothn ESS

>>> 
>>> f1=interp1d(x[0:12],log_y[0:12],kind='quadratic')>>> plt.plot(x[0:12],log_y[0:12],'-',x_new_fit,f2(x_new_fit),'-',x_new_fit,f1(x_new_fit),'--') 
[<matplotlib.lines.Line2D object at 0x3a97dd0>, <matplotlib.lines.Line2D object at 0x3a682d0>, <matplotlib.lines.Line2D object at 0x3a687d0>] 
>>> plt.show() 
>>> 
1

Вместо того, чтобы изменять данные, вы можете просто построить их на полулогарифмическом участке. Так, например, вы можете сделать:

import matplotlib.pyplot as plt 

    xArray = range(22) 
    yArray = [4194304,497420,76230,17220,3595,1697,491,184,54,15,4,4,1,1,1,1,1,1,1,1,1,1] 

    plt.semilogy(xArray,yArray) 
    plt.show 

Как для этого кода фитинга - попробуйте следующее:

import matplotlib.pyplot as plt 
    from scipy.optimize import curve_fit 
    from numpy import square 

    xArray = range(22) 
    yArray = [4194304,497420,76230,17220,3595,1697,491, 
       184,54,15,4,4,1,1,1,1,1,1,1,1,1,1] 

    def f(x,a,b,c): 
     return a*(square(x))+(b*x)+c 

    popt, pcov = curve_fit(f, xArray, yArray) 

    fittedA = popt[0] 
    fittedB = popt[1] 
    fittedC = popt[1] 

    yFitted = f(xArray,fittedA,fittedB,fittedC) 

    plt.figure() 
    plt.semilogy(xArray,yFitted) 
    plt.show 

Вам нужно будет придумать лучше фитинга функции то квадратичная я использовал в f(), чтобы получить хорошую форму, но это должно делать то, что вам нужно.

Смежные вопросы