使用Matplotlib绘制三维线性模型
我正在尝试为一个数据集创建一个线性模型的三维图。我在R语言中相对容易地完成了这个任务,但在Python中却遇到了很大的困难。以下是我在R中做的:
这是我在Python中做的:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import statsmodels.formula.api as sm
csv = pd.read_csv('http://www-bcf.usc.edu/~gareth/ISL/Advertising.csv', index_col=0)
model = sm.ols(formula='Sales ~ TV + Radio', data = csv)
fit = model.fit()
fit.summary()
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter(csv['TV'], csv['Radio'], csv['Sales'], c='r', marker='o')
xx, yy = np.meshgrid(csv['TV'], csv['Radio'])
# Not what I expected :(
# ax.plot_surface(xx, yy, fit.fittedvalues)
ax.set_xlabel('TV')
ax.set_ylabel('Radio')
ax.set_zlabel('Sales')
plt.show()
我哪里做错了,应该怎么做呢?
谢谢。
2 个回答
12
明白了!
我在mdurant的回答评论中提到的问题是,表面没有像这些结合散点图和表面图那样绘制成漂亮的方形图案。
我意识到问题出在我的meshgrid
上,所以我修正了两个范围(x
和y
),并为np.arange
使用了成比例的步长。
这样我就可以使用mdurant回答中提供的代码,结果非常完美!
这是结果:
这是代码:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import statsmodels.formula.api as sm
from matplotlib import cm
csv = pd.read_csv('http://www-bcf.usc.edu/~gareth/ISL/Advertising.csv', index_col=0)
model = sm.ols(formula='Sales ~ TV + Radio', data = csv)
fit = model.fit()
fit.summary()
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
x_surf = np.arange(0, 350, 20) # generate a mesh
y_surf = np.arange(0, 60, 4)
x_surf, y_surf = np.meshgrid(x_surf, y_surf)
exog = pd.core.frame.DataFrame({'TV': x_surf.ravel(), 'Radio': y_surf.ravel()})
out = fit.predict(exog = exog)
ax.plot_surface(x_surf, y_surf,
out.reshape(x_surf.shape),
rstride=1,
cstride=1,
color='None',
alpha = 0.4)
ax.scatter(csv['TV'], csv['Radio'], csv['Sales'],
c='blue',
marker='o',
alpha=1)
ax.set_xlabel('TV')
ax.set_ylabel('Radio')
ax.set_zlabel('Sales')
plt.show()
4
你说得对,plot_surface确实需要一个坐标的网格(meshgrid)来进行绘图,但predict则需要一种和你之前用来拟合的数据结构(也就是“exog”)。
exog = pd.core.frame.DataFrame({'TV':xx.ravel(),'Radio':yy.ravel()})
out = fit.predict(exog=exog)
ax.plot_surface(xx, yy, out.reshape(xx.shape), color='None')