python 2.7中日志日志的最佳拟合线

cod*_*532 6 python ip matplotlib curve-fitting linear-regression

这是对数刻度中的网络IP频率等级图.完成此部分后,我试图使用Python 2.7在log-log标度上绘制最佳拟合线.我必须使用matplotlib的"symlog"轴刻度,否则一些值不能正确显示,一些值会被隐藏.

我正在绘制的数据的X值是URL,Y值是URL的相应​​频率.

我的数据看起来像这样:

'http://www.bing.com/search?q=d2l&src=IE-TopResult&FORM=IETR02&conversationid=  123 0.00052210688591'
`http://library.uc.ca/  118 4.57782298326e-05`
`http://www.bing.com/search?q=d2l+uofc&src=IE-TopResult&FORM=IETR02&conversationid= 114 4.30271029472e-06`
`http://www.nature.com/scitable/topicpage/genetics-and-statistical-analysis-34592   109 1.9483268261e-06`
Run Code Online (Sandbox Code Playgroud)

数据包含第一列中的URL,第二列中的相应频率(相同URL存在的次数),最后是第3列中传输的字节.首先,我只使用第1列和第2列进行此分析.共有2,465个x值或唯一网址.

以下是我的代码

import os
import matplotlib.pyplot as plt
import numpy as np
import math
from numpy import *
import scipy
from scipy.interpolate import *
from scipy.stats import linregress
from scipy.optimize import curve_fit

file = open(filename1, 'r')
lines = file.readlines()

result = {}
x=[]
y=[]
for line in lines:
  course,count,size = line.lstrip().rstrip('\n').split('\t')
  if course not in result:
      result[course] = int(count)
  else:
      result[course] += int(count)
file.close()

frequency = sorted(result.items(), key = lambda i: i[1], reverse= True)
x=[]
y=[]
i=0
for element in frequency:
  x.append(element[0])
  y.append(element[1])


z=[]
fig=plt.figure()
ax = fig.add_subplot(111)
z=np.arange(len(x))
print z
logA = [x*np.log(x) if x>=1 else 1 for x in z]
logB = np.log(y)
plt.plot(z, y, color = 'r')
plt.plot(z, np.poly1d(np.polyfit(logA, logB, 1))(z))
ax.set_yscale('symlog')
ax.set_xscale('symlog')
slope, intercept = np.polyfit(logA, logB, 1)
plt.xlabel("Pre_referer")
plt.ylabel("Popularity")
ax.set_title('Pre Referral URL Popularity distribution')
plt.show()
Run Code Online (Sandbox Code Playgroud)

您会看到很多库被导入,因为我一直在玩很多这些库,但我的实验都没有产生预期的结果.所以上面的代码正确生成了排名图.哪条是红线,但曲线中的蓝线(应该是最佳拟合线)在视觉上是不正确的,可以看出.这是生成的图表.

正确的排名图但曲线拟合不正确

这是我期待的图表.第二张图中的虚线是我在某种程度上错误地绘制的.

预期图表

关于如何解决这个问题的任何想法?

Cra*_*aig 12

在对数对数刻度上沿直线下降的数据遵循表单的幂关系y = c*x^(m).通过取两边的对数,可以得到拟合的线性方程:

log(y) = m*log(x) + c
Run Code Online (Sandbox Code Playgroud)

呼叫np.polyfit(log(x), log(y), 1)提供的数值mc.然后,您可以使用这些值来计算拟合值log_y_fit:

log_y_fit = m*log(x) + c
Run Code Online (Sandbox Code Playgroud)

您要根据原始数据绘制的拟合值为:

y_fit = exp(log_y_fit) = exp(m*log(x) + c)
Run Code Online (Sandbox Code Playgroud)

所以,你遇到的两个问题是:

  1. 您使用原始x坐标计算拟合值,而不是log(x)坐标

  2. 您正在绘制拟合y值的对数,而不将它们转换回原始比例

我通过替换为以下代码解决了这两个问题plt.plot(z, np.poly1d(np.polyfit(logA, logB, 1))(z)):

m, c = np.polyfit(logA, logB, 1) # fit log(y) = m*log(x) + c
y_fit = np.exp(m*logA + c) # calculate the fitted values of y 
plt.plot(z, y_fit, ':')
Run Code Online (Sandbox Code Playgroud)

这可以放在一行作为:plt.plot(z, np.exp(np.poly1d(np.polyfit(logA, logB, 1))(logA))),但我发现这使得调试更加困难.

以下代码中的其他一些不同之处:

  • 当你计算logAz过滤掉任何值<1时,你正在使用列表推导,但它z是一个线性范围,只有第一个值<1.z从1开始创建似乎更容易,这就是我编码它的方式.

  • 我不确定你为什么x*log(x)在你的列表理解中有这个术语logA.这看起来像是一个错误,所以我没有把它包括在答案中.

此代码应该适合您:

fig=plt.figure()
ax = fig.add_subplot(111)

z=np.arange(1, len(x)+1) #start at 1, to avoid error from log(0)

logA = np.log(z) #no need for list comprehension since all z values >= 1
logB = np.log(y)

m, c = np.polyfit(logA, logB, 1) # fit log(y) = m*log(x) + c
y_fit = np.exp(m*logA + c) # calculate the fitted values of y 

plt.plot(z, y, color = 'r')
plt.plot(z, y_fit, ':')

ax.set_yscale('symlog')
ax.set_xscale('symlog')
#slope, intercept = np.polyfit(logA, logB, 1)
plt.xlabel("Pre_referer")
plt.ylabel("Popularity")
ax.set_title('Pre Referral URL Popularity distribution')
plt.show()
Run Code Online (Sandbox Code Playgroud)

当我在模拟数据上运行它时,我得到以下图表:

带有拟合线的对数图

笔记: