前几天,清理出一些十年以前DOS下的程序及代码,看来目前也没什么用了,想打个包刻在光碟上,却发现有些代码现在可能还能起作用,其中就有计算一元回归和多元回归的代码,一看代码文件时间,居然是1993年的,于是稍作整理,存放在这,分析虽不十分完整,但一般应用是没问题的,最起码,可提供给那些刚学C的学生们参考。
先看看一元线性回归函数代码:
//求线性回归方程:Y=a+bx
//dada[rows*2]数组:X,Y;rows:数据行数;a,b:返回回归系数
//SquarePoor[4]:返回方差分析指标:回归平方和,剩余平方和,回归平方差,剩余平方差
//返回值:0求解成功,-1错误
intLinearRegression(double*data,introws,double*a,double*b,double*SquarePoor)
{
intm;
double*p,Lxx=0.0,Lxy=0.0,xa=0.0,ya=0.0;
if(data==0||a==0||b==0||rows<1)
return-1;
for(p=data,m=0;m<rows;m++)
{
xa+=*p++;
ya+=*p++;
}
xa/=rows;//X平均值
ya/=rows;//Y平均值
for(p=data,m=0;m<rows;m++,p+=2)
{
Lxx+=((*p-xa)*(*p-xa));//Lxx=Sum((X-Xa)平方)
Lxy+=((*p-xa)*(*(p+1)-ya));//Lxy=Sum((X-Xa)(Y-Ya))
}
*b=Lxy/Lxx;//b=Lxy/Lxx
*a=ya-*b*xa;//a=Ya-b*Xa
if(SquarePoor==0)
return0;
//方差分析
SquarePoor[0]=SquarePoor[1]=0.0;
for(p=data,m=0;m<rows;m++,p++)
{
Lxy=*a+*b**p++;
SquarePoor[0]+=((Lxy-ya)*(Lxy-ya));//U(回归平方和)
SquarePoor[1]+=((*p-Lxy)*(*p-Lxy));//Q(剩余平方和)
}
SquarePoor[2]=SquarePoor[0];//回归方差
SquarePoor[3]=SquarePoor[1]/(rows-2);//剩余方差
return0;
}
为了理解代码,把几个与代码有关的公式写在下面(回归理论和公式推导就免了,网上搜索到处是,下面的公式图片也是网上搜的,有些公式图形网上没找到或者不合适,可参见后面多元回归中的公式):
1、回归方程式:
2、回归系数:
其中:
3、回归平方和:
4、剩余平方和:
实例计算:
doubledata1[12][2]={
//XY
{187.1,25.4},
{179.5,22.8},
{157.0,20.6},
{197.0,21.8},
{239.4,32.4},
{217.8,24.4},
{227.1,29.3},
{233.4,27.9},
{242.0,27.8},
{251.9,34.2},
{230.0,29.2},
{271.8,30.0}
};
voidDisplay(double*dat,double*Answer,double*SquarePoor,introws,intcols)
{
doublev,*p;
inti,j;
printf("回归方程式: Y=%.5lf",Answer[0]);
for(i=1;i<cols;i++)
printf("+%.5lf*X%d",Answer[i],i);
printf(" ");
printf("回归显著性检验: ");
printf("回归平方和:%12.4lf回归方差:%12.4lf ",SquarePoor[0],SquarePoor[2]);
printf("剩余平方和:%12.4lf剩余方差:%12.4lf ",SquarePoor[1],SquarePoor[3]);
printf("离差平方和:%12.4lf标准误差:%12.4lf ",SquarePoor[0]+SquarePoor[1],sqrt(SquarePoor[3]));
printf("F检验:%12.4lf相关系数:%12.4lf ",SquarePoor[2]/SquarePoor[3],
sqrt(SquarePoor[0]/(SquarePoor[0]+SquarePoor[1])));
printf("剩余分析: ");
printf("观察值估计值剩余值剩余平方 ");
for(i=0,p=dat;i<rows;i++,p++)
{
v=Answer[0];
for(j=1;j<cols;j++,p++)
v+=*p*Answer[j];
printf("%12.2lf%12.2lf%12.2lf%12.2lf ",*p,v,*p-v,(*p-v)*(*p-v));
}
system("pause");
}
intmain()
{
doubleAnswer[2],SquarePoor[4];
if(LinearRegression((double*)data1,12,&Answer[0],&Answer[1],SquarePoor)==0)
Display((double*)data1,Answer,SquarePoor,12,2);
return0;
}
运行结果:
上面的函数和例子程序不仅计算了回归方程式,还计算了显著性检验指标,例如F检验指标,我们可以在统计F分布表上查到F0.01(1,10)=10.04(注:括号里的1,10分别为回归平方和和剩余平方和所拥有的自由度),小于计算的F检验值25.94,可以认为该回归例子高度显著。
如果使用图形界面,可以根据原始数据和计算结果绘制各种图表,如散点图、趋势图、控制图等。很多非线性方程可以借助数学计算,转化为直线方程进行回归分析。
同一元线性回归相比,多元线性回归分析代码可就复杂多了,必须求解线性方程,因此本代码中包含一个可独立使用的线性方程求解函数:
voidFreeData(double**dat,double*d,intcount)
{
inti,j;
free(d);
for(i=0;i<count;i++)
free(dat[i]);
free(dat);
}
//解线性方程。data[count*(count+1)]矩阵数组;count:方程元数;
//Answer[count]:求解数组。返回:0求解成功,-1无解或者无穷解
intLinearEquations(double*data,intcount,double*Answer)
{
intj,m,n;
doubletmp,**dat,*d=data;
dat=(double**)malloc(count*sizeof(double*));
for(m=0;m<count;m++,d+=(count+1))
{
dat[m]=(double*)malloc((count+1)*sizeof(double));
memcpy(dat[m],d,(count+1)*sizeof(double));
}
d=(double*)malloc((count+1)*sizeof(double));
for(m=0;m<count-1;m++)
{
//如果主对角线元素为0,行交换
for(n=m+1;n<count&&dat[m][m]==0.0;n++)
{
if(dat[n][m]!=0.0)
{
memcpy(d,dat[m],(count+1)*sizeof(double));
memcpy(dat[m],dat[n],(count+1)*sizeof(double));
memcpy(dat[n],d,(count+1)*sizeof(double));
}
}
//行交换后,主对角线元素仍然为0,无解,返回-1
if(dat[m][m]==0.0)
{
FreeData(dat,d,count);
return-1;
}
//消元
for(n=m+1;n<count;n++)
{
tmp=dat[n][m]/dat[m][m];
for(j=m;j<=count;j++)
dat[n][j]-=tmp*dat[m][j];
}
}
for(j=0;j<count;j++)
d[j]=0.0;
//求得count-1的元
Answer[count-1]=dat[count-1][count]/dat[count-1][count-1];
//逐行代入求各元
for(m=count-2;m>=0;m--)
{
for(j=count-1;j>m;j--)
d[m]+=Answer[j]*dat[m][j];
Answer[m]=(dat[m][count]-d[m])/dat[m][m];
}
FreeData(dat,d,count);
return0;
}
//求多元回归方程:Y=B0+B1X1+B2X2+...BnXn
//data[rows*cols]二维数组;X1i,X2i,...Xni,Yi(i=0torows-1)
//rows:数据行数;cols数据列数;Answer[cols]:返回回归系数数组(B0,B1...Bn)
//SquarePoor[4]:返回方差分析指标:回归平方和,剩余平方和,回归平方差,剩余平方差
//返回值:0求解成功,-1错误
intMultipleRegression(double*data,introws,intcols,double*Answer,double*SquarePoor)
{
intm,n,i,count=cols-1;
double*dat,*p,a,b;
if(data==0||Answer==0||rows<2||cols<2)
return-1;
dat=(double*)malloc(cols*(cols+1)*sizeof(double));
dat[0]=(double)rows;
for(n=0;n<count;n++)//n=0tocols-2
{
a=b=0.0;
for(p=data+n,m=0;m<rows;m++,p+=cols)
{
a+=*p;
b+=(*p**p);
}
dat[n+1]=a;//dat[0,n+1]=Sum(Xn)
dat[(n+1)*(cols+1)]=a;//dat[n+1,0]=Sum(Xn)
dat[(n+1)*(cols+1)+n+1]=b;//dat[n+1,n+1]=Sum(Xn*Xn)
for(i=n+1;i<count;i++)//i=n+1tocols-2
{
for(a=0.0,p=data,m=0;m<rows;m++,p+=cols)
a+=(p[n]*p[i]);
dat[(n+1)*(cols+1)+i+1]=a;//dat[n+1,i+1]=Sum(Xn*Xi)
dat[(i+1)*(cols+1)+n+1]=a;//dat[i+1,n+1]=Sum(Xn*Xi)
}
}
for(b=0.0,m=0,p=data+n;m<rows;m++,p+=cols)
b+=*p;
dat[cols]=b;//dat[0,cols]=Sum(Y)
for(n=0;n<count;n++)
{
for(a=0.0,p=data,m=0;m<rows;m++,p+=cols)
a+=(p[n]*p[count]);
dat[(n+1)*(cols+1)+cols]=a;//dat[n+1,cols]=Sum(Xn*Y)
}
n=LinearEquations(dat,cols,Answer);//计算方程式
//方差分析
if(n==0&&SquarePoor)
{
b=b/rows;//b=Y的平均值
SquarePoor[0]=SquarePoor[1]=0.0;
p=data;
for(m=0;m<rows;m++,p++)
{
for(i=1,a=Answer[0];i<cols;i++,p++)
a+=(*p*Answer[i]);//a=Ym的估计值
SquarePoor[0]+=((a-b)*(a-b));//U(回归平方和)
SquarePoor[1]+=((*p-a)*(*p-a));//Q(剩余平方和)(*p=Ym)
}
SquarePoor[2]=SquarePoor[0]/count;//回归方差
if (rows - cols > 0.0)
SquarePoor[3] = SquarePoor[1] / (rows - cols); // 剩余方差
else
SquarePoor[3] = 0.0;
}
free(dat);
returnn;
}
为了理解代码,同样贴几个主要公式在下面,其中回归平方和和剩余平方和公式和一元回归相同:
1、回归方程式:,
2、回归系数方程组:
3、F检验:
4、相关系数:,其中,Syy是离差平方和(回归平方和与剩余平方和之和)。该公式其实就是U/(U+Q)的平方根(没找到这个公式的图)。
5、回归方差:U / m,m为回归方程式中自变量的个数(没找到图)。
6、剩余方差:Q / (n - m - 1),n为观察数据的样本数,m同上(没找到图)。
7、标准误差:也叫标准误,就是剩余方差的平方根(没找到图)。
下面是一个多元回归的例子:
doubledata[15][5]={
//X1X2X3X4Y
{316,1536,874,981,3894},
{385,1771,777,1386,4628},
{299,1565,678,1672,4569},
{326,<span style
分享到:
相关推荐
C语言版的线性回归分析函数 本文档提供了一个使用C语言编写的线性回归分析函数,用于计算一元回归方程的回归系数和方差分析指标。该函数可以为刚学C语言的学生提供参考。 一、线性回归分析函数 线性回归分析函数...
C语言版的线性回归分析函数.pdf C语言版的线性回归分析函数是一个非常实用的文件,提供了线性回归分析的C语言实现代码。线性回归分析是一种常用的统计方法,用于研究变量之间的关系。该文件提供了一个简单的线性...
c语言描述的一元线性回归可以有效地解决数据统计中的问题
这是一个完美的任意元线性回归模型,使用c语言编写,采用初等变换实现,使用非常方便,只有2个函数,只要把要用到的函数拷到你的程序中即可。里面还附上逆阵的测试程序方便你验证,源文件使用.cpp或记事本打开
在这个“C语言线性回归计算器”项目中,我们将探讨如何使用C语言来实现线性回归算法,以便对一组数据点进行分析并得出最佳拟合直线。 在C语言中,线性回归涉及的主要概念包括数据结构(如数组)来存储输入的数据点...
c语言写的线性 回归分析方程和时间趋势分析方程,函数形式,源码下载
使用C语言实现多元线性回归需要定义矩阵运算函数,计算回归系数和残差平方和的平方根。通过这篇文章,我们可以了解多元线性回归的基本概念和C语言实现的步骤。 资源链接: * 多元线性回归的定义和数学模型 * C语言...
在C语言中实现多远线性回归方程通常涉及到矩阵运算和数值方法。在这个程序中,我们看到的主要目的是建立一个可以处理多个自变量的...程序还包含了数据预处理和结果输出的组件,使其成为一个完整的线性回归分析工具。
总的来说,本文深入讲解了利用C语言进行一元线性回归处理的知识点,包括相关关系与函数关系的异同点、C语言的特点、流程图在算法设计中的作用、线性回归分析的数学原理以及C语言在实现线性回归算法中的具体应用。...
Logistic回归是一种广泛应用的统计分析方法,主要用于二分类问题,如预测用户是否会购买产品或病人是否患有某种疾病。它的核心是构建一个Sigmoid函数,将线性组合的输入映射到0到1之间,代表了事件发生的概率。C语言...
本资源"用C编写的数据处理与回归分析函数"提供了一套用C语言编写的工具,旨在帮助开发者进行数据操作和统计建模。下面将详细介绍这些知识点。 首先,数据处理是数据分析的基石,它涉及到数据清洗、预处理、转换等多...
在给定的文档中,我们看到了几个使用R语言进行非线性回归分析的例子,涉及不同类型的非线性模型。 首先,文档中的`lm9.4p`例子展示了如何用线性回归对数据进行初步探索。`lm()`函数被用来建立一个线性模型,其中`...
这些步骤是线性回归分析的基础。 接下来,代码进入一个迭代过程,寻找最优的自变量子集。迭代条件由`while(it==1)`控制,`it`标记是否有变量需要添加或删除。在每次迭代中,它会检查所有非对角线元素的绝对值,找出...
最小二乘法是一种在数据拟合中广泛应用的数学方法,特别是在线性回归分析中。它通过寻找一组参数,使得预测值与实际观测值之间的残差平方和最小,从而得到最佳的拟合直线或曲线。这种方法在工程、统计学、物理学等...
线性拟合的目标函数通常为残差平方和,即所有数据点到直线的垂直距离的平方和,我们需要找到使这个和最小的a和b。 在C语言中,我们可以使用以下步骤实现线性拟合: 1. **数据准备**:定义结构体或数组存储数据点,...
3. 数学和统计库:C语言本身没有内置的统计函数,但可以通过引入如GNU Scientific Library (GSL)这样的外部库来执行线性回归、时间序列分析或其他预测模型的计算。 4. 算法实现:预测模型可能包括简单的线性回归、...
它结合了主成分分析(PCA)和线性回归的优点,旨在找到一组新的线性组合(即偏最小二乘载荷),使得这些组合既能够最大化样本间的差异(解释变量的方差),又能够最好地预测目标变量。这种方法特别适用于变量之间...