【问题标题】:Adding a line to a matplotlib scatterplot based on a slope根据斜率向 matplotlib 散点图中添加一条线
【发布时间】:2015-07-23 09:56:17
【问题描述】:

我有一个从 DataFrame 构建的散点图 - 它显示了两个变量的相关性 - 长度和年龄

import matplotlib.pyplot as plt
df = DataFrame (......)
plt.title ('Fish Length vs Age')
plt.xlabel('Length')
plt.ylabel('Age (days)')
plt.scatter(df['length'],df['age'])

现在我想在这个散点图中添加一条斜率为 0.88 的线。我该怎么做?

附:我设法找到使用点而不是坡度来画线的所有示例

更新。我重新阅读了这个理论 - 事实证明,应该根据数据点绘制相关系数的事实是我编造的:) 部分原因是我脑海中的这张图片

但是我仍然对 matplotlib 的线条绘图功能感到困惑

【问题讨论】:

  • 您可以将 Pearson 相关系数设为 0.88 以获取无限多的线 - r 值 (PCC) 不会告诉您线的斜率,它会告诉您数据点的距离那个“最合适的线”。您能否编辑您的问题以阐明您希望 slope 是什么?
  • @KirstieJane 我已经更新了问题:)
  • @iX3 链接到问题中的 Pearson 相关系数没有意义。斜率与它无关,应该删除参考。
  • @KirstieJane,对此感到抱歉。看起来有人在没有任何解释的情况下改变了 OP 的问题;这就是我拒绝删除的原因。我现在会尝试纠正它。

标签: python pandas matplotlib


【解决方案1】:

相关系数不会给出回归线的斜率,因为您的数据处于不同的尺度。如果您想用回归线绘制散点图,我建议您在seaborn 中使用最少的代码行。

要安装seaborn

pip install seaborn

代码示例:

import numpy as np
import pandas as pd
import seaborn as sns

# simulate some artificial data
# =====================================
df = pd.DataFrame(np.random.multivariate_normal([10, 100], [[100, 800], [800, 10000]], size=100), columns=['X', 'Y'])

df

# plot 
# ====================================
sns.set_style('ticks')
sns.regplot(df.X, df.Y, ci=None)
sns.despine()  

编辑:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# simulate some artificial data
# =====================================
df = pd.DataFrame(np.random.multivariate_normal([10, 100], [[100, 800], [800, 10000]], size=100), columns=['X', 'Y'])


# plot
# ==============================
fig, ax = plt.subplots()
ax.scatter(df.X, df.Y)

# need a slope and c to fix the position of line
slope = 10
c = -100

x_min, x_max = ax.get_xlim()
y_min, y_max = c, c + slope*(x_max-x_min)
ax.plot([x_min, x_max], [y_min, y_max])
ax.set_xlim([x_min, x_max])

【讨论】:

  • 不不不!! :) 我还没有绘制回归线 :) 我现在只想绘制具有给定斜率的单线 :) 你能帮忙只使用 matplotlib 吗?
  • @Dennis 一条以相关系数为斜率的线在散点图的上下文中毫无意义,因为您的 x-y 比例不匹配。要明白我的意思,请尝试在散点图上绘制 y = c + 0.88x,当 x 从 1000 增加到 2000 时,y 应该增加 880。你的 y 比例是多少? [0,160] 不适合。回归斜率给出了correlation * sigma_y / sigma_x,它解释了这种缩放问题。
  • 我明白你在说什么,非常感谢你如此明确的解释!但是 :) 如果我改写我的问题“我如何在 matplotlib 中用给定的斜率画一条线?”怎么办?你能帮我解决这个简单的问题,暂时忘记回归和相关性吗? :) 请放心
  • @Dennis 好的,我已经编辑了答案以使用 .plot 用两点绘制一条线。
【解决方案2】:

基于@JinxunLi 的答案,您只想添加一条连接两点的线。

这两个点具有 x 和 y 坐标,因此对于这两个点,您将有四个数字:x_0y_0x_1y_1

假设您希望这两个点的 x 坐标跨越 x 轴,因此您将手动设置 x_0x_1

x_0 = 0
x_1 = 5000

或者,您可以只取轴的最小值和最大值:

x_min, x_max = ax.get_xlim()
x_0 = x_min
x_1 = x_max

您将直线的斜率定义为increase in y / increase in x,即:

slope = (y_1 - y_0) / (x_1 - x_0)

这可以重新排列为:

(y_1 - y_0) = slope * (x_1 - x_0)

这个斜率有无数条平行线,所以我们必须从其中一个点开始。对于此示例,假设您希望线路通过原点 (0,0)

x_0 = 0 # We already know this as it was set earlier
y_0 = 0

现在您可以将y_1 的公式重新排列为:

y_1 = slope * (x_1 - x_0) + y_0

如果您知道希望斜率为 0.88,那么您可以计算另一点的 y 位置:

y_1 = 0.88 * (5000 - 0) + 0

对于您在问题中提供的数据,一条斜率为 0.88 的线会很快飞离 y 轴的顶部(上例中的y_1 = 4400)。

在下面的示例中,我输入了一条斜率 = 0.03 的线。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# simulate some artificial data
# =====================================
df = pd.DataFrame( { 'Age' : np.random.rand(25) * 160 } )

df['Length'] = df['Age'] * 0.88 + np.random.rand(25) * 5000

# plot those data points
# ==============================
fig, ax = plt.subplots()
ax.scatter(df['Length'], df['Age'])

# Now add on a line with a fixed slope of 0.03
slope = 0.03

# A line with a fixed slope can intercept the axis
# anywhere so we're going to have it go through 0,0
x_0 = 0
y_0 = 0

# And we'll have the line stop at x = 5000
x_1 = 5000
y_1 = slope (x_1 - x_0) + y_0

# Draw these two points with big triangles to make it clear
# where they lie
ax.scatter([x_0, x_1], [y_0, y_1], marker='^', s=150, c='r')

# And now connect them
ax.plot([x_0, x_1], [y_0, y_1], c='r')    

plt.show()

【讨论】:

  • 刚刚意识到您需要在 matplotlib 中限制一行 - id 没有“无限”的概念//再次感谢
猜你喜欢
  • 1970-01-01
  • 2015-06-29
  • 1970-01-01
  • 1970-01-01
  • 2019-05-06
  • 2021-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多