【问题标题】:How to read this multi-format data in SAS?如何在 SAS 中读取这种多格式数据?
【发布时间】:2014-10-02 10:07:56
【问题描述】:

我有一个奇怪的数据集需要导入 SAS,根据格式将记录分成两个表,并完全删除一些记录。数据结构如下:

c Comment line 1
c Comment line 2
t lines init
a 'mme006'   M   8   99   15   '111 ME - RANDOLPH ST'
  path=no
    dwt=0.01  42427  ttf=1  us1=3  us2=0
    dwt=#0   42350  ttf=1  us1=1.8  us2=0  lay=3
    dwt=>0  42352  ttf=1  us1=0.5  us2=18.13
    42349  lay=3
a 'mme007'   M   8   99   15   '111 ME - RANDOLPH ST'
  path=no
    dwt=+0  42367  ttf=1  us1=0.6  us2=0
    dwt=0.01  42368  ttf=1  us1=0.6  us2=35.63 lay=3
    dwt=#0  42369  ttf=1  us1=0.3  us2=0
    42381  lay=3

只需要保留以adwt 或整数开头的行。

对于以a 开头的行,所需的输出是这样的表,称为“行”,其中包含行中的前两个非a 值:

 name   | type
--------+------
 mme006 | M
 mme007 | M

对于dwt/integer 行,表“itins”如下所示:

 anode | dwt  | ttf | us1 | us2   | lay
 ------+------+-----+-----+-------+-----
 42427 | 0.01 |   1 | 3.0 |  0.00 |
 42350 | #0   |   1 | 1.8 |  0.00 |   3
 42352 | >0   |   1 | 0.5 | 18.13 | 
 42349 |      |     |     |       |   3       <-- line starting with integer
 42367 | +0   |   1 | 0.6 |  0.00 |
 42368 | 0.01 |   1 | 0.6 | 35.63 |   3
 42369 | #0   |   1 | 0.3 |  0.00 |
 42381 |      |     |     |       |   3       <-- line starting with integer

到目前为止我的代码已经差不多了,但还不完全:

data lines itins;
  infile in1 missover;
  input @1 first $1. @;
      if first in ('c','t') then delete;
      else if first='a' then do;
        input name $ type $;
        output lines; end;
      else do;
        input @1 path=$ dwt=$ anode ttf= us1= us2= us3= lay=;
        if path='no' then delete;
        output itins; end;

问题:

  • “行”表是正确的,但我无法去掉“名称”值周围的引号(例如 'mme006'
  • 在“itins”表中,“ttf”、“us1”和“us2”已正确填充。但是,“anode”和“lay”始终为空,而“dwt”的值类似于 #0 42360.01 42,长度始终为 8 个字符,借用了 应该在“anode”中的部分内容.

我做错了什么?

【问题讨论】:

  • 我认为您在这里混合输入法时遇到了麻烦。去掉引号很容易(dequote()),但另一部分我不知道你可以用这种方式解决,因为anode 不能用命名输入读取。
  • 感谢dequote() 提示!对于允许在不修改输入数据的情况下导入anode 的替代方法有什么建议吗?

标签: import dataset sas


【解决方案1】:

DEQUOTE() 将删除匹配的引号。

您对dwt 的问题是您需要告诉它使用什么信息;所以如果 dwt 是四长,:$4. 而不仅仅是$

但是,阳极是个问题。我想出的解决方案是:

data lines itins;
  infile in1 missover;
  input @1 first $1. @;
      if first in ('c','t') then delete;
      else if first='a' then do;
        input name $ type $;
        output lines; end;
      else do;
        input @1 path= $ @;
        if path='no' then delete;
        else do;
            if substr(_infile_,5,1)='d' then do;
                input dwt= :$12. ttf= us1= us2= us3= lay=;
                anode=input(scan(dwt,2,' '),best.);
                dwt=scan(dwt,1,' ');
                output itins; 
            end;
            else do;
                input @5 anode 5. lay=;
                output itins;
            end;
        end;
    end;

run;

基本上,先检查计划;然后如果它不是计划行,请检查 dwt 中的“d”。如果存在,请像这样读取一行,将阳极合并到 dwt 中,然后再将其拆分。如果它不存在,只需读取阳极并铺设即可。

如果 dwt 可以具有 2-4 以外的宽度,因此它可能需要更短,那么这可能不起作用,您必须明确找出阳极的位置才能正确读取它。

【讨论】:

  • 谢谢,@Joe,这似乎几乎可以工作。我收到anode+lay= 行的错误,但是,在if substr(_infile_,5,1)='d' then do 块期间出现(奇怪):NOTE: NAME, '42349 lay' is not defined.
  • 您很可能需要摆弄 if 条件。这就是 if / else do; 应该避免的:识别只是 anode+lay 的行,不要尝试在它们上使用其他输入字符串。上一行的lay= 可能正在下一行搜索lay,我不完全确定它是如何工作的。
  • 条件似乎很好,因为anode+lay= 行随后被else 块正确读取,因此输出表实际上是完整的。我对此感到非常困惑。
  • 我认为这是由上一行的lay= 寻找下一个要读入的字段引起的(因为它默认为flowover)。如果您将其更改为 truncovermissover 它可能会起作用(我认为其他任何东西都不会受到影响,但不确定)。
  • 嗯,不管有没有,它也发生在missover。我不确定为什么 SAS 应该在那里寻找下一行 - 但我对这种输入方式没有太多经验。
猜你喜欢
  • 1970-01-01
  • 2013-08-06
  • 2014-08-04
  • 2018-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多