| David Franklin, Blog | |
| 2019 Archive | |
| Back | dfranklinnh@gmail.com |
|
JanuaryThe vi editor is a efficient screen-oriented text editor and can be found on most Unix and Linux systems. It has a keyboard-driven interface. If you do not know it and it is available, try it -- there is a lot of information about it on the internet. Occassionally when a program is opened there are tabs in code which usually makes the file difficult to read. If the program is opened within the vi editor use the following command to change a tab character to two spaces: :%s/\t/ /g Hope this helps. FebruaryRecently was working on a system running a SAS program. Some weird data was appearing after a MERGE statement and inside a datastep -- a new derived variable in a second dataset had values of 'A', 'B', and 'C' but there was an unexpected value of 'D' present after the merge. Nothing was appearing in the SAS LOG. After some investigation it was found that the variable name existed in both datasets, the original and the newly derived dataset. It was the fact that both datasets had the same variable that was causing the weird situation. So how do we get SAS to tell us of a possible issue where there is the same variable in both datasets using the MERGE statement and that variable is not in the BY statement? Meet the SAS option MSGLEVEL which has two values:
To give some more detail as to when MSGLEVEL equals I, see below (reference SAS documentation):
It is this second part, the "writes a warning to the SAS log whenever a MERGE statement would cause variables to be overwritten." that would have shown that the variable was being overwritten but was hidden. Here is an example:
data one;
input subjid $ grp $ age;
cards;
C2451 A 21
C2452 B 45
C2453 C 52
C2454 D 64
;
run;
*Recalculated GRP variable;
data two;
input subjid $ grp $;
cards;
C2451 C
C2452 B
C2453 A
;
run;
options msglevel=n;
run;
data both;
merge one two;
by subjid;
run;
When this is run there is no indication that the variable GRP is in both datasets. If we change the MSGLEVEL settion to 'I' we will get something similar to that below:
options msglevel=i;
run;
data both;
merge one two;
by subjid;
run;
INFO: The variable VAR on data set WORK.ONE will be over written by data set WORK.TWO.
Hope this helps. MarchPROC MEANS and PROC SUMMARY, among others, can count the number of items in a dataset so both are available. Note I said 'items', not 'records' or 'observations'. Why the difference. Lets looks at a dataset and a PROC MEANS call: data one;
input subjid $ age;
infile cards missover;
cards;
M2522 16
M2561 20
M2562
M2565 43
;
run;
Running PROC MEANS produces the following:
proc means data=one noprint;
var age;
output out=rslt (drop=_type_) n=n;
run;
proc print data=rslt;
run;
*** OUTPUT ***
OBS _FREQ_ n
1 4 3
n=3, _FREQ_=4, why the difference? n counts the number of non-missing values while _FREQ_ gives the number of records. Hope this helps. AprilWith OPTIONS MPRINT, MLOGIC and SYMBOLGEN a lot can be sent to the SAS LOG including what SAS statements were used, what values were used in macro variables, among many other things. But what about the code if it is included in a %INCLUDE call? Come to the rescue the SOURCE2 option. This can be called two ways, either as: options source2; %include "../../macros/isodate.sas"; run; or %include "../../macros/isodate.sas" /source2; run; Hope this helps. MayHow many of us use the following to print out a macro variable value to the SAS LOG: %put mvar=&mvar; to print out a value to the SAS LOG? Since 9.3 there has been another way to write this so you need only print the macro variable out out once: %put &=mvar; Cleaner and more easier code to write. Hope this helps. JuneLets look at a datastep below:
data one;
input subjid $ age;
infile cards;
cards;
M2522 16
M2561 20
M2562
M2565 43
;
run;
A PROC PRINT produces the following: subjid age M2522 16 M2561 20 M2562 . Why not all data? There are two important INFILE statement options that control how data is read, MISSOVER and FLOWOVER, details of these which are:
If we do the following, only changing the INFILE statement as shown below:
data one;
input subjid $ age;
infile cards MISSOVER;
cards;
M2522 16
M2561 20
M2562
M2565 43
;
run;
the PROC PRINT produces the following: subjid age M2522 16 M2561 20 M2562 . |