Sas 将单个观测值拆分为多个观测值

Sas 将单个观测值拆分为多个观测值,sas,Sas,我有以下SAS数据集: data mydata; LENGTH id 4.0 num 4.0 A $ 4. B $ 8. C $ 20.; input id num A $ B $ C $; datalines; 1 1 x yy zzzzz 2 1 x yy zzzzz 3 2 xq yyqq zzzzzqqqqq 4 1 x yy zzzzz 5 3 xqw yyqqww zzzzzqqqqqwwwww 6 1 x yy zzzzz 7 4 xqwe yyqqwwee zz

我有以下SAS数据集:

data mydata;
   LENGTH id 4.0 num 4.0 A $ 4. B $ 8. C $ 20.;
   input id num A $ B $ C $;
   datalines;
1 1 x yy zzzzz
2 1 x yy zzzzz
3 2 xq yyqq zzzzzqqqqq
4 1 x yy zzzzz
5 3 xqw yyqqww zzzzzqqqqqwwwww
6 1 x yy zzzzz
7 4 xqwe yyqqwwee zzzzzqqqqqwwwwweeeee
;
看起来像

mydata
-------------------
id num A B C
1  1   x yy zzzzz
2  1   x yy zzzzz
3  2   xq yyqq zzzzzqqqqq
4  1   x yy zzzzz
5  3   xqw yyqqww zzzzzqqqqqwwwww
6  1   x yy zzzzz
7  4   xqwe yyqqwwee zzzzzqqqqqwwwwweeeee
问题是num>1的每个观察值实际上包含多个“观察值”的数据,我想使用SAS中的一些逻辑将其拆分。下面是我想要得到的一个例子:

mydatawanted
-------------------
id num A B C
1  1   x yy zzzzz
2  1   x yy zzzzz
3  1   x yy zzzzz
3  1   q qq qqqqq
4  1   x yy zzzzz
5  1   x yy zzzzz
5  1   q qq qqqqq
5  1   w ww wwwww
6  1   x yy zzzzz
7  1   x yy zzzzz
7  1   q qq qqqqq
7  1   w ww wwwww
7  1   e ee eeeee
基本上,如果num>1,我希望根据每个变量的长度,为每个项目获取每个变量的子字符串,然后将它们作为num=1的新观察值输出。以下是我迄今为止尝试编写的代码:

data mydata2(drop=i _:);
    set mydata; /*use the data from the original data set */
    _temp_id = id; /*create temp variables from the currently read observation */
    _temp_num = num;
    _temp_A = A;
    _temp_B = B;
    _temp_C = C;
    if (_temp_num > 1) THEN /* if num in current record > 1 then split them up */
        do i = 1 to _temp_num;
            id = _temp_id; /* keep id the same */
            num = 1; /* set num to 1 for each new observation */
            A = substr(_temp_A,i,i); /*split the string by 1s */
            B = substr(_temp_B,1 + 2 * (i - 1),i * 2); /*split the string by 2s */
            C = substr(_temp_C,1 + 5 * (i - 1),i * 5); /*split the string by 5s */
            OUTPUT; /* output this new observation with the changes */
        end;
    else OUTPUT; /* if num == 1 then output without any changes */
run;
然而,它并没有像我希望的那样工作(我加入了一些评论,以显示我认为在每一步都发生了什么)。它实际上会产生以下结果:

mydata2
-------------------
id num A B C
1  1   x yy zzzzz
2  1   x yy zzzzz
3  1   x yy zzzzz
3  1   q qq qqqqq
4  1   x yy zzzzz
5  1   x yy zzzzz
5  1   qw qqww qqqqqwwwww
5  1   w ww wwwww
6  1   x yy zzzzz
7  1   x yy zzzzz
7  1   qw qqww qqqqqwwwww
7  1   we wwee wwwwweeeee
7  1   e ee eeeee
此mydata2结果与mydatawanted结果不同。num=1的行很好,但是当num>1时,输出记录与我想要的有很大不同。但记录总数是正确的。我真的不确定发生了什么,因为这是我第一次尝试像这样复杂的SAS逻辑,但我希望能在修复代码或使用其他方法完成我想做的事情方面得到任何帮助。谢谢大家!


编辑:我修复了原始输入mydata语句的问题,并更新了该问题。

您的子字符串不正确。Substr接受参数
(原始字符串,开始,长度)
,而不是
(原始字符串,开始,结束位置)
。所以
length
应该是
1,2,5
而不是
i,i*2,i*5

        A = substr(_temp_A,i,1); /*split the string by 1s */
        B = substr(_temp_B,1 + 2 * (i - 1),2); /*split the string by 2s */
        C = substr(_temp_C,1 + 5 * (i - 1),5); /*split the string by 5s */

首先,我要做的是回到给你这些数据的人那里,和他们好好谈谈。这是一种糟糕的数据存储方式。哈哈,我同意!我相信他们这样做是为了设法节省空间。为了代码的简单性,我还建议删除
if
,并对每一行执行此操作。如果i=1,那么它不会做任何事情,但这段代码并不需要很长时间。除非你要解析数以千万计的记录,否则额外的时间不会太长,但代码的简单性会让维护变得更容易。哦,一方面我为这个简单的错误感到抱歉,但另一方面我真的很高兴它不是太复杂。这把它修好了。顺便说一句,关于if的观点很好,我实际上正在处理很多记录(不确定是否有数千万条,但可能在100万条左右?),但你是对的,这可能不会对速度产生太大影响。另外,再次感谢乔的帮助!