全部版块 我的主页
论坛 计量经济学与统计论坛 五区 计量经济学与统计软件 Stata专版
6596 14
2017-03-10
悬赏 10000 个论坛币 已解决
有如下变量(该变量为计数数据):
var
2
0
3
12
5
8
.
.
.
20

问题一:
生成1000个新变量(随机分布),要求新变量的数值总和与原变量数值总和相等,并且新变量依旧为计数数据(非负整数)。

我根据要求写了如下代码:
sum var
return list
forvalues i=1(1)1000 {
gen var`i'=rpoisson(r(mean))
}

以上代码基本上可以解决问题,但是不完美。因为是计数数据,我因此使用了泊松分布,让新生成的泊松分布的均值与原变量保持一致。但问题是根据以上代码新生成的新变量并不能严格保证数值总和和原变量数值总和完全一致(尽管比较接近)。因此,希望能找到完美的解决方案。

问题二:
生成1000个新变量,新变量要求保持原变量的所有数值不变,只是改变观察值出现的顺序。

可用附件数据进行试验。

谢谢!


对于问题一,根据夏日贵志的思路,我改写代码如下(具体思路及出现的问题,详见下面的跟帖):
*Simulation Distribution*
forvalues i=1/1000 {
use "test.dta", clear
gen order=_n
sum var
local sum=r(sum)
gen var`i'=rpoisson(r(mean))
sum var`i'
local diff=`sum'-r(sum)
gen random=rnormal() if var`i'!=0
replace random=-1 if var`i'==0
sort random
if `diff'>0 {
replace var`i'=var`i'+1 in f/`diff'
}
if `diff'<0 {
replace var`i'=var`i'-1 in `diff'/l
}
save "var`i'.dta", replace
}
*Merge*
use test.dta, clear
gen order=_n
forvalues i=1/1000 {
merge 1:1 order using "var`i'.dta", nogen
}
keep var*
save "simulation.dta", replace
*Erase*
forvalues i=1/1000 {
erase "var`i'.dta
}

对于问题二,根据夏日贵志的思路,我改写代码如下(夏日贵志的代码生成了一个新变量,我的问题要求生成1000个新变量,因此我在夏日贵志思路的基础上,简单嵌套了循环程序):
forvalues i=1/1000 {
use "test.dta", clear
gen random`i'=rnormal()
sort random`i'
gen order=_n
drop random
rename var var`i'
save "var`i'.dta", replace
}
use test.dta, clear
gen order=_n
forvalues i=1/1000 {
merge 1:1 order using "var`i'.dta", nogen
}
keep var*
save "simulation.dta", replace
forvalues i=1/1000 {
erase "var`i'.dta"
}

以上代码的运算速度还是很快的,只是在merge的步骤相对费时一些(merge 1000次)。

test.dta

大小:3.3 KB

 马上下载

最佳答案

夏目贵志 查看完整内容

第一个问题略麻烦一点,不过还算有意思。 第二个问题就很简单了 gen id=_n preserve gen i=rnormal() sort i replace id=_n rename var var2 drop i save tmp, replace restore merge 1:1 id using tmp, nogenerate drop id erase tmp.dta
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

全部回复
2017-3-10 05:38:28
第一个问题略麻烦一点,不过还算有意思。
复制代码


第二个问题就很简单了
gen id=_n
preserve
gen i=rnormal()
sort i
replace id=_n
rename var var2
drop i
save tmp, replace
restore
merge 1:1 id using tmp, nogenerate
drop id
erase tmp.dta


二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2017-3-12 02:06:19
非常感谢夏日贵志的参与,思路很巧妙。
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2017-3-12 12:01:00
夏目贵志 发表于 2017-3-11 23:32
第一个问题略麻烦一点,不过还算有意思。
非常感谢你的帖子,第一个问题目前确实能保证总和相等,但是两个变量的标准差之间的差距太大了。我一开始之所以选择泊松分布,因为计数数据大体服从泊松分布。但严格来讲这也有些问题。泊松分布满足均值等于方差,但实际上样本未必满足这个条件。另外,randomly choose a new observation of var2 to apply correction,其实并不是很随机的。生成的local diff确实可以巧妙地解决总和相等的问题,但是replace var2这步总改变从1到diff位置的计数值,而且就是在前几个位置上加1。这毫无疑问可以满足均值相等的问题,但是分配数值的方法并不随机。再有个小问题,我要生成1000个新变量,也许需要扩展到10000个,目前测试文件的观察值只有130,实际问题的观察值会比这个大得多,因此这个也要同时考虑代码运算速度和内存容量的问题。

我根据你的生成local diff的思路,依然使用泊松分布,改写代码如下:

*Simulation Distribution*
forvalues i=1/1000 {
use "test.dta", clear
gen order=_n
sum var
local sum=r(sum)
gen var`i'=rpoisson(r(mean))
sum var`i'
local diff=`sum'-r(sum)
sort var`i'
if `diff'>0 {
replace var`i'=var`i'+1 in f/`diff'
}
if `diff'<0 {
replace var`i'=var`i'-1 in `diff'/l
}
save "var`i'.dta", replace
}
*Merge*
use test.dta, clear
gen order=_n
forvalues i=1/1000 {
merge 1:1 order using "var`i'.dta", nogen
}
keep var*
save "simulation.dta", replace
*Erase*
forvalues i=1/1000 {
erase "var`i'.dta"
}

但是这个还是不能解决新变量标准差与原变量标准差之间差距较大的问题。我也想到了使用正态分布规定均值和标准差的方法,利用round取整,但是这会产生许多负值,可以replace负值为0,但是改动后标准差的差距又大了。另外,我觉得sort变量后首末位几个数据加减1的方法不够随机。这实际上是把最大值变小,把最小值变大。
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2017-3-12 22:18:13
非常感谢你的帖子,第一个问题目前确实能保证总和相等,但是两个变量的标准差之间的差距太大了。我一开始之所以选择泊松分布,因为计数数据大体服从泊松分布。但严格来讲这也有些问题。泊松分布满足均值等于方差,但实际上样本未必满足这个条件。
至于我为什么用了uniform,其实只是随手挑了一个。你要是用rnormal()^2也是一样的。并不是我觉得uniform一定对,别的一定不对。只是需要这些随机数不为负而已。要求样本的矩和总体完全一样本来就是不合理的。你就算从现在的样本里随机抽样,也没有任何办法保证的。所以建议你别纠结这一点了。
另外,randomly choose a new observation of var2 to apply correction,其实并不是很随机的。生成的local diff确实可以巧妙地解决总和相等的问题,但是replace var2这步总改变从1到diff位置的计数值,而且就是在前几个位置上加1。这毫无疑问可以满足均值相等的问题,但是分配数值的方法并不随机。
这个并没有不随机。
gen var3=runiform() if var2>=1
sort var3
其实就是在随机排序。
再有个小问题,我要生成1000个新变量,也许需要扩展到10000个,目前测试文件的观察值只有130,实际问题的观察值会比这个大得多,因此这个也要同时考虑代码运算速度和内存容量的问题。
我的这个方法并没有什么效率格外不高的地方。在我电脑上一千万观测值的情况下泡一下我这个程序也不到十秒钟。
r; t=8.08 10:15:44
但是这个还是不能解决新变量标准差与原变量标准差之间差距较大的问题。另外,我觉得sort变量后首末位几个数据加减1的方法不够随机。这实际上是把最大值变小,把最小值变大。
刚才解释过了。标准差之间有差距是正常的。你换一个和原分布相近的就能缓解这个问题。想要完全一致就算不是不可能,我个人觉得也没什么道理。sort的问题已经说过是随机sort的了。
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

2017-3-12 22:20:46
另外,如果你回想一下自由度的概念,就能发现:你要保证均值和方差,就要牺牲自由度。换句话说就是不可能让你所有的观测值都随机。总有需要特别调整的。
二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

点击查看更多内容…
相关推荐
栏目导航
热门文章
推荐文章

说点什么

分享

扫码加好友,拉您进群
各岗位、行业、专业交流群