【问题标题】:Replace a subset of data with a sequence of integers用整数序列替换数据子集
【发布时间】:2015-09-05 14:05:21
【问题描述】:

我有一个如下所示的数据集:

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 中完成这个看似简单的任务?

【问题讨论】:

  • 这是对围绕您的数据的假设的非常稀疏的描述。每次测试总是有 3 个 id 吗?测试的不同值是否组合在一起,或者是否有多批具有相同测试值的观察?是否有另一个变量可以确定相同测试值的 3 个(或其他)观察值出现的顺序?您确定 id 的缺失值是全有或全无,没有一个 test 值仅缺失 3 个(或其他)值中的 1 个?

标签: subset sequence stata stata-macros


【解决方案1】:

好的,再想一想,我想我已经解决了自己的问题。最简单的解决方案是利用 Stata 的 _n-function 而不使用循环:

replace id = _n - 3 if (id == .)

这似乎可以解决问题。

【讨论】:

  • 如果您只有 6 个观察值,则此方法有效。如果你想让标识符重复 1、2、3,那就不行了。
  • 如果您只有 6 个观察值,使用 Stata 的数据编辑器,您可以手动替换缺失值。 :-)
【解决方案2】:

各种可能性之一(用于重复标识符 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) 

也可以。

【讨论】:

    【解决方案3】:

    或许

    replace id = cond(test==test[_n-1],id[_n-1]+1,1) if missing(id)
    

    这并不要求每个测试恰好有三个 id。

    【讨论】:

      【解决方案4】:

      如果您的所有 ID 都以数字 1 开头,而您真的只想给它们编号,那么应该可以这样:

      sort test id
      by test: gen id2 = _n
      replace id = id2 if missing(id)
      

      请注意,您应该根据需要更改第一个排序。根据您的问题的性质,带有 test == B 的项目的顺序是“有序的”是没有意义的,因此您应该确保初始排序将它们置于理想的顺序。

      编辑:正如 Nick Cox 所指出的,此代码简化为单行代码,如果这是所需的操作,则更可取。为了简单起见,我把它写成 3 行,并注意以下事实:

      1. 必须考虑排序,无论您是独立执行还是在 bysort 命令中执行,以确保标签与程序员的目标对齐

      2. 如果您想抽查新 ID 和旧 ID,那么能够直观地看到 id2 可能会很有用,以确保代码正常工作。

      一旦这两个都得到保证,我同意下面评论中尼克的代码更可取。

      【讨论】:

      • 这减少到bysort test (id) : replace id = _n if missing(id)
      【解决方案5】:

      出于指导目的,@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 |
           +-----------+
      

      【讨论】:

        猜你喜欢
        • 2022-01-03
        • 1970-01-01
        • 1970-01-01
        • 2017-07-04
        • 1970-01-01
        • 2014-10-30
        • 1970-01-01
        • 1970-01-01
        • 2019-04-16
        相关资源
        最近更新 更多