我有一个如下所示的数据集:
id test
1 A
2 A
3 A
. B
. B
. B
我想用与id
对应的整数序列填充缺失值:
id test
1 A
2 A
3 A
1 B
2 B
3 B
我最初考虑使用forvalues
循环,如下所示:
forvalues i=1/3 {
replace id = `i' if (id == .)
}
但是(出于显而易见的原因)只是在第一次迭代期间用1
替换了所有缺失的值。
然后我考虑通过行索引将循环限制为数据的子集(如在R中),但Stata(?)似乎不存在此功能:
forvalues i=1/3 {
replace id[3+`i'] = `i' if (id == .)
}
如何在Stata中完成这个看似简单的任务?
答案 0 :(得分:1)
好的,考虑一下,我想我已经解决了自己的问题。最简单的解决方案是利用Stata的id
- 函数而无需求助于循环:
_n
这似乎可以解决问题。
答案 1 :(得分:1)
各种可能性之一(用于重复标识符1,2,3,1,2,3 ......,这是我阅读问题的方式)是
replace id = 1 + mod(_n - 1, 3) if missing(id)
或查看help egen
seq()
功能。
egen newid = seq(), to(3)
replace id = newid if missing(id)
在前三个观察中给出初始的1,2,3,然后
replace id = id[_n-3] if missing(id)
也会奏效。
答案 2 :(得分:1)
或者
replace id = cond(test==test[_n-1],id[_n-1]+1,1) if missing(id)
不要求每次测试只有三个id。
答案 3 :(得分:1)
如果您的所有ID都以数字1开头,并且您真的只想对它们进行编号,那么这样的事情应该有效:
sort test id
by test: gen id2 = _n
replace id = id2 if missing(id)
请注意,您应该根据需要更改第一个排序。根据你的问题的性质,没有任何意义,测试== B的项目的顺序是“有序的”,所以你应该确保初始排序使它们按照理想的顺序。
编辑:正如Nick Cox所说,这段代码减少到一个衬里,如果这是所需的动作,这是更好的选择。为简单起见,我将其写成3行,并注意以下事实:无论是单独执行还是使用bysort命令,都必须考虑排序,以确保标签与程序员的目标保持一致
如果您想要查看旧ID的新ID,可以直观地看到id2,以确保代码正常工作。
一旦确认了这两个,我同意下面评论中尼克的代码是可取的。
答案 4 :(得分:1)
出于指导目的,@ Nick的egen
方法可以进一步推广:
clear
input id str1 test
1 A
2 A
3 A
. B
. B
. C
. C
. C
. C
. D
. E
. E
. E
end
levelsof test, local(test_levels)
local number_of_test_levels : word count `test_levels'
forvalues i = 1 / `number_of_test_levels' {
count if missing(id) & test == "`=char(64 + `i')'"
if `r(N)' != 0 {
egen newid`i' = seq(), from(1) to(`r(N)')
replace id = newid`i' if missing(id) & test == "`=char(64 + `i')'"
drop newid`i'
}
}
产生预期的输出:
sort test id
list
+-----------+
| id test |
|-----------|
1. | 1 A |
2. | 2 A |
3. | 3 A |
4. | 1 B |
5. | 2 B |
|-----------|
6. | 1 C |
7. | 2 C |
8. | 3 C |
9. | 4 C |
10. | 1 D |
|-----------|
11. | 1 E |
12. | 2 E |
13. | 3 E |
+-----------+