【问题标题】:Counting observations under varying conditions in Stata在Stata中计算不同条件下的观察值
【发布时间】:2015-03-08 01:59:53
【问题描述】:

我有一个大型数据集,其结构如下(这是一个示例):

+-----------------------------------------+
| id       date   treat   match   num     |
|-----------------------------------------|
|  1  01feb2000       1       2      2    |
|  1  01apr2000       0       .      .    |
|  1  01jan2002       1       3      1    |
|-----------------------------------------|
|  2  01mar2000       1       3      0    |
|  2  01may2000       0       .      .    |
|-----------------------------------------|
|  3  01dec2002       1       .      .    |
+-----------------------------------------+

对于由id 标识的每个组,我在某些日期有某些事件。每次发生都是治疗或控制。每个治疗观察都与某个id 匹配。您可以将iddatetreatmatch 变量作为给定。

我的目标是为每个实际匹配的治疗观察计算num 的值(可能存在治疗观察不匹配的情况,请参阅id 3)。 规则是从处理观察之日起一年内计算匹配的id中出现的任何次数(不管是否处理)。

示例:第一个处理过的观测值与 id2 匹配。id2 在 2000 年 2 月 1 日之后的下一年内有两个观测值。

重要提示:首先,匹配 id 中第一次出现的日期永远不会早于考虑的治疗观察日期。其次,多个治疗观察可以匹配同一个id

请注意,here 此处已提出类似问题。在这里,我关心算法的效率,因为我的数据集很大。我的解决方案如下:

gen NUM = .
gen yrafter = 25000    // arbitrary date outside of the panel
format yrafter %td
gen in_window = 0
sort id date

forval i = 1/`=_N' {
    if (match[`i'] != .) {
        replace yrafter = (date_installation[`i'] + 365) if ags == match[`i']
            replace in_window = date_installation <= yrafter & ags == match[`i']

            by id: egen NUM_temp = sum(in_window) if ags == match[`i']
            replace NUM_temp = 0 if NUM_temp == .
            sum NUM_temp if ags == match[`i'], meanonly

            replace NUM0 in `i' = r(max)
        drop NUM_temp

        replace in_window = 0 if ags == match[`i']
    }
}

drop yrafter in_window

为了减少迭代次数,我实际上想在处理观察后进行排序,并且只对它们进行迭代。但是,根据我对问题的理解,我不能这样做,因为一些后续命令需要我在上面应用的排序(我是对的吗?)。

我的策略是迭代每个相关观察:对于匹配的id 组中的所有观察,我将yrafter 的值替换为需要考虑的最新可能发生的事件。然后在变量in_window 中,我简单地识别出在可能的最新日期之前的那些观察结果(请记住,在treatment 变量的日期之前不能出现任何事件),然后计算所有观察值。我将结果保存在 num 中,并为下一次迭代设置所有内容。

显然,这需要很多时间。我的第一个猜测是优化循环头,因为检查 if 条件对于 Stata 来说似乎非常耗时。有人有优化的想法吗?

【问题讨论】:

  • 您对数据集的大小有何看法?有多少ids?每个id 的最小、最大和平均观察数?观察总数?您的代码是否提供正确的结果?多久时间?电脑规格?
  • 我的数据集大小超过 1 Mio。观察和大约 14,000 个身份。我的代码确实提供了正确的结果,但目前我无法为您提供有关运行时间的任何确切信息。

标签: stata matching


【解决方案1】:

尝试一些类似的东西

clear
set more off

*----- example data -----

input ///
 id  str20 date   treat   match   num     
  1  01feb2000       1       2      2    
  1  01apr2000       0       .      .    
  1  01jan2002       1       3      1    
  2  01mar2000       1       3      0    
  2  01may2000       0       .      .    
  3  01dec2002       1       .      .    
end

list, sepby(id)

gen dat = date(date,"DMY")
format %td dat
drop date
order dat, after(id)

list, sepby(id)

*----- what you want -----

gen num2 = .
forvalues i = 1/`=_N' {
    if treat[`i'] == 1 {
        count if id == match[`i'] & dat <=  dat[`i'] + 365
        replace num2 = r(N) in `i'
    }
}
replace num2 = . if missing(match)

list, sepby(id)

assert num == num2

我没有关于你的数据集大小的信息,所以除非你准确地透露,否则我不会做任何测试。

(我没有检查您的代码。我只是尝试将您的问题的措辞翻译成 Stata 代码。)

【讨论】:

  • 感谢您的建议!在我看来,我不知道 count 命令这一事实使我的生活变得非常困难。我已经在我的原始数据集上测试了上面的算法:结果是正确的并且运行时间是合适的,即比以前好得多(再次,我没有采取确切的运行时间)。感谢您的努力!
【解决方案2】:

只有当我有正确的代码时,我才会担心效率。以下是错误。

是非法的,应该是

    replace NUM0 = r(max) in `i' 

我无法评论您的主要问题,因为我不明白您要做什么。我想你的解释是清楚和合乎逻辑的;当我从未做过类似的事情时,我无法吸收你正在做的所有事情,这太复杂了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多