regplot 返回的 bin 数据每个 运行 都略有变化

bin data returned by regplot changed slightly for each running

我想绘制基于平均值的回归图。我用的是seaborn的regplot,但是发现回归函数在每个运行处都有细微的变化。你知道怎么解决吗?谢谢。

这里是测试脚本,你可能会发现R2每次都变了

import numpy as np
import pandas as pd
import seaborn as sns
from sklearn import linear_model
from sklearn.metrics import mean_squared_error, r2_score


# Plot barplot with linear fit
def get_data_XYE(p):
    x_list = []
    lower_list = []
    upper_list = []
    for line in p.lines:
        x_list.append(line.get_xdata()[0])
        lower_list.append(line.get_ydata()[0])
        upper_list.append(line.get_ydata()[1])
    y = 0.5 * (np.asarray(lower_list) + np.asarray(upper_list))
    y_error = np.asarray(upper_list) - y
    x = np.asarray(x_list)
    return x, y, y_error

thres = 140
reg = linear_model.LinearRegression()

H = pd.DataFrame([48,22,27,35,49,142,141,151,151,305,841,726,566,222,86,187,103,176,81,96,304,170,
                  109,123,281,210,534,680,594,327,371,674,39,7,14,29,136,36,55,61,99,146,6,9,17,91,
                  192,194,195,209,207,220,238,197,227,229,14,90,73,109,7,8,52,84,6,30,20,36,113,22,
                  55,124,59,58,52,73,69,58,49,39,136,251,84,48,88,100,93,112,150,151,163,173,134,
                  468,296,103,81,84,127,392,55,80,54,45,51,72,62,54,54,82,105,49,265,130,95,81,54,
                  123,98,67,39,117,140,83,102,92,106,90,57,59,43,87,79,111,95,87,112,35,26,68,37,74,
                  92,113,104,103,74,74,179,173,285,286,166,157,221,177,147,152,144,181,16,182,185,
                  170,165,143,142,35,35,77,97,54,48,264,29,43,157,154,492,261,276,181,115,85,92,157,
                  334,132,16,75,75,235,375,361,303,48,108,145,137,70,63,56,56,62,86,145,41,94,549,
                  256,39,159,153,13,13,14,14,204,192,88,140,94,83,219,190,113,87,94])
R = pd.DataFrame([37,40,30,29,24,23,27,12,21,20,34,29,28,27,32,23,29,28,22,28,23,24,29,32,23,18,25,
                  22,29,12,12,14,29,31,30,34,31,22,40,25,36,27,27,29,35,33,25,25,27,27,19,35,26,18,
                  24,25,37,52,47,34,39,40,48,41,44,35,36,53,46,38,44,23,26,26,28,27,21,25,21,20,27,
                  35,24,46,34,22,30,30,30,31,26,25,28,21,31,24,27,33,21,31,33,29,33,32,21,25,22,39,
                  31,34,26,23,18,20,18,34,25,20,12,23,25,21,21,25,31,17,27,28,29,25,24,25,21,24,27,
                  23,22,23,22,22,26,22,19,26,35,33,35,29,26,26,30,22,32,33,33,28,32,26,29,36,37,37,
                  28,24,30,25,20,29,24,33,35,30,32,31,33,40,35,37,24,34,29,27,24,36,26,26,26,27,27,
                  20,17,28,26,34,18,20,20,18,19,23,20,22,25,32,44,41,39,41,40,40,44,36,42,31,32,26,
                  29,23,29,29,28,31,22,29,24,28,28,25])
dat = pd.merge(H,R,left_index=True,right_index=True)
dat.columns=['H','R']

breaks = [6.0,39.0,75.0,117.0,159.0,197.0,238.0,305.0,392.0,492.0,594.0,726.0,841.0]
g = sns.regplot(x='H',y='R',data=dat,fit_reg=False,x_bins=breaks)
dat = get_data_XYE(g)
x = dat[0].reshape(-1,1)
y = dat[1].reshape(-1,1)
mask = x<thres
reg.fit(x[mask].reshape(-1, 1),y[mask])
yp = reg.coef_*x[mask]+reg.intercept_
r2 = r2_score(y[mask],yp)
g.axes.plot(x[mask], yp, color='red', linewidth=3)
g.axes.legend(labels=[r'$y={:.2f}x+{:.2f},R^2={:.4f}$'.format(reg.coef_.squeeze(),
              reg.intercept_.squeeze(),r2)],loc='upper right')
y

您在回归中使用因变量的置信区间范围的中点。但是置信区间是使用百分位数 bootstrap 计算的,因此 a) 会有一些随机性(用 seed= 控制)并且 b) 它们不会对称(所以这可能不是你想要的来解决你的问题)。