我正在对大约120万个观测值进行约45,000次本地线性回归(基本上是这样),因此我希望能得到一些帮助,以加快速度,因为我很不耐烦。
我基本上正在尝试构建按年份和职位划分的工资合同--函数工资(给定公司、年份、职位经验)--适用于一堆公司。
以下是我正在处理的数据(基本结构)集:
> wages
firm year position exp salary
1: 0007 1996 4 1 20029
2: 0007 1996 4 1 23502
3: 0007 1996 4 1 22105
4: 0007 1996 4 2 23124
5: 0007 1996 4 2 22700
---
1175141: 994 2012 5 2 47098
1175142: 994 2012 5 2 45488
1175143: 994 2012 5 2 47098
1175144: 994 2012 5 3 45488
1175145: 994 2012 5 3 47098
我希望构建所有公司的经验水平从0到40的工资函数,例如:
> salary_scales
firm year position exp salary
1: 0007 1996 4 0 NA
2: 0007 1996 4 1 21878.67
3: 0007 1996 4 2 23401.33
4: 0007 1996 4 3 23705.00
5: 0007 1996 4 4 24260.00
---
611019: 9911 2015 4 36 NA
611020: 9911 2015 4 37 NA
611021: 9911 2015 4 38 NA
611022: 9911 2015 4 39 NA
611023: 9911 2015 4 40 NA
为此,我按照@BondedDust的建议(在这里)使用了COBS(受限B样条)软件包,使我能够将工资合同的单调性融入到模型中。
但仍存在一些问题; 特别是在我需要外推时(每个公司没有年轻员工或老龄员工),拟合曲线往往会失去单调性或低于0。
为了解决这个问题,我使用简单的线性外推来扩大数据边界 - 在
min_exp
和max_exp
之外延伸拟合曲线,使其通过最低(或最高)的两个拟合点——虽然不完美,但似乎效果不错。考虑到这一点,这是我的工作方式(请记住我是
data.table
的狂热者):#get the range of experience for each firm
wages[,min_exp:=min(exp),by=.(year,firm,position)]
wages[,max_exp:=max(exp),by=.(year,firm,position)]
#Can't interpolate if there are only 2 or 3 unique experience cells represented
wages[,node_count:=length(unique(exp)),by=.(year,firm,position)]
#Nor if there are too few teachers
wages[,ind_count:=.N,by=.(year,firm,position)]
#Also troublesome when there is little variation in salaries like so:
wages[,sal_scale_flag:=mean(abs(salary-mean(salary)))<50,by=.(year,firm,position)]
wages[,sal_count_flag:=length(unique(salary))<5,by=.(year,firm,position)]
cobs_extrap<-function(exp,salary,min_exp,max_exp,
constraint="increase",print.mesg=F,nknots=8,
keep.data=F,maxiter=150){
#these are passed as vectors
min_exp<-min_exp[1]
max_exp<-min(max_exp[1],40)
#get in-sample fit
in_sample<-predict(cobs(x=exp,y=salary,
constraint=constraint,
print.mesg=print.mesg,nknots=nknots,
keep.data=keep.data,maxiter=maxiter),
z=min_exp:max_exp)[,"fit"]
#append by linear extension below min_exp
c(if (min_exp==1) NULL else in_sample[1]-
(min_exp:1)*(in_sample[2]-in_sample[1]),in_sample,
#append by linear extension above max_exp
if (max_exp==40) NULL else in_sample[length(in_sample)]+(1:(40-max_exp))*
(in_sample[length(in_sample)]-in_sample[length(in_sample)-1]))
}
salary_scales<-
wages[node_count>=7&ind_count>=10
&sal_scale_flag==0&sal_count_flag==0,
.(exp=0:40,
salary=cobs_extrap(exp,salary,min_exp,max_exp)),
by=.(year,firm,position)]
有没有什么特别的事情可能会拖慢我的代码?还是我必须耐心等待?
以下是一些较小的公司-职位组合,可以进行试玩:
firm year position exp salary count
1: 0063 2010 5 2 37433 10
2: 0063 2010 5 2 38749 10
3: 0063 2010 5 4 38749 10
4: 0063 2010 5 8 42700 10
5: 0063 2010 5 11 47967 10
6: 0063 2010 5 15 50637 10
7: 0063 2010 5 19 51529 10
8: 0063 2010 5 23 50637 10
9: 0063 2010 5 33 52426 10
10: 0063 2010 5 37 52426 10
11: 9908 2006 4 1 26750 10
12: 9908 2006 4 6 36043 10
13: 9908 2006 4 7 20513 10
14: 9908 2006 4 8 45023 10
15: 9908 2006 4 13 33588 10
16: 9908 2006 4 15 46011 10
17: 9908 2006 4 15 37179 10
18: 9908 2006 4 22 43704 10
19: 9908 2006 4 28 56078 10
20: 9908 2006 4 29 44866 10
exp
是你的函数的参数,但它没有被使用;而total_exp_floor
却被使用了(代替了exp
参数)。 - Frankcobs
中,所以我认为我不会有任何运气尝试加速...除非我们能想出一种并行调用cobs
的方法。 - MichaelChiricocobs
是以纯R代码实现的。如果您需要足够的CPU时间,可以证明您可以用一两周的编程时间将其转换为C/C++代码(例如使用Rcpp)。或者您确实可以尝试并行化,但是您必须放弃纯数据表解决方案。 - Roland