Stata累计和与重复记录

时间:2015-10-14 14:18:15

标签: loops stata

clear 
input input record1 record2   value       str8 sdate
  1      1       0        2         "1/1/2010"
  2      1       0        2         "1/1/2010"
  3      1       0        3         "1/3/2010"
  4      1       0        3        "1/3/2010"
  5      1       0        3        "1/3/2010"
  6      0       1        -3        "1/5/2010"
  7      0       1        -3         "1/5/2010"
  8      1       0        2        "1/5/2010"
  9      0       1        1         "1/7/2010" 
 end 
 gen date = daily(sdate, "MDY") 
 format date %td 

我所拥有的MWE是我的数据中每个人的变量recordi,如果他们涉及该值,则为1。我想为每个人创建一个变量,该变量累计将天数值与前一天的最终值相加。留下以下输出。

input record1 record2   value   date          record1dailysum    record2dailysum
  1      1       0        2     1/1/2010            2                .
  2      1       0        2     1/1/2010            2                .
  3      1       0        3     1/3/2010            5                .
  4      1       0        3     1/3/2010            5                .
  5      1       0        3     1/3/2010            5                .
  6      0       1        -3    1/5/2010            .               -3
  7      0       1        -3    1/5/2010            .               -3
  8      1       0        2     1/5/2010            7                .
  9      0       1        1     1/7/2010            .               -2

我有很多记录,所以我使用了一个循环来创建这些值。这就是我尝试创建的recorddailysumi

qui forval i = 1/2
    by date: egen record`i'dailysum = value + value[_n-1] if record`i' == 1
}

最后,我想将值向下移动一个日期,因此对于record11/3/2010的值将是1/1/2010等中的值。

不能选择压缩数据以按日期创建唯一记录并记录和合并(至少这是最后的手段,因为它是一个庞大而混乱的数据集)。

1 个答案:

答案 0 :(得分:1)

代码中的一些错误:

  • {
  • 末尾遗失forvalues
  • by date表示您希望将每个唯一日期视为一个组。你真的不想要这个。您希望sort date然后按record[i]运行代码(根据您的数据结构)。
  • (可能)更正常的方法是让一个名为record的字段等于1,2,......,在这种情况下,您只需编码bys record (date): ...(稍后)
  • 请注意,sum()generate)的egen函数会给出累积总和。

关于请求:通过在数据中重复观察,以及通过在观察中重复累积总和所获得的收益,您不清楚会得到什么。为什么不只是duplicates drop [varlist]?或者,如果您需要保留所有观察结果,那么标记唯一观察结果可能会更有用,我认为。

最后,“我想为每个人创建一个变量,累计将天数值与前一天的最终值相加。留下以下输出。”不一致“最后,我想将值向下移动一个日期,因此对于record1,2010年1月3日的值将是2010年1月1日的值,等等。”

一个解决方案,维护你的结构:

clear 
input input record1 record2   value       str8 sdate
  1      1       0        2         "1/1/2010"
  2      1       0        2         "1/1/2010"
  3      1       0        3         "1/3/2010"
  4      1       0        3        "1/3/2010"
  5      1       0        3        "1/3/2010"
  6      0       1        -3        "1/5/2010"
  7      0       1        -3         "1/5/2010"
  8      1       0        2        "1/5/2010"
  9      0       1        1         "1/7/2010" 
end 

// tag unique obs (consider instead duplicates drop record1 record2 value sdate, force)
egen tag = tag(record1 record2 value sdate)

// generate stata data
gen date = daily(sdate, "MDY") 
format date %td 

// fixed loop
sort date
forval i = 1/2 {
    gen record`i'dailysum = sum(value) if record`i' == 1 & tag == 1
}

// if you must have duplicated sums, you can replace by group
forvalues i = 1/2 {
    clonevar record`i'dailysum2 = record`i'dailysum
    bys record`i' value date (record`i'dailysum2): replace record`i'dailysum2 = record`i'dailysum2[1]
}
sort record2 date record1 date
li, sepby(record1) noobs

结果

  +------------------------------------------------------------------------------------------------------------+
  | input   record1   record2   value      sdate   tag        date   record..   record..   record..   record.. |
  |------------------------------------------------------------------------------------------------------------|
  |     2         1         0       2   1/1/2010     0   01jan2010          .          .          2          . |
  |     1         1         0       2   1/1/2010     1   01jan2010          2          .          2          . |
  |     3         1         0       3   1/3/2010     1   03jan2010          5          .          5          . |
  |     5         1         0       3   1/3/2010     0   03jan2010          .          .          5          . |
  |     4         1         0       3   1/3/2010     0   03jan2010          .          .          5          . |
  |     8         1         0       2   1/5/2010     1   05jan2010          7          .          7          . |
  |------------------------------------------------------------------------------------------------------------|
  |     6         0         1      -3   1/5/2010     1   05jan2010          .         -3          .         -3 |
  |     7         0         1      -3   1/5/2010     0   05jan2010          .          .          .         -3 |
  |     9         0         1       1   1/7/2010     1   07jan2010          .         -2          .         -2 |
  +------------------------------------------------------------------------------------------------------------+

然而,如果这是我的项目,我肯定会看到这样的事情:

// AN ALTERNATIVE APPROACH

clear 
input input record1 record2   value       str8 sdate
  1      1       0        2         "1/1/2010"
  2      1       0        2         "1/1/2010"
  3      1       0        3         "1/3/2010"
  4      1       0        3        "1/3/2010"
  5      1       0        3        "1/3/2010"
  6      0       1        -3        "1/5/2010"
  7      0       1        -3         "1/5/2010"
  8      1       0        2        "1/5/2010"
  9      0       1        1         "1/7/2010" 
end 

// recode record
gen record = .
forvalues i = 1/2 {
    replace record = `i' if record`i' == 1
}
drop record?

gen date = daily(sdate, "MDY") 
format date %td 

// drop duplicates
duplicates drop record value date , force

// gen daily sum by record (loop not required due to single variable structure)
bysort record (date): gen dailysum = sum(value)

li, sepby(record) noobs

产生

  +----------------------------------------------------------+
  | input   value      sdate   record        date   dailysum |
  |----------------------------------------------------------|
  |     1       2   1/1/2010        1   01jan2010          2 |
  |     3       3   1/3/2010        1   03jan2010          5 |
  |     8       2   1/5/2010        1   05jan2010          7 |
  |----------------------------------------------------------|
  |     6      -3   1/5/2010        2   05jan2010         -3 |
  |     9       1   1/7/2010        2   07jan2010         -2 |
  +----------------------------------------------------------+

在第二个示例中,将值向下移动一个日期是一项简单的任务:

// shift the values down by one date
bysort record (date): gen dailysum2 = dailysum[_n-1]

在第一个示例中,以下内容应该有效:

forvalues i = 1/2 {
    bys tag record`i' (date): gen record`i'dailysumshift = record`i'dailysum[_n-1] if tag == 1
}