如何适应对数刻度

mar*_*all 5 python matplotlib

我有以下几点

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
Run Code Online (Sandbox Code Playgroud)

如果我在 y 轴上用对数刻度绘制它们,它们看起来大致呈线性。我怎样才能在这个对数刻度上拟合一条直线,以便我可以拟合数据?

我当前的代码非常粗糙。对于每个 x,y 对,我都会这样做。

xcoords.append(x)
ycoords.append(math.log(y))
Run Code Online (Sandbox Code Playgroud)

然后最后我做

plt.plot(xcoords,ycoords)
plt.show()
Run Code Online (Sandbox Code Playgroud)

Bon*_*fum 1

该解决方案使用 numpy (docs)中的最小二乘拟合方法。

本页提供了线性数据上线性回归的示例用法。

因为您有对数线性数据,所以在这里我们首先转换数据,然后运行线性拟合。

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()
Run Code Online (Sandbox Code Playgroud)

拟合所有数据

但是,您的数据似乎有两种状态,因此单个线性拟合不能很好地捕获数据。相反,您可以将其描述为两种不同的制度,这可能合适也可能不合适,具体取决于您的数据来自何处以及您是否可以解释这两种制度发生变化的点。

因此,让我们获取数据的第一部分并对其进行拟合

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()
Run Code Online (Sandbox Code Playgroud)

拟合部分数据

这更适合数据的第一部分(但它可能不是特别有意义——这取决于生成数据点的过程)。