import numpy as np
np.set_printoptions(precision=4) #设置numpy输出精度
x=np.linspace(-4,4,20) #构建[-4,4]上 x 的数据向量
x
array([-4. , -3.5789, -3.1579, -2.7368, -2.3158, -1.8947, -1.4737, -1.0526, -0.6316, -0.2105, 0.2105, 0.6316, 1.0526, 1.4737, 1.8947, 2.3158, 2.7368, 3.1579, 3.5789, 4. ])
np.random.seed(1) #设置随机种子数以便重复结果
e=np.random.randn(20) #随机误差数据向量 e~N(0,1)
e
array([ 1.6243, -0.6118, -0.5282, -1.073 , 0.8654, -2.3015, 1.7448, -0.7612, 0.319 , -0.2494, 1.4621, -2.0601, -0.3224, -0.3841, 1.1338, -1.0999, -0.1724, -0.8779, 0.0422, 0.5828])
import matplotlib.pyplot as plt
y1=x; plt.plot(x,y1,'o'); #完全正相关 y=x
y2=-x; plt.plot(x,y2,'o'); #完全负相关 y=-x
y3=x+e; plt.plot(x,y3,'o'); #正相关 y=x+e
y4=-x+e; plt.plot(x,y4,'o'); #负相关 y=-x+e
fig,ax=plt.subplots(2,2,figsize=(10,8)) #将上述四个图放到一页上
ax[0,0].plot(x,y1,'o'); ax[0,1].plot(x,y2,'o')
ax[1,0].plot(x,y3,'o'); ax[1,1].plot(x,y4,'o');
plt.plot(x,y1,'o');
np.corrcoef([x,y1])
array([[1., 1.], [1., 1.]])
plt.plot(x,y2,'o');
np.corrcoef([x,y2])
array([[ 1., -1.], [-1., 1.]])
plt.plot(x,y3,'o');
np.corrcoef([x,y3])[0,1]
0.907917278678589
plt.plot(x,y4,'o');
np.corrcoef(x,y4)[0,1]
-0.9140292045707705
np.corrcoef([x,y1,y2,y3,y4])
array([[ 1. , 1. , -1. , 0.9079, -0.914 ], [ 1. , 1. , -1. , 0.9079, -0.914 ], [-1. , -1. , 1. , -0.9079, 0.914 ], [ 0.9079, 0.9079, -0.9079, 1. , -0.6598], [-0.914 , -0.914 , 0.914 , -0.6598, 1. ]])
import pandas as pd #构建模拟数据的数据框
pd.set_option('display.max_rows', 10)
xy=pd.DataFrame({'x':x,'y1':y1,'y2':y2,'y3':y3,'y4':y4});xy
x | y1 | y2 | y3 | y4 | |
---|---|---|---|---|---|
0 | -4.000000 | -4.000000 | 4.000000 | -2.375655 | 5.624345 |
1 | -3.578947 | -3.578947 | 3.578947 | -4.190704 | 2.967191 |
2 | -3.157895 | -3.157895 | 3.157895 | -3.686066 | 2.629723 |
3 | -2.736842 | -2.736842 | 2.736842 | -3.809811 | 1.663873 |
4 | -2.315789 | -2.315789 | 2.315789 | -1.450382 | 3.181197 |
... | ... | ... | ... | ... | ... |
15 | 2.315789 | 2.315789 | -2.315789 | 1.215898 | -3.415681 |
16 | 2.736842 | 2.736842 | -2.736842 | 2.564414 | -2.909270 |
17 | 3.157895 | 3.157895 | -3.157895 | 2.280036 | -4.035753 |
18 | 3.578947 | 3.578947 | -3.578947 | 3.621161 | -3.536734 |
19 | 4.000000 | 4.000000 | -4.000000 | 4.582815 | -3.417185 |
20 rows × 5 columns
xy.corrwith(xy.x)
x 1.000000 y1 1.000000 y2 -1.000000 y3 0.907917 y4 -0.914029 dtype: float64
xy.corr() #根据数据框计算相关系数矩阵
x | y1 | y2 | y3 | y4 | |
---|---|---|---|---|---|
x | 1.000000 | 1.000000 | -1.000000 | 0.907917 | -0.914029 |
y1 | 1.000000 | 1.000000 | -1.000000 | 0.907917 | -0.914029 |
y2 | -1.000000 | -1.000000 | 1.000000 | -0.907917 | 0.914029 |
y3 | 0.907917 | 0.907917 | -0.907917 | 1.000000 | -0.659836 |
y4 | -0.914029 | -0.914029 | 0.914029 | -0.659836 | 1.000000 |
pd.plotting.scatter_matrix(xy,figsize=(9,8)); #矩阵散点图
import pandas as pd #读取BSdata分析用数据
BS=pd.read_excel('DaPy_data.xlsx','BSdata')[['性别','身高','体重','支出']];BS
性别 | 身高 | 体重 | 支出 | |
---|---|---|---|---|
0 | 女 | 167 | 71 | 46.0 |
1 | 男 | 171 | 68 | 10.4 |
2 | 女 | 175 | 73 | 21.0 |
3 | 男 | 169 | 74 | 4.9 |
4 | 男 | 154 | 55 | 25.9 |
... | ... | ... | ... | ... |
47 | 男 | 175 | 68 | 44.4 |
48 | 女 | 166 | 65 | 5.3 |
49 | 女 | 159 | 58 | 71.4 |
50 | 女 | 169 | 73 | 5.5 |
51 | 女 | 165 | 67 | 56.8 |
52 rows × 4 columns
plt.plot(BS['身高'],BS['体重'],'o');
BS['身高'].corr(BS['体重']) #BS.身高.corr(BS.体重)
0.9118170987010521
BS[['身高','体重']].corr()
身高 | 体重 | |
---|---|---|
身高 | 1.000000 | 0.911817 |
体重 | 0.911817 | 1.000000 |
BS.corr()
身高 | 体重 | 支出 | |
---|---|---|---|
身高 | 1.000000 | 0.911817 | 0.043881 |
体重 | 0.911817 | 1.000000 | 0.042946 |
支出 | 0.043881 | 0.042946 | 1.000000 |
plt.rcParams['font.sans-serif']=['SimSun']; #设置中文字体为'宋体'
pd.plotting.scatter_matrix(BS,figsize=(9,8)); #矩阵散点图
import scipy.stats as st #加载统计分析方法包
st.pearsonr(x,y1) #pearson相关及检验
(0.9999999999999998, 1.2459683851238692e-139)
st.pearsonr(x,y2)
(-0.9999999999999998, 1.2459683851238692e-139)
st.pearsonr(x,y3)
(0.9079172786785887, 3.2236304802662254e-08)
st.pearsonr(x,y4)
(-0.9140292045707707, 1.7775582357873907e-08)
plt.plot(BS['身高'],BS['体重'],'o');
st.pearsonr(BS.身高,BS.体重)
(0.9118170987010525, 5.7473293164451325e-21)
plt.plot(BS['身高'],BS.支出,'o');
st.pearsonr(BS.身高,BS.支出)
(0.04388113075958894, 0.7574067077940487)
# 定义模拟直线回归函数
import statsmodels.api as sm #加载统计模型包
def reglinedemo(n=20): #模拟样本例数
x=np.arange(n)+1 #自变量取值
e=np.random.normal(0,1,n) #误差项
y=2+0.5*x+e #因变量值
x1=sm.add_constant(x);x1 #加常数项
fm=sm.OLS(y,x1).fit();fm #模型拟合,见下
plt.plot(x,y,'.',x,fm.fittedvalues,'r-'); #添加回归线,红色
for i in range(len(x)): #画垂直线
plt.vlines(x,y,fm.fittedvalues,linestyles='dotted',colors='b');
np.random.seed(12)
reglinedemo(20)
np.random.seed(12)
reglinedemo(40)
y=BS.体重; x=BS.身高
plt.plot(x,y,'o');
import statsmodels.api as sm #加载线性回归模型库
fm1=sm.OLS(y,sm.add_constant(x)).fit() #最小二乘估计,加常数项
fm1.params #模型参数的估计值
C:\Users\Lenovo\anaconda3\lib\site-packages\statsmodels\tsa\tsatools.py:142: FutureWarning: In a future version of pandas all arguments of concat except for the argument 'objs' will be keyword-only x = pd.concat(x[::order], 1)
const -79.282827 身高 0.876949 dtype: float64
yfit=fm1.fittedvalues #拟合估计值
plt.plot(x, y,'.',x,yfit, 'r-');
fm1.tvalues #模型系数t值
const -8.414938 身高 15.702810 dtype: float64
fm1.pvalues #系数检验p值
const 3.820690e-11 身高 5.747329e-21 dtype: float64
pd.DataFrame({'b':fm1.params,'t':fm1.tvalues,'p':fm1.pvalues}) #格式输出
b | t | p | |
---|---|---|---|
const | -79.282827 | -8.414938 | 3.820690e-11 |
身高 | 0.876949 | 15.702810 | 5.747329e-21 |
import pandas as pd #读取BSdata分析用数据
BS=pd.read_excel('DaPy_data.xlsx','BSdata')[['性别','身高','体重','支出']];BS
性别 | 身高 | 体重 | 支出 | |
---|---|---|---|---|
0 | 女 | 167 | 71 | 46.0 |
1 | 男 | 171 | 68 | 10.4 |
2 | 女 | 175 | 73 | 21.0 |
3 | 男 | 169 | 74 | 4.9 |
4 | 男 | 154 | 55 | 25.9 |
... | ... | ... | ... | ... |
47 | 男 | 175 | 68 | 44.4 |
48 | 女 | 166 | 65 | 5.3 |
49 | 女 | 159 | 58 | 71.4 |
50 | 女 | 169 | 73 | 5.5 |
51 | 女 | 165 | 67 | 56.8 |
52 rows × 4 columns
import statsmodels.formula.api as smf #加载公式模型建立包
fm2=smf.ols('体重~身高',data=BS).fit()
fm2.summary().tables[1] #回归系数检验表,来自summary的第2张表
coef | std err | t | P>|t| | [0.025 | 0.975] | |
---|---|---|---|---|---|---|
Intercept | -79.2828 | 9.422 | -8.415 | 0.000 | -98.207 | -60.359 |
身高 | 0.8769 | 0.056 | 15.703 | 0.000 | 0.765 | 0.989 |
fm2.summary().tables[0]
Dep. Variable: | 体重 | R-squared: | 0.831 |
---|---|---|---|
Model: | OLS | Adj. R-squared: | 0.828 |
Method: | Least Squares | F-statistic: | 246.6 |
Date: | Tue, 24 Aug 2021 | Prob (F-statistic): | 5.75e-21 |
Time: | 15:42:05 | Log-Likelihood: | -133.21 |
No. Observations: | 52 | AIC: | 270.4 |
Df Residuals: | 50 | BIC: | 274.3 |
Df Model: | 1 | ||
Covariance Type: | nonrobust |
fm2.summary().tables[2]
Omnibus: | 6.599 | Durbin-Watson: | 2.161 |
---|---|---|---|
Prob(Omnibus): | 0.037 | Jarque-Bera (JB): | 5.704 |
Skew: | -0.782 | Prob(JB): | 0.0577 |
Kurtosis: | 3.434 | Cond. No. | 3.58e+03 |
fm3=smf.ols('体重~身高+支出',data=BS).fit()
fm3.summary().tables[1] #回归系数检验表,来自summary的第2张表
coef | std err | t | P>|t| | [0.025 | 0.975] | |
---|---|---|---|---|---|---|
Intercept | -79.2878 | 9.518 | -8.331 | 0.000 | -98.414 | -60.161 |
身高 | 0.8768 | 0.056 | 15.528 | 0.000 | 0.763 | 0.990 |
支出 | 0.0011 | 0.021 | 0.050 | 0.960 | -0.041 | 0.044 |
fm3.summary()
Dep. Variable: | 体重 | R-squared: | 0.831 |
---|---|---|---|
Model: | OLS | Adj. R-squared: | 0.825 |
Method: | Least Squares | F-statistic: | 120.8 |
Date: | Tue, 24 Aug 2021 | Prob (F-statistic): | 1.14e-19 |
Time: | 15:42:05 | Log-Likelihood: | -133.21 |
No. Observations: | 52 | AIC: | 272.4 |
Df Residuals: | 49 | BIC: | 278.3 |
Df Model: | 2 | ||
Covariance Type: | nonrobust |
coef | std err | t | P>|t| | [0.025 | 0.975] | |
---|---|---|---|---|---|---|
Intercept | -79.2878 | 9.518 | -8.331 | 0.000 | -98.414 | -60.161 |
身高 | 0.8768 | 0.056 | 15.528 | 0.000 | 0.763 | 0.990 |
支出 | 0.0011 | 0.021 | 0.050 | 0.960 | -0.041 | 0.044 |
Omnibus: | 6.641 | Durbin-Watson: | 2.165 |
---|---|---|---|
Prob(Omnibus): | 0.036 | Jarque-Bera (JB): | 5.744 |
Skew: | -0.784 | Prob(JB): | 0.0566 |
Kurtosis: | 3.440 | Cond. No. | 3.62e+03 |
%run init.py
fm2.predict(pd.DataFrame({'身高':[170]})) #估计
0 69.7986 dtype: float64
fm2.predict(pd.DataFrame({'身高':[190]})) #预测
0 87.3375 dtype: float64
fm2.predict(pd.DataFrame({'身高': [170,180,190]})) #估计与预测
0 69.7986 1 78.5681 2 87.3375 dtype: float64
BS_M=BS[BS.性别=='男'][['身高','体重']];BS_M
身高 | 体重 | |
---|---|---|
1 | 171 | 68 |
3 | 169 | 74 |
4 | 154 | 55 |
5 | 183 | 76 |
9 | 173 | 63 |
... | ... | ... |
37 | 178 | 78 |
40 | 158 | 60 |
45 | 169 | 65 |
46 | 166 | 70 |
47 | 175 | 68 |
27 rows × 2 columns
BS_F=BS[BS.性别=='女'][['身高','体重']];BS_F
身高 | 体重 | |
---|---|---|
0 | 167 | 71 |
2 | 175 | 73 |
6 | 169 | 71 |
7 | 166 | 66 |
8 | 165 | 69 |
... | ... | ... |
44 | 164 | 62 |
48 | 166 | 65 |
49 | 159 | 58 |
50 | 169 | 73 |
51 | 165 | 67 |
25 rows × 2 columns
import scipy.stats as st
M_r=st.pearsonr(BS_M.身高,BS_M.体重);M_r
(0.9105200024864898, 4.43657339837424e-11)
import warnings
warnings.filterwarnings("ignore") #忽略警告信息
import seaborn as sns
sns.jointplot('身高','体重',data=BS_M); #直方图+散点图
#plt.plot(BS_F.身高,BS_F.体重,'o');
#plt.title(M_r);
st.pearsonr(BS_F.身高,BS_F.体重)
(0.8931328371576219, 1.907324154689927e-09)
sns.jointplot('身高','体重',data=BS_F);
smf.ols('体重~身高',data=BS_M).fit().summary().tables[1]
coef | std err | t | P>|t| | [0.025 | 0.975] | |
---|---|---|---|---|---|---|
Intercept | -85.4332 | 14.189 | -6.021 | 0.000 | -114.657 | -56.210 |
身高 | 0.9101 | 0.083 | 11.011 | 0.000 | 0.740 | 1.080 |
sns.regplot(y="体重",x="身高",data=BS_M,ci=0);
sns.jointplot('身高','体重',data=BS_M,kind='reg');
smf.ols('体重~身高',data=BS_F).fit().summary().tables[1]
coef | std err | t | P>|t| | [0.025 | 0.975] | |
---|---|---|---|---|---|---|
Intercept | -80.3893 | 15.405 | -5.218 | 0.000 | -112.257 | -48.522 |
身高 | 0.8867 | 0.093 | 9.523 | 0.000 | 0.694 | 1.079 |
sns.regplot(y='体重',x='身高',data=BS_F,ci=0);
sns.jointplot('身高','体重',data=BS_F,kind='reg',ci=0);
from plotnine import *
theme_set(theme_bw(base_family='SimSun'));
(ggplot(BS,aes('身高','体重')) + geom_point() + facet_wrap('性别',nrow=1)
+ stat_smooth(method='lm',se=True)) #无可信区间的回归线
<ggplot: (135948302333)>
(ggplot(BS,aes('身高','体重')) + geom_point() + facet_wrap('性别',nrow=2)
+ stat_smooth(method='lm',se=False)) #有可信区间的回归线
<ggplot: (135948459261)>