在matplotlib

时间:2015-06-05 02:32:50

标签: python numpy matplotlib loglog

我有一个情节,我在两个轴上都是对数。我有pyplot的loglog函数来执行此操作。它还给出了两个轴上的对数刻度。

现在,使用numpy我直线到我拥有的点数。但是,当我在情节上绘制这条线时,我无法得到一条直线。我得到一条曲线。 The blue line is the supposedly "straight line". It is not getting plotted straight. I want to fit a straight line to the curve plotted by red dots

蓝线是所谓的“直线”。它没有直接绘制。我想将这条直线拟合到由红点绘制的曲线

以下是我用来绘制点数的代码:

import numpy
from matplotlib import pyplot as plt
import math
fp=open("word-rank.txt","r")
a=[]
b=[]

for line in fp:
    string=line.strip().split()
    a.append(float(string[0]))
    b.append(float(string[1]))

coefficients=numpy.polyfit(b,a,1)
polynomial=numpy.poly1d(coefficients)
ys=polynomial(b)
print polynomial
plt.loglog(b,a,'ro')
plt.plot(b,ys)
plt.xlabel("Log (Rank of frequency)")
plt.ylabel("Log (Frequency)")
plt.title("Frequency vs frequency rank for words")
plt.show()

3 个答案:

答案 0 :(得分:7)

为了更好地理解这个问题,让我们先谈谈普通的问题。线性回归(在这种情况下,polyfit函数是您的线性回归算法。)

假设您有一组数据点(x,y),如下所示:

Linear regression diagram

您希望创建一个模型,将y预测为x的函数,因此您可以使用线性回归。那使用模型:

y = mx + b

并使用线性代数计算最能预测数据的mb的值。

接下来,使用模型预测y的值作为x的函数。您可以通过为x(想想linspace)选择一组值并计算y的相应值来完成此操作。绘制这些(x,y)对可以得到回归线。

现在,让我们谈谈对数回归。在这种情况下,我们仍然有两个变量,y与x,我们仍然对它们的关系感兴趣,即能够预测y给定x。唯一的区别是,现在yx碰巧是其他两个变量的对数,我称之为log(F)log(R)。到目前为止,这只不过是一个简单的名称更改。

Log regression diagram

线性回归的工作方式也相同。你仍然在回归y和x。线性回归算法并不关心yx实际上是log(F)log(R) - 它对算法没有任何影响。

最后一步有点不同 - 这就是你在上面的情节中被绊倒的地方。你正在做的是计算

F = m R + b

但这是不正确的,因为FR之间的关系不是线性的。 (这就是你使用对数日志图的原因。)

相反,你应该计算

log(F) = m log(R) + b

如果你改变它(将10增加到双方的力量并重新排列),你得到

F = c R^m

其中c = 10^b。这是FR之间的关系:它是一种幂律关系。 (幂律关系是log-log图最好的。)

在您的代码中,您在致电polyfit时使用了A和B,但您应该使用log(A)log(B)

答案 1 :(得分:5)

您的线性拟合不会在loglog-plot中显示的相同数据上执行。

制作像这样的a和b numpy数组

a = numpy.asarray(a, dtype=float)
b = numpy.asarray(b, dtype=float)

现在您可以对它们执行操作。 loglog-plot的作用是将对数取为a和b的10的基数。

你也可以这样做
logA = numpy.log10(a)
logB = numpy.log10(b)

这是loglog图可视化的内容。通过将logA和logB绘制为常规图来检查这一点。在日志数据上重复线性拟合,并在与logA,logB数据相同的图中绘制线条。

coefficients = numpy.polyfit(logB, logA, 1)
polynomial = numpy.poly1d(coefficients)
ys = polynomial(b)
plt.plot(logB, logA)
plt.plot(b, ys)

答案 2 :(得分:1)

其他答案提供了很好的解释和解决方案。但是,我想提出一个对自己有很大帮助的解决方案,也许对您也有帮助。

编写适合对数-对数刻度的线的另一种简单方法是下面的代码中的函数powerfit。它接收原始的xy数据,并且通过使用许多新的x点,您可以在对数-对数刻度上获得一条直线。在当前情况下,值xnewx相同(都是b)。

定义新的x坐标的优点是,无论出于何种目的,您都可以从功率拟合线中获得尽可能少的点。

import numpy as np
from matplotlib import pyplot as plt
import math


def powerfit(x, y, xnew):
    """line fitting on log-log scale"""
    k, m = np.polyfit(np.log(x), np.log(y), 1)
    return np.exp(m) * xnew**(k)


fp=open("word-rank.txt","r")
a=[]
b=[]

for line in fp:
    string=line.strip().split()
    a.append(float(string[0]))
    b.append(float(string[1]))

ys = powerfit(b, a, b)

plt.loglog(b,a,'ro')
plt.plot(b,ys)
plt.xlabel("Log (Rank of frequency)")
plt.ylabel("Log (Frequency)")
plt.title("Frequency vs frequency rank for words")
plt.show()