楼主: xingxf
7295 35

[编程问题求助] 生成过去特定一段时间特定条件下某ID重复出现的次数 [推广有奖]

11
xingxf 发表于 2013-5-1 17:08:45
sungmoo 发表于 2013-5-1 17:01
对于完全相同的行(重复值),楼主要如何处理?
重复值是需要保留的。比如,1985年1月1日这行,如果之前1982年1月1日有两个重复值,那么这个要算两次。

12
xingxf 发表于 2013-5-2 03:09:41
voodoo 发表于 2013-5-1 16:00
答案和问题是相关的。请你再澄清一下关于你样本的性质:
1. 为什么存在很多完全相同的duplicate obs?
2. ...
谢谢您的关注,但是我觉得您问的问题和我问题的答案没有必然的关联,也就是说要解决我的问题不需要知道您问题的答案。事实上我写的代码可以解决问题,但是运行速度太慢。
对于您的问题:
1. 如果您把一个id在一个时间点的数据作为一个obs,那么这确实是有重复制,但是,需要说明的是,我研究的是公司,一个公司可以在一天做几项交易,比如,在一天同时提出几起收购,同时举债,那么你把一起交易作为一个obs,那么我提供的数据就是严格的面板数据。
2. 公司多,id自然多,有的公司交易多,有的交易少,那么每个id的样本差距就很大。
3. 我提供的sample不是我的final sample,但是对于我要生成的一个特定变量来说,这就是全部的数据。

13
voodoo 发表于 2013-5-2 10:55:55
暂时未想到优化循环的方法, 但通过简单的数据预处理即可大幅降低循环时间。
示例程序见楼下:







巫毒上传,必属佳品!
坛友下载,三思后行!

14
voodoo 发表于 2013-5-2 11:18:16
//        以下程序尽管循环部分并未优化,但只需根据你的数据对数据进行清洁,并合并重复样本的信息,就可将程序运行时间缩短至原来的20%!
//        这事实上也说明了在数据管理过程中理解数据的重要性

set more off
use sample.dta, clear
count        // 看看共有多少样本

//        #1
//        根据你的说明,B E MA取值要么1,要么missing,不应为0啊?
//        将0替换为.,然后删除三个变量均为.的样本
//        竟然多达26万个,节约50%的时间
foreach v in B E MA {
        replace `v' = . if `v' == 0
}
drop if missing(B) & missing(E) & missing(MA)

//        #2
//        循环计算
/*
        //        #2.0
        //        10000样本先试一下
sort id date
keep in 1/10000
*/
        //        #2.1
        //        用`v't合并重复样本的信息,然后删除重复样本
foreach v in B E MA {
        bysort id date: egen `v't = total(`v')
        drop `v'
}
duplicates drop id date, force

        //        #2.2
        //        删除只有一个date的,肯定无需进入循环
by id: gen N = _N
drop if N == 1
drop N

        //        #2.3
        //        双重循环计算
count        // 看看还剩下多少样本
foreach v in B E MA {        // 变量循环
        gen Var_`v' = .
        qui forval i = 1/`=_N' {        // 样本循环
                su `v't if id==id[`i'] & inrange((date[`i']-date), 1, 1826)
                replace Var_`v' = r(sum) in `i'
        }

        drop `v't
}


        //        #2.4
        //        和原来的样本数据合并
merge 1:m id date using sample, nogen
/*
foreach v in B E MA {        // 替换缺失值为0
        replace Var_`v' = 0 if missing(Var_`v')
}
*/
save sample2, replace

//        加红部分的循环尚有待想出办法来进一步优化


巫毒上传,必属佳品!
坛友下载,三思后行!

15
voodoo 发表于 2013-5-2 11:38:15
  1. //        以下程序尽管循环部分并未优化,但只需根据你的数据对数据进行清洁,并合并重复样本的信息,就可将程序运行时间缩短至原来的20%!
  2. //        这事实上也说明了在数据管理过程中理解数据的重要性

  3. set more off
  4. use sample.dta, clear
  5. count        // 看看共有多少样本

  6. //        #1
  7. //        根据你的说明,B E MA取值要么1,要么missing,不应为0啊?
  8. //        将0替换为.,然后删除三个变量均为.的样本
  9. //        竟然多达26万个,节约50%的时间
  10. foreach v in B E MA {
  11.         replace `v' = . if `v' == 0
  12. }
  13. drop if missing(B) & missing(E) & missing(MA)

  14. //        #2
  15. //        循环计算
  16. /*
  17.         //        #2.0
  18.         //        10000样本先试一下
  19. sort id date
  20. keep in 1/10000
  21. */
  22.         //        #2.1
  23.         //        用`v't合并重复样本的信息,然后删除重复样本
  24. foreach v in B E MA {
  25.         bysort id date: egen `v't = total(`v')
  26.         drop `v'
  27. }
  28. duplicates drop id date, force

  29.         //        #2.2
  30.         //        删除只有一个date的,肯定无需进入循环
  31. by id: gen N = _N
  32. drop if N == 1
  33. drop N

  34.         //        #2.3
  35.         //        双重循环计算
  36. count        // 看看还剩下多少样本
  37. foreach v in B E MA {        // 变量循环
  38.         gen Var_`v' = .
  39.         qui forval i = 1/`=_N' {        // 样本循环
  40.                 su `v't if id==id[`i'] & inrange((date[`i']-date), 1, 1826)
  41.                 replace Var_`v' = r(sum) in `i'
  42.         }
  43.         drop `v't
  44. }

  45.         //        #2.4
  46.         //        和原来的样本数据合并
  47. merge 1:m id date using sample, nogen
  48. /*
  49. foreach v in B E MA {        // 替换缺失值为0
  50.         replace Var_`v' = 0 if missing(Var_`v')
  51. }
  52. */
  53. save sample2, replace
复制代码
已有 1 人评分经验 论坛币 学术水平 热心指数 收起 理由
dxystata + 100 + 100 + 1 + 1 好的意见建议

总评分: 经验 + 100  论坛币 + 100  学术水平 + 1  热心指数 + 1   查看全部评分

巫毒上传,必属佳品!
坛友下载,三思后行!

16
jonathanjp 发表于 2013-5-2 20:01:14
我将你的问题发在了Statalist,Nick Cox这样回复:

I don't know a sure-fire way to speed this up. It might just be faster if you -expand-ed the data to one observation for every day. Then the code would be  simpler,  but you would end up with several millions of observations. Or you could translate the code into Mata.

以上信息,仅供参考。
已有 1 人评分学术水平 热心指数 信用等级 收起 理由
xingxf + 2 + 2 + 2 观点有启发

总评分: 学术水平 + 2  热心指数 + 2  信用等级 + 2   查看全部评分

17
xingxf 发表于 2013-5-2 21:05:37
voodoo 发表于 2013-5-2 11:18
//        以下程序尽管循环部分并未优化,但只需根据你的数据对数据进行清洁,并合并重复样本的信息,就可 ...
谢谢您的热心,但是不好意思,我明白您为什么想问我样本的详细信息了,您是想解决一开始数据管理的问题。但实际上,我发上来的样本已经进行了清理。您也没问我B,E,MA这三个dummy的含义,我也没细说,您就误认为这三个dummy要么为1,要么为missing value。实际上我的数据完全不能按您的方法进行清理的。

我可以把这个样本再详细描述一下。id就是公司代码,date是event date,我这个样本里B,E,MA三个dummy分别代表公司在bond issue,equity issu,和M&A时是否聘请top-tier investment bank作为financial advisor。如果聘请top-tier bank,则该dummy设置为1,否则为零。因此,这就是为什么B,E,MA三个dummy会有三种取值1,0,missing value。举例来说,如果一个公司在一个时间点做了一个deal为M&A,并且聘请了top-tier bank,那么B和E就应该为missing value,而MA应为1;如果没有聘请top-tier bank,那么B和E均为missing value,而MA为0。我的问题的含义,就是说在某个deal发生的五年前,该公司聘请top-tier bank做过多少起bond issue,多少起equity issue和多少起M&A。所以,在这个逻辑的基础上,我上传的数据已经是经过清理的最简化数据。

18
xingxf 发表于 2013-5-2 21:20:20
jonathanjp 发表于 2013-5-2 20:01
我将你的问题发在了Statalist,Nick Cox这样回复:

I don't know a sure-fire way to speed this up. It ...
谢谢您的热心帮助,Statalist需要subscribe是吧,我自己也去subscribe一个。

19
xingxf 发表于 2013-5-2 21:26:15
jonathanjp 发表于 2013-5-2 20:01
我将你的问题发在了Statalist,Nick Cox这样回复:

I don't know a sure-fire way to speed this up. It ...
Nick的办法还是有启发的

20
voodoo 发表于 2013-5-2 21:51:50
xingxf 发表于 2013-5-2 21:05
谢谢您的热心,但是不好意思,我明白您为什么想问我样本的详细信息了,您是想解决一开始数据管理的问题。 ...
那就从原程序中剔除#1步骤(仅保留save sample2, replace)。还是采用“分而治之”的方法,但将NSMPL设为60。
我相信最终程序运行时间应该可以在700秒左右(303*2)。
巫毒上传,必属佳品!
坛友下载,三思后行!

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
加好友,备注jltj
拉您入交流群
GMT+8, 2026-1-1 09:09