如何在 Stata 中将长数据转换为宽数据?
How to transform long to wide data in Stata?
我有这个数据:
id test test_date value
1 A 02/06/2014 12:26 11
1 B 02/06/2014 12:26 23
1 C 02/06/2014 13:17 43
1 D 02/06/2014 13:17 65
1 E 02/06/2014 13:17 34
1 F 02/06/2014 13:17 64
1 A 05/06/2014 15:14 234
1 B 05/06/2014 15:14 646
1 C 05/06/2014 16:50 44
1 E 05/06/2014 16:50 55
2 E 05/06/2014 16:50 443
2 F 05/06/2014 16:50 22
2 G 05/06/2014 16:59 445
2 B 05/06/2014 20:03 66
2 C 05/06/2014 20:03 77
2 D 05/06/2014 20:03 88
2 E 05/06/2014 20:03 44
2 F 05/06/2014 20:19 33
2 G 05/06/2014 20:19 22
我想将此数据转换为宽格式,如下所示:
id date A B C D E F G
1 02/06/2014 12:26 11 23 43 65 34 64 .
1 05/06/2014 15:14 234 646 44 . 55 . .
2 05/06/2014 16:50 . . . . 443 22 445
2 05/06/2014 20:03 . 66 77 88 44 33 22
我在 Stata 中使用 reshape
命令,但它没有产生所需的结果:
reshape wide test_date value, i(id) j(test) string
知道怎么做吗?
更新:
你是对的,我们需要这个 missvar。我尝试通过编程来创建它,但失败了。假设在测试日期的 2 小时内,批次将认为相同。我们只有 7 个测试(A、B、C、D、E、F、G)。首先我试着找出时差;
bysort id: gen diff_bd = (test_date[_n] - test_date[_n-1])/(1000*60*60)
bysort id: generate missvar = _n if diff_bd <= 2
命令指定的有点错误。你想重塑 value
。查看您想要的输出并注意观察结果由 id
和 test_date
唯一标识。因此,它们应该在 i
选项中。
reshape wide value, i(id test_date) j(test) string
这会产生接近您想要的结果,您只需重命名几个变量即可获得准确的输出。具体来说:
rename test_date date
renpfix value
@jfeigenbaum 给出了部分答案。
我看到的问题是您缺少标识相关子组的变量。这些子组似乎受到 test
取值 A - G
的限制。但我可能错了。
我已将此变量包含在示例数据集中,并将其命名为 missvar
。我将此变量强加到数据集中,相信它可以识别虽然隐含在您的原始 post 中但对您的分析很重要的组。
clear
set more off
*----- example data -----
input ///
id str1 test str30 test_date value missvar
1 A "02/06/2014 12:26" 11 1
1 B "02/06/2014 12:26" 23 1
1 C "02/06/2014 13:17" 43 1
1 D "02/06/2014 13:17" 65 1
1 E "02/06/2014 13:17" 34 1
1 F "02/06/2014 13:17" 64 1
1 A "05/06/2014 15:14" 234 2
1 B "05/06/2014 15:14" 646 2
1 C "05/06/2014 16:50" 44 2
1 E "05/06/2014 16:50" 55 2
2 E "05/06/2014 16:50" 443 1
2 F "05/06/2014 16:50" 22 1
2 G "05/06/2014 16:59" 445 1
2 B "05/06/2014 20:03" 66 2
2 C "05/06/2014 20:03" 77 2
2 D "05/06/2014 20:03" 88 2
2 E "05/06/2014 20:03" 44 2
2 F "05/06/2014 20:19" 33 2
2 G "05/06/2014 20:19" 22 2
end
gen double tdate = clock( test_date, "DM20Yhm")
format %tc tdate
drop test_date
list, sepby(id)
*----- what you want ? -----
reshape wide value, i(id missvar tdate) j(test) string
collapse (min) tdate value?, by(id missvar)
rename value* *
list
应该有某种方式以编程方式识别组。依靠数据的原始排序顺序是一种方法,但它可能不是最安全的。这可能是唯一的方法,但只有你自己知道。
编辑
关于您的评论和 "missing" 变量,创建它的一种方法是:
// one hour is 3600000 milliseconds
bysort id (tdate): gen batch = sum(tdate - tdate[_n-1] > 7200000)
对于您的示例数据,这将创建一个与我的 missvar
相同的 batch
变量。您还可以使用时间序列运算符。
让我强调您在展示示例数据时需要小心。它必须是真正的代表,否则您可能会得到不适合它的代码;这包括您没有注意到它的可能性,因为 Stata 没有给出错误。
例如,如果您在两小时内将相同的 test
应用到相同的 id
,那么您将丢失此代码的信息(在 collapse
). (这在您的示例数据中不是问题。)
编辑 2
回应评论中发现的另一个问题:
假设对 人 1 进行新的观察,使得他在两小时的限制内接受重复测试,但 在不同的时间:
1 A "02/06/2014 12:26" 11 1 // old observation
1 B "02/06/2014 12:26" 23 1
1 A "02/06/2014 12:35" 99 1 // new observation
1 C "02/06/2014 13:17" 43 1
1 D "02/06/2014 13:17" 65 1
1 E "02/06/2014 13:17" 34 1
1 F "02/06/2014 13:17" 64 1
1 A "05/06/2014 15:14" 234 2
1 B "05/06/2014 15:14" 646 2
1 C "05/06/2014 16:50" 44 2
1 E "05/06/2014 16:50" 55 2
测试 A
应用于 12:26
和 12:35
。 Reshape
对此没有问题,但是 collapse
会丢弃信息,因为它在 id missvar
组中取最小值;请注意,对于变量 valueA
,新信息(99)将丢失(所有其他变量也会发生这种情况,但您明确表示要丢弃它)。在 reshape
之后但在 collapse
之前,您会得到:
. list, sepby(id)
+--------------------------------------------------------------------------------------------------+
| id missvar tdate valueA valueB valueC valueD valueE valueF valueG |
|--------------------------------------------------------------------------------------------------|
1. | 1 1 02jun2014 12:26:00 11 23 . . . . . |
2. | 1 1 02jun2014 12:35:00 99 . . . . . . |
3. | 1 1 02jun2014 13:17:00 . . 43 65 34 64 . |
4. | 1 2 05jun2014 15:14:00 234 646 . . . . . |
5. | 1 2 05jun2014 16:50:00 . . 44 . 55 . . |
|--------------------------------------------------------------------------------------------------|
6. | 2 1 05jun2014 16:50:00 . . . . 443 22 . |
7. | 2 1 05jun2014 16:59:00 . . . . . . 445 |
8. | 2 2 05jun2014 20:03:00 . 66 77 88 44 . . |
9. | 2 2 05jun2014 20:19:00 . . . . . 33 22 |
+--------------------------------------------------------------------------------------------------+
运行完整的代码证实了我们刚才所说的:
. list, sepby(id)
+--------------------------------------------------------------------------+
| id missvar tdate A B C D E F G |
|--------------------------------------------------------------------------|
1. | 1 1 02jun2014 12:26:00 11 23 43 65 34 64 . |
2. | 1 2 05jun2014 15:14:00 234 646 44 . 55 . . |
|--------------------------------------------------------------------------|
3. | 2 1 05jun2014 16:50:00 . . . . 443 22 445 |
4. | 2 2 05jun2014 20:03:00 . 66 77 88 44 33 22 |
+--------------------------------------------------------------------------+
现在假设 人 1 的新观察,使得他在两小时的限制内接受重复测试,但同时 :
1 A "02/06/2014 12:26" 11 1 // old observation
1 B "02/06/2014 12:26" 23 1
1 A "02/06/2014 12:26" 99 1 // new observation
1 C "02/06/2014 13:17" 43 1
1 D "02/06/2014 13:17" 65 1
1 E "02/06/2014 13:17" 34 1
1 F "02/06/2014 13:17" 64 1
1 A "05/06/2014 15:14" 234 2
1 B "05/06/2014 15:14" 646 2
1 C "05/06/2014 16:50" 44 2
1 E "05/06/2014 16:50" 55 2
那么reshape
就不行了。 Stata 抱怨:
values of variable test not unique within id missvar tdate
并且有理由。错误在发出问题信号时很明显。 (如果不清楚,请返回 help reshape
并做一些练习。)考虑到命令的功能,该请求毫无意义。
最后,请注意,检查某项功能是否有效相对容易:只需尝试一下即可!在这种情况下,所需要的只是稍微修改示例数据。如有必要,返回帮助文件和手册。
我有这个数据:
id test test_date value
1 A 02/06/2014 12:26 11
1 B 02/06/2014 12:26 23
1 C 02/06/2014 13:17 43
1 D 02/06/2014 13:17 65
1 E 02/06/2014 13:17 34
1 F 02/06/2014 13:17 64
1 A 05/06/2014 15:14 234
1 B 05/06/2014 15:14 646
1 C 05/06/2014 16:50 44
1 E 05/06/2014 16:50 55
2 E 05/06/2014 16:50 443
2 F 05/06/2014 16:50 22
2 G 05/06/2014 16:59 445
2 B 05/06/2014 20:03 66
2 C 05/06/2014 20:03 77
2 D 05/06/2014 20:03 88
2 E 05/06/2014 20:03 44
2 F 05/06/2014 20:19 33
2 G 05/06/2014 20:19 22
我想将此数据转换为宽格式,如下所示:
id date A B C D E F G
1 02/06/2014 12:26 11 23 43 65 34 64 .
1 05/06/2014 15:14 234 646 44 . 55 . .
2 05/06/2014 16:50 . . . . 443 22 445
2 05/06/2014 20:03 . 66 77 88 44 33 22
我在 Stata 中使用 reshape
命令,但它没有产生所需的结果:
reshape wide test_date value, i(id) j(test) string
知道怎么做吗?
更新: 你是对的,我们需要这个 missvar。我尝试通过编程来创建它,但失败了。假设在测试日期的 2 小时内,批次将认为相同。我们只有 7 个测试(A、B、C、D、E、F、G)。首先我试着找出时差;
bysort id: gen diff_bd = (test_date[_n] - test_date[_n-1])/(1000*60*60)
bysort id: generate missvar = _n if diff_bd <= 2
命令指定的有点错误。你想重塑 value
。查看您想要的输出并注意观察结果由 id
和 test_date
唯一标识。因此,它们应该在 i
选项中。
reshape wide value, i(id test_date) j(test) string
这会产生接近您想要的结果,您只需重命名几个变量即可获得准确的输出。具体来说:
rename test_date date
renpfix value
@jfeigenbaum 给出了部分答案。
我看到的问题是您缺少标识相关子组的变量。这些子组似乎受到 test
取值 A - G
的限制。但我可能错了。
我已将此变量包含在示例数据集中,并将其命名为 missvar
。我将此变量强加到数据集中,相信它可以识别虽然隐含在您的原始 post 中但对您的分析很重要的组。
clear
set more off
*----- example data -----
input ///
id str1 test str30 test_date value missvar
1 A "02/06/2014 12:26" 11 1
1 B "02/06/2014 12:26" 23 1
1 C "02/06/2014 13:17" 43 1
1 D "02/06/2014 13:17" 65 1
1 E "02/06/2014 13:17" 34 1
1 F "02/06/2014 13:17" 64 1
1 A "05/06/2014 15:14" 234 2
1 B "05/06/2014 15:14" 646 2
1 C "05/06/2014 16:50" 44 2
1 E "05/06/2014 16:50" 55 2
2 E "05/06/2014 16:50" 443 1
2 F "05/06/2014 16:50" 22 1
2 G "05/06/2014 16:59" 445 1
2 B "05/06/2014 20:03" 66 2
2 C "05/06/2014 20:03" 77 2
2 D "05/06/2014 20:03" 88 2
2 E "05/06/2014 20:03" 44 2
2 F "05/06/2014 20:19" 33 2
2 G "05/06/2014 20:19" 22 2
end
gen double tdate = clock( test_date, "DM20Yhm")
format %tc tdate
drop test_date
list, sepby(id)
*----- what you want ? -----
reshape wide value, i(id missvar tdate) j(test) string
collapse (min) tdate value?, by(id missvar)
rename value* *
list
应该有某种方式以编程方式识别组。依靠数据的原始排序顺序是一种方法,但它可能不是最安全的。这可能是唯一的方法,但只有你自己知道。
编辑
关于您的评论和 "missing" 变量,创建它的一种方法是:
// one hour is 3600000 milliseconds
bysort id (tdate): gen batch = sum(tdate - tdate[_n-1] > 7200000)
对于您的示例数据,这将创建一个与我的 missvar
相同的 batch
变量。您还可以使用时间序列运算符。
让我强调您在展示示例数据时需要小心。它必须是真正的代表,否则您可能会得到不适合它的代码;这包括您没有注意到它的可能性,因为 Stata 没有给出错误。
例如,如果您在两小时内将相同的 test
应用到相同的 id
,那么您将丢失此代码的信息(在 collapse
). (这在您的示例数据中不是问题。)
编辑 2
回应评论中发现的另一个问题:
假设对 人 1 进行新的观察,使得他在两小时的限制内接受重复测试,但 在不同的时间:
1 A "02/06/2014 12:26" 11 1 // old observation
1 B "02/06/2014 12:26" 23 1
1 A "02/06/2014 12:35" 99 1 // new observation
1 C "02/06/2014 13:17" 43 1
1 D "02/06/2014 13:17" 65 1
1 E "02/06/2014 13:17" 34 1
1 F "02/06/2014 13:17" 64 1
1 A "05/06/2014 15:14" 234 2
1 B "05/06/2014 15:14" 646 2
1 C "05/06/2014 16:50" 44 2
1 E "05/06/2014 16:50" 55 2
测试 A
应用于 12:26
和 12:35
。 Reshape
对此没有问题,但是 collapse
会丢弃信息,因为它在 id missvar
组中取最小值;请注意,对于变量 valueA
,新信息(99)将丢失(所有其他变量也会发生这种情况,但您明确表示要丢弃它)。在 reshape
之后但在 collapse
之前,您会得到:
. list, sepby(id)
+--------------------------------------------------------------------------------------------------+
| id missvar tdate valueA valueB valueC valueD valueE valueF valueG |
|--------------------------------------------------------------------------------------------------|
1. | 1 1 02jun2014 12:26:00 11 23 . . . . . |
2. | 1 1 02jun2014 12:35:00 99 . . . . . . |
3. | 1 1 02jun2014 13:17:00 . . 43 65 34 64 . |
4. | 1 2 05jun2014 15:14:00 234 646 . . . . . |
5. | 1 2 05jun2014 16:50:00 . . 44 . 55 . . |
|--------------------------------------------------------------------------------------------------|
6. | 2 1 05jun2014 16:50:00 . . . . 443 22 . |
7. | 2 1 05jun2014 16:59:00 . . . . . . 445 |
8. | 2 2 05jun2014 20:03:00 . 66 77 88 44 . . |
9. | 2 2 05jun2014 20:19:00 . . . . . 33 22 |
+--------------------------------------------------------------------------------------------------+
运行完整的代码证实了我们刚才所说的:
. list, sepby(id)
+--------------------------------------------------------------------------+
| id missvar tdate A B C D E F G |
|--------------------------------------------------------------------------|
1. | 1 1 02jun2014 12:26:00 11 23 43 65 34 64 . |
2. | 1 2 05jun2014 15:14:00 234 646 44 . 55 . . |
|--------------------------------------------------------------------------|
3. | 2 1 05jun2014 16:50:00 . . . . 443 22 445 |
4. | 2 2 05jun2014 20:03:00 . 66 77 88 44 33 22 |
+--------------------------------------------------------------------------+
现在假设 人 1 的新观察,使得他在两小时的限制内接受重复测试,但同时 :
1 A "02/06/2014 12:26" 11 1 // old observation
1 B "02/06/2014 12:26" 23 1
1 A "02/06/2014 12:26" 99 1 // new observation
1 C "02/06/2014 13:17" 43 1
1 D "02/06/2014 13:17" 65 1
1 E "02/06/2014 13:17" 34 1
1 F "02/06/2014 13:17" 64 1
1 A "05/06/2014 15:14" 234 2
1 B "05/06/2014 15:14" 646 2
1 C "05/06/2014 16:50" 44 2
1 E "05/06/2014 16:50" 55 2
那么reshape
就不行了。 Stata 抱怨:
values of variable test not unique within id missvar tdate
并且有理由。错误在发出问题信号时很明显。 (如果不清楚,请返回 help reshape
并做一些练习。)考虑到命令的功能,该请求毫无意义。
最后,请注意,检查某项功能是否有效相对容易:只需尝试一下即可!在这种情况下,所需要的只是稍微修改示例数据。如有必要,返回帮助文件和手册。