Using unistats with Lab data (3)

Last updated: 10 Jan 2012

Introduction

I am going to show you a very complex use of %unistats for lab data reporting. I am going to transpose not only by statistics name but by treatment arm as well. But to make it more complicated, the treatment arm is a timepoint I have chosen ("Value at visit"=1 and "Change from baseline"=2) and nothing to do with a real treatment arm such as Placebo and Drug.

You might (and should) question why I am using the macros in such a strange fashion. The answer being that the macros were designed to do all the complicated work for you and were designed to handle many situations. The idea is that if you use the macros for creating tables then the work you have to do is mostly in selecting the data and feeding it to the macros and displaying the results afterwards (if the macro can not do it). Tables should just be tabulations. And by "tabulations" it means that you should not be doing any processing work. You should just select the data, feed it into the macro, and if it can not display the results you want then you do so using "proc report" on the output dataset but at no time do you do any "real processing" of the data because that would need "validation" and the Spectre macros should be "validated" already and able to do the work for you without any worries. They have been in use since 2006 and have never been known to produce a wrong value (except in the case of sparse p-value statistics that got fixed a few years ago). You can rely on them completely and they can do a few things for you like transpose the results any way you wish. You are going to see a complex example that I will explain.

The Challenge

I'm first going to explain why I have to do some crazy stuff with the macros. It all stems from having a "proc report" "across" variable that must not use up a line due to a strict client requirement. This is not possible with "across" variables and "proc report" so to get round it the variables need to be transposed somehow and I don't want to do the transpose in the macro code. Below in the box is the header columns of the output I want to create. What is important here is that there is no avaliable line above the "_Value at Visit_" and "_Difference from baseline_" line to have a "proc report" "across" variable so if the character variable being displayed are named "NSTR", "MEANSTR" etc. then they need to be named something like "N1STR", "N2STR", "MEAN1STR", "MEAN2STR" etc. so that there is no "across" variable but instead just a list of variables with the "across" variable value as part of the name of the variable which in this case is "1" and "2". The "1" list we will label as '("__Value at Visit__" N1STR MEAN1STR STD1STR MIN1STR MEDIAN1STR MAX1STR)' and the next group '("__Difference from baseline__" N2STR MEAN2STR STD2STR MIN2STR MEDIAN2STR MAX2STR)'. I have a timepoint variable named tp which is "1" for "Value on Visit" and "2" for "Difference from baseline" and I am going to tell the %unistats macro that "tp" is my treatment arm variable even though it is not. It is just the "across" variable. %unistats will accept it and use the value of this variable to create the statistics variable names as listed in this paragraph. But there is a minor problem with doing this.....
 
________________________________________________________________________________________________________________________________________________________
Treatment/                   ______________________Value at Visit______________________   _________________Difference from baseline_________________
  Visit                            N*      Mean        SD       Min    Median       Max         N*      Mean        SD       Min    Median       Max
________________________________________________________________________________________________________________________________________________________

The "minor problem" explained

The minor problem with telling %unistats to use a treatment variable that it did not expect is that it relies on the %popfmt macro to tell it what the values of the treatment arm variable are. These will be written to the global macro variable _trtvallist_ . It expects the unique values to be there. This is better than scanning the input dataset which might have a million observations or more. It assumes you ran %popfmt on a demography dataset with just a few hundred observations and was easily able to list out the unique treatment identifiers. But supposing you have not done this? Most likely you have run %popfmt on the treatment arm variable just to create a format that has the "(N=xxx)" label at the end and now you are not going to use the information it provided for you in the global macro variables. It might have told you that &_trtvallist_ = 010 500 but that is no use to you because you are about to use "tp" as the treatment variable and that only contains the values "1" and "2". But you can specify this directly. You can either set "%let _trtvallist_=1 2;" to override what %popfmt set up or supply it to the %popfmt macro directly using a parameter in the form "trtvallist=1 2" like I did in the following example. After this I merge with some lab info. You will see that we still refer to the treatment arm variable &trtvar but this is now just a "by" variable. Note that like in the example on the previous page I am adjusting the number of decimal places displayed using the contents of the variable dpvar=rounding. I am switching off messages using msgs=no and I am adjusting the number of spaces to the right of a missing value using misspad=yes.
 
                /**************************
                         Summarize
                 **************************/

  %let wherecls=and _hasbase=1 and _haslast=1;
  %if &showmiss EQ Y %then %let wherecls=;

  %unistats(dsin=_laball3(where=((_fgprev or _fgontv or _fgpostv) &wherecls and missing(_fgrept))),
  print=no,varlist=_val,msglevel=X,padmiss=yes,msgs=no,
  trtvar=_tp,trtfmt=tpfmt.,dpvar=rounding,trtvallist=1 2,
  byvars=&trtvar labnm labnmx &labunit _phase _period visno _vistext,
  nfmt=5.,stdfmt=5.,minfmt=5.,maxfmt=5.,meanfmt=5.,
  descstats=&descstat,dstranstattrt=_transtat,leftstr=yes);
 

                /**************************
                     Add lab group order
                 **************************/

  *- add in the lab group info -;
  proc sql noprint;
    create table _transtat2 as (
    select a.*, b.labgrp, b.labgrpx, b.labnmor
    from _transtat as a
    left join _labgrp as b
    on a.labnm=b.labnm
    ) order by labgrp, labgrpx, labnmor, labnm, labnmx;
  quit;

The list of numeric statistics variables will be the list of "keywords" held in &_statkeys_ and the corresponding character variables will have the same name but ending in "1STR" or "2STR". A little later in the code I list these character variables that I need to use in a "proc report" step. Look carefully at the way I refer to them. Look for %suffix(1STR,&_statkeys_) and %scan(&_statkeys_,&i,%str( ))&j.STR
 
                /**************************
                       Produce report
                 **************************/

  %let ncolw=8;
  %if %words(&_statkeys_) GT 6 %then %let ncolw=6;

  proc report missing headline headskip nowd split="@" data=_transtat2 spacing=2; 
    by labgrp labgrpx labnmor labnm labnmx &labunit;
    columns ("%sysfunc(repeat(%sysfunc(byte(131)),%eval(&repwidth-1)))"
              &trtvar _phase _period visno _vistext 
            ("_Value at visit_" %suffix(1STR,&_statkeys_)) 
            ("_Difference from %lowcase(&bslnlbl)_" %suffix(2STR,&_statkeys_))
            ); 
    define &trtvar / order order=internal noprint;
    define _phase / order noprint;
    define _period / order noprint;
    define visno / order noprint;
    define _vistext / id order width=26 "Treatment/" "  Visit" spacing=0;
    %do j=1 %to 2;
      %do i=1 %to %words(&_statkeys_);
        %let key=%scan(&_statkeys_,&i,%str( ))&j.STR;
        %let spac=;
        %if &i EQ 1 %then %let spac=spacing=⪆
        define &key / display width=&ncolw &spac right;
      %end;
    %end;
    compute before &trtvar;
      line @1 &trtvar &_popfmt_.;
    endcompute;
    break after _phase / skip;
  run; 

Conclusion

You have seen how to use the macro %unistats with a different treatment arm variable to provide a more "flattened" report.

 

Use the "Back" button of your browser to return to the previous page.

contact the author





















SAS and all other SAS Institute Inc. product or service names are registered trademarks or trademarks of SAS Institute Inc. in the USA and other countries. ® indicates USA registration.