在动态范围内计算观察值

时间:2014-11-08 12:55:09

标签: stata

考虑以下示例:

input group day month year number treatment NUM
1 1 2 2000 1 1 2
1 1 6 2000 2 0 .
1 1 9 2000 3 0 .
1 1 5 2001 4 0 .
1 1 1 2010 5 1 1
1 1 5 2010 6 0 .
2 1 1 2001 1 1 0
2 1 3 2002 2 1 0
end

gen date = mdy(month,day,year) 
format date %td
drop day month year

对于每组,我有不同的观察数。每个观察指的是用日期指定的事件。可变数字是每个组中的编号。

现在,我想计算从该组内每次治疗观察日期(不包括其自身)开始一年内发生的观察次数。这意味着,我想创建变量NUM我已经在上面的例子中加入了。我不关心治疗次数= 0。

编辑开始:发现以下信息缺失但是必须解决此问题:如果去年同一组内没有观察,则治疗变量的值为1 。因此,变量NUM也不可能必须考虑处理= 1的观察。原则上,组内可能有两个具有相同日期的观察值。 编辑结束

我调查了Stata tip 51: Events in intervals。它似乎可以解决我的数据集很大(> 1 mio观察),这样它真的非常低效 - 特别是因为我不关心所有治疗= 0观察。

我想知道是否有其他选择。我的方法是在每组中查找仍然在1年范围内的最新日期(并且可能将其存储在变量latestDate中)。然后我只是简单地从处理= 0变量的值中减去从观察值变量中得到的值。

注意:我的效率低下"代码如下所示

gsort -treatment
gen treatment_id = _n
replace treatment_id = . if treatment==0
gen count=.
sum treatment_id, meanonly
qui forval i = 1/`r(max)'{
        count if inrange(date-date[`i'],1,365) & group == group[`i']
        replace count = r(N) in `i'
}
sort group date

2 个答案:

答案 0 :(得分:2)

我假设治疗不能在前一次治疗的1年内发生(在该组中)。在您的示例数据中也是如此,但一般情况下可能不正确。但是,假设情况确实如此,那么这应该有效。我正在使用SSC上的carryforwardssc install carryforward)。就像你最近的日期想法一样,我在最近一次治疗后一年确定并计算该窗口中的观察数量。

sort group date
gen yrafter = (date + 365) if treatment == 1
by group: carryforward yrafter, replace
format yrafter %td
gen in_window = date <= yrafter & treatment == 0
egen answer = sum(in_window), by(group yrafter)
replace answer = . if treatment == 0

我不能保证这会比循环更快,但我怀疑它会是。

答案 1 :(得分:2)

问题并不完全清楚。

使用两个不同的结果num2num3来考虑以下数据:

  +-----------------------------------------+
  |     date2   group   treat   num2   num3 |
  |-----------------------------------------|
  | 01feb2000       1       1      3      2 |
  | 01jun2000       1       0      .      . |
  | 01sep2000       1       0      .      . |
  | 01nov2000       1       1      0      0 |
  | 01may2002       1       0      .      . |
  | 01jan2010       1       1      1      1 |
  | 01may2010       1       0      .      . |
  |-----------------------------------------|
  | 01jan2001       2       1      0      0 |
  | 01mar2002       2       1      0      0 |
  +-----------------------------------------+

变量num2的计算假设您有兴趣计算在经过处理的观察(treat == 1)后一年内的所有观察,是那些观察treat等于0或1。例如,在01feb2000之后,有三个观察符合时间跨度条件;其中两个人treat==0,一个人treat == 1,他们都被计算在内。

变量num3也计算观察后的一年内观察结果,但仅计算treat == 0的情况。

num2是根据您引用的文章的精神使用代码计算的。使用in可以提高运行效率,并且没有gsort(如代码中所示),这非常慢。我假设每个group都没有重复日期:

clear
set more off

input ///
group str15 date count treat num
1 01.02.2000 1 1 2
1 01.06.2000 2 0 .
1 01.09.2000 3 0 .
1 01.11.2000 3 1 .
1 01.05.2002 4 0 .
1 01.01.2010 5 1 1
1 01.05.2010 6 0 .
2 01.01.2001 1 1 0
2 01.03.2002 2 1 0
end

list

gen date2 = date(date,"DMY")
format date2 %td
drop date count num

order date
list, sepby(group)


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

gen num2 = .
isid group date, sort

forvalues j = 1/`=_N' {

    count in `j'/L if inrange(date2 - date2[`j'], 1, 365) & group == group[`j'] 

    replace num2 = r(N) in `j'
}

replace num2 = . if !treat

list, sepby(group)

num3使用与@jfeigenbaum发布的精神(和结果)类似的代码计算:

<snip>

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

isid group date, sort
by group: gen indicat = sum(treat)

sort group indicat, stable
by group indicat: egen num3 = total(inrange(date2 - date2[1], 1, 365))
replace num3 = . if !treat

list, sepby(group)

对于您的问题,可能有两种以上的解释,但我会留下它。

(请注意,我已将您的示例数据更改为包含可能使问题更加真实的案例。)