【问题标题】:Reading data into SAS, columns not aligned将数据读入 SAS,列未对齐
【发布时间】:2014-03-05 00:06:54
【问题描述】:

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

001 Mayo Clinic  120 78 7 15 
Patient has had a persistent cough for 3 weeks
023 Mayo Clinic  157 72 10 2 
Patient complained of ear ache
064 HMC  201 59 . . 
Patient left against medical advice
003 HMC  166 58 8 15 
Patient placed on beta-blockers on 7/1/2006

我发现将其读入 SAS 的任务基本上是不可能的。不,在这种情况下,重新格式化数据文件是不可能的。所以让我解释一下你在这里看到的内容:

每个主题都有两行数据。第一行是-

受试者编号/诊所/wt/hr/dx/sx (不要担心数字是什么意思,这无关紧要)。

第二行是文本,它基本上是一个包含额外信息的注释,涉及到其数据在前一行中列出的主题。所以,这些行:

001 Mayo Clinic  120 78 7 15 
Patient has had a persistent cough for 3 weeks

适用于单一主题。主题 001。这些需要成为 SAS 数据集中的单行。我完全不知所措;由于诊所名称的长度不同,并且数字列未对齐,我无法弄清楚如何让 SAS 读取它。这是我能得到的最接近的:

data ClinData;
    infile "&wdir.clinic_data.txt";
    retain patno clinic weight hr dx sx exinfo;
    input patno clinic $1. @;
    if clinic='M' then
        input patno @5 clinic $11. weight hr dx sx / @1 exinfo $30.;
    else if clinic='H' then
        input patno @5 clinic $3. weight hr dx sx / @1 exinfo $30.;
    run;

这打印为:

http://i61.tinypic.com/2uswl90.png

所有数值都在正确的位置。

但是,这有几个问题。

首先,主题编号 ('patno') 始终显示为缺失值。为什么?

其次,诊所仅由其第一个字母“M”或“H”表示。我无法让 SAS 根据它所在的诊所来更改诊所变量的长度。

第三,变量“exinfo”包含有关患者的注释。但是,我无法让 SAS 包含整条生产线。在格式化失控之前,我能得到的最高值是大约 30 个字符。

有什么帮助吗?对于这种类型的输入,SAS 文档非常糟糕。这些示例都没有真正符合我的需要,并且没有充分解释如何使用某些选项。我知道我需要使用列/行指针;但问题是各行的列不一致。所以无论我使用哪种指针格式,仍然会有不正确的行。

【问题讨论】:

    标签: sas


    【解决方案1】:

    在 SAS 中没有什么是不可能的。查看您的样本数据,我注意到您的诊所名称后面有两个空格,并且您的患者编号始终是三个字符。如果这始终是正确的,您可以利用它来发挥自己的优势:

    data want;
      length patno $3 clinic $20 weight hr dx sx 8 exinfo $80;
      input;
      patno  = scan(_infile_,1,' ');
      clinic = substr(_infile_,5,index(_infile_,'  ')-5);
      weight = input(scan(_infile_,-4,' '),8.);
      hr     = input(scan(_infile_,-3,' '),8.);
      dx     = input(scan(_infile_,-2,' '),8.);
      sx     = input(scan(_infile_,-1,' '),8.);
      input exinfo $80.;
    
    datalines;
    001 Mayo Clinic  120 78 7 15 
    Patient has had a persistent cough for 3 weeks
    023 Mayo Clinic  157 72 10 2 
    Patient complained of ear ache
    064 HMC  201 59 . . 
    Patient left against medical advice
    003 HMC  166 58 8 15 
    Patient placed on beta-blockers on 7/1/2006
    run;
    

    基本上这是解析自动变量_INFILE_来读取每个变量。 “困难”部分是如何阅读诊所名称(因为它包含嵌入的空白)。如果诊所并不总是有那个双空白,您仍然可以通过substrindex 和/或scan 函数的其他操作来完成。如果是这样,我会留给你的。

    此外,在创建新数据集时,请始终使用长度语句定义变量,以确保它们具有正确的长度,尤其是对于字符变量。

    【讨论】:

    • 哈,是的,我并不是说这在 SAS 中是不可能的,而是说我在没有帮助的情况下是不可能的。我知道这是可能的。无论如何,感谢您的帮助!直到当天晚些时候我才能再次查看该数据集,所以我会在下午尝试这个,如果有任何问题,请告诉您。
    【解决方案2】:

    您遇到的大多数问题都是由于您明确声明的长度。例如 Clinic 在初始输入语句中被定义为 $1 并且您不能在您尝试在第二个输入行中修改事实之后的长度。

    这应该让你更接近你正在寻找的东西:

    data ClinData(drop=s varlen);
      retain patno clinic weight hr dx sx; 
    
      input patno clinic $30. @;
        clinic=compress(clinic,,'ka');
        s=length(clinic)+4+2;
       input @s weight hr dx sx /@; 
         varlen=length(_infile_); 
        input  @1 exinfo $varying256. varlen;
    
    datalines4;
    001 Mayo Clinic  120 78 7 15 
    Patient has had a persistent cough for 3 weeks
    023 Mayo Clinic  157 72 10 2 
    Patient complained of ear ache
    064 HMC  201 59 . . 
    Patient left against medical advice
    003 HMC  166 58 8 15 
    Patient placed on beta-blockers on 7/1/2006
    ;;;;
    run; 
    proc print data=ClinData; run;
    

    【讨论】:

    • 欢迎。我任意设置了诊所和 exinfo 字段的长度(分别为 30 美元和 256 美元)。您可能希望将它们调整为更小的长度,尤其是在文件相当大或经常构建的情况下,因为文件大小将代表分配的空间(30 和 256),即使该字段中包含的最长长度明显更小(即: 11 和 48)。
    【解决方案3】:

    您以奇怪的方式混合输入类型,导致您无法正确阅读。

    您的诊所长度为 1,因为您将其作为一个字符输入,将其定义为 1。不要这样做 - 如果需要,请使用一次性变量 - 并将其长度定义为更长的值。

    我推荐如下方法。使用 INFILE(在输入过程中创建的包含一行数据的自动变量)比尝试单独使用输入技术更容易。您的数据非常简单;如果它比你提供的更复杂(例如你有比这更多的诊所),正则表达式或其他逻辑可能会进一步帮助 - infile 将更容易解析。还有 ANYDIGIT 和 NODIGIT 等类似功能,加上 COMPRESS,可能会有所帮助。

    data want;
    length clinic $12;
    input 
    @1 patid 3. @;  *hold input so _infile_ exists and we can play with it.  Might as well read in patid here.;
    array numvars weight hr dx sx; *we are going to read this in via array;
    do _t = 4 to 1 by -1;  *we are going through the string in backwards order;
     numvars[_t] = scan(_infile_,(_t-5),' '); *(_t-5) is giving us 4 -> -1 3 -> -2 etc.- I include space explicitly here as I think period otherwise might count which is bad;
    end;
    clinic = scan(_infile_,2); *start out using the 2nd word;
    if scan(_infile_,3) = 'Clinic' then clinic=catx(' ',clinic,scan(_infile_,3)); *then maybe add the third word.  Here you could also check if compress(scan(_infile_,3),,'ka') is not missing;
    input;
    input @1 exinfo $50.;
    put _all_;
    datalines;
    001 Mayo Clinic  120 78 7 15 
    Patient has had a persistent cough for 3 weeks
    023 Mayo Clinic  157 72 10 2 
    Patient complained of ear ache
    064 HMC  201 59 . . 
    Patient left against medical advice
    003 HMC  166 58 8 15 
    Patient placed on beta-blockers on 7/1/2006
    ;;;;
    run;
    

    【讨论】:

    • 感谢您的帮助!我要等到下午晚些时候才能对此进行测试。如果我有任何问题,我会告诉你的。再次感谢!
    猜你喜欢
    • 2015-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-24
    • 2011-11-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多