

*********************************************************************************************************;
* September 2026                                                                                        *;
*                                                                                                       *;
* 2016 NHCS-NDI Synthetic Datasets                                                                      *;
* Example SAS code                                                                                      *;
*                                                                                                       *;
* The following SAS code can be used to read the 16 implicate text files                                *;
* (provided in comma-separated value or .csv format)                                                    *;
* from a stored location into a temporary SAS work dataset.                                             *;
*                                                                                                       *;
* *********************************************************************************************         *;                                                                                                       *;
* This code assumes that you have downloaded all 16 implicate text files to a location on your computer.*;
* In this example, the data file is saved in the folder, "C:\PUBLIC USE DATA\", and the                 *;
*          data files are saved as "NHCS_NDI_Final_1.csv" through "NHCS_NDI_Final_16.csv".              *;
*********************************************************************************************************;


*******************;
* MACRO VARIABLES *;
*******************;

** This is the file location where you have downloaded the public files on your computer.;
%*LET INFILE_PATH=C:\PUBLIC USE DATA\;


** This is the file location where you want to save the SAS datasets. ;
** For a temporary SAS dataset, you can specify the libname as (work) ;
** To save as a permanent SAS dataset, provide a directory path in the libname in quotation marks;
libname OUTLIB (work);

****************************************************;
* Read in NHCS-NDI synthetic implicates files  *;
****************************************************;
options mprint;
%macro NHCSsynthIn(nImplicates=);
  %* read in CSV files for implicates *;

  %* Loop over all 16 implicate files *;
  %do f=1 %to &nImplicates. ;

   %* implicate number with leading zero (01, 02, etc.) to match file name *;
    %let ff=%left(%qsysfunc(putn(&f.,z2.)));


    %* read in each file *;
    data OUTLIB.NHCS_NDI_Final_&f.;
      %let _EFIERR_ = 0; 
      infile "&INFILE_PATH.\nhcs_ndi_v11_imp&ff._final.csv"  delimiter = ',' MISSOVER DSD lrecl=32767 firstobs=2 ;
      input SEQNUM COPD_IND DIABETES_IND DSCHRG_STUS_CD HEART_DISEASE_IND LAST_ENC_SETTING MENTAL_HEALTH_IND MONTH_LAST_ENC MORTSTAT P_AGE_CD
        P_RACE_ETHNCTY_CD P_SEX_CD P_URBRURAL_CD SEPSIS_IND TIME_TO_DEATH_CD TOT_ED_ENC TOT_ICU_DAYS TOT_IP_ENC TOT_OPIOID_ENC UCOD_LEADING 
        ED_ENCOUNTER_POSTIP_IND DRUG_OVRDSE_DEATH DRUG_OVRDSE_DEATH_ANYOPIOID UCOD_HEART_DISEASE UCOD_CANCER UCOD_CHRONIC_LOWER_RESP_DISEASE 
        UCOD_UNINTENTIONAL_INJURIES UCOD_STROKE UCOD_ALZHEIMERS_DISEASE UCOD_DIABETES UCOD_INFLUENZA_AND_PNEUMONIA UCOD_KIDNEY_DISEASE P_URBRURAL_CD_R 
        TOT_IP_ENC_R1 TOT_IP_ENC_R2 TOT_ED_ENC_R1 TOT_ED_ENC_R2 TOT_OPIOID_ENC_R DSCHRG_STUS_CD_R DEATH_WITHIN_30DAYS DEATH_WITHIN_60DAYS DEATH_WITHIN_90DAYS
        DRUG_OVRDSE_DEATH_R DRUG_OVRDSE_DEATH_ANYOPIOID_R TOT_ICU_DAYS_R1 TOT_ICU_DAYS_R2 P_AGE_CD_R ;        
      if _ERROR_ then call symputx('_EFIERR_',1);  
    run;

  %end;

%mend NHCSsynthIn;
%NHCSsynthIn(nImplicates=16);

* Append all synthetic files for ease of use in SAS procedures *; 

data OUTLIB.synth_all;
  set OUTLIB.NHCS_NDI_Final_1 - OUTLIB.NHCS_NDI_Final_16 indsname=dsin;
  * Create a new variable that contains the implicate number for each record *;
  _imputation_=input(substr(dsin, anydigit(dsin)), best3.);
  format _imputation_ z2.;
run;

* Note: each implicate file should have 2,916,833 observations. The appended file should have 46,669,328 observations *;

*******************************************************************;

******************************;
** EXAMPLE                  **;
** Basic Frequency Analysis **;
******************************;

* The code below provides an example for performing univariate frequencies or bivariate frequencies (cross-tabulation). *;
* There are multiple methods to code this type of analyses.                                                             *;
* There may be slight differences in estimates among estimates produced with different methods in SAS or methods        *;
*   implemented in different statistical software packages.                                                             *;

****************************************************;
* Frequencies using Proc SURVEYFREQ                *;
****************************************************;
* SAS Survey procedures are typically not needed to analyze unweighted data that do not include survey design variables.  *;
* However, the SURVEYFREQ procedure with multiply imputed data provides a straightforward and efficient way for           *;
* calculating standard errors (SE)that are needed to combine the implicates using Rubin’s combining rules.                *;
* In this example, the SURVEYFREQ procedure is used instead of Proc FREQ only because it will produce the standard errors *;
* of the proportion for each level of the analysis variable (e.g. P_SEX_CD=1 and P_SEX_CD=2) in a single call.            *;
* Each analysis is performed on the appended dataset using a “BY” statement to produce separate estimates for each        *;
* implicate, and the intermediate results are written to an output dataset. Then PROC MIANALYZE is used to combine        *;
* the estimates from each implicate to produce the overall estimates.                                                     *;
* This method expresses estimates as a percent (range 0-100).                                                             *;


* Note: you may see a note in the SAS log such as:                                                                            *;
*    "The BY statement provides completely separate analyses of the BY groups. It does not provide a statistically valid      *;
*    subpopulation or domain analysis."                                                                                       *;
*    This is not a concern - in this example, we are requesting that statistics be calculated separately for each implicate.  *;

  ****************************;
  ** Univariate Frequencies **;
  ****************************;

  * use the "BY" command to produce separate estimates for each imputation *;
  proc surveyfreq data = OUTLIB.synth_all missing;
    tables P_SEX_CD P_AGE_CD;
    by _imputation_;
    * for univariate frequency, save the ODS table "OneWay” as an intermediate dataset ;
    ods output OneWay=freq_oneway;
  run;

proc freq data = OUTLIB.synth_all;
    tables UCOD_HEART_DISEASE P_SEX_CD P_AGE_CD TOT_ICU_DAYS/missing;
    by _imputation_;
    * for univariate frequency, save the ODS table "OneWay” as an intermediate dataset ;
    *ods output OneWay=freq_oneway;
  run;


  * prepare output for Proc MIANALYZE (remove "total" rows and sort by the analysis variables);
  proc sort data=freq_oneway (where=(_skipline ne "1")) out=freq_oneway2;
    by P_SEX_CD P_AGE_CD;
  run;
 proc print data = freq_oneway2(obs = 50);run;

  * call Proc MIANALYZE to combine the results from all imputations using Rubin's rules *;
  proc mianalyze data=freq_oneway2;
    by P_SEX_CD P_AGE_CD;
    modeleffects percent ;
    stderr stderr;
    ods output ParameterEstimates=freq_oneway_combined;
  run;


  * The final combined estimates are printed in the list output and saved in dataset freq_oneway_combined *;
  

  ***************************************;
  * Bivariate frequencies (Cross-Freqs) *;
  ***************************************;
  * use the "BY" command to produce separate estimates for each imputation *;
  proc surveyfreq data = OUTLIB.synth_all missing;
    tables P_SEX_CD*P_AGE_CD;
    by _imputation_;
    * for cross-frequency, save the ODS table "CrossTabs” as an intermediate dataset ;
    ods output CrossTabs=freq_crosstab;
  run;

  * prepare output for Proc MIANALYZE (remove "total" rows and sort by the analysis variables);
  proc sort data=freq_crosstab (where=(_skipline ne "1" and P_SEX_CD ne . and P_AGE_CD ne .)) out=freq_crosstab2;
    by P_SEX_CD P_AGE_CD;
  run;

  * call Proc MIANALYZE to combine the results from all imputations using Rubin's rules *;
  proc mianalyze data=freq_crosstab2 ;
    by P_SEX_CD P_AGE_CD;
    modeleffects percent ;
    stderr stderr;
    ods output ParameterEstimates=freq_crosstab_combined;
  run;
  * The final combined estimates are printed in the list output and saved in dataset freq_crosstab_combined. *;  


*********************************;
** EXAMPLE                     **;
** Basic Regression Analysis   **;
** using SAS proc LOGISTIC     **;
*********************************;

* The code below provides an example for performing a binomial logistic regression and provides the method to combine          *;
* the results accurately for multiply imputed files.                                                                           *;
* Unlike with frequency analysis, the use of SAS survey procedures provide no advantage over the using standard SAS procedures *;
* for basic logistic regression analysis when analyzing multiply imputed files. Therefore, the following examples use 	       *;
* Proc LOGISTIC.                                                                                                               *;
*                                                                                                                              *;
* The regression is performed on the appended dataset using a “BY” statement to produce separate estimates for                 *;
* each implicate, and the intermediate results are written to an output dataset. Then PROC MIANALYZE is used to                *;
* combine the estimates from each implicate to produce the overall estimates.                                                  *;


proc logistic data=OUTLIB.synth_all ;
by _imputation_;
class P_AGE_CD(ref = "1") P_SEX_CD(ref = "1") P_RACE_ETHNCTY_CD(ref = "1") P_URBRURAL_CD(ref = "1") HEART_DISEASE_IND(ref = "0") TOT_ICU_DAYS(ref = "0") / param=ref;
model UCOD_HEART_DISEASE(EVENT= "1") = P_AGE_CD P_SEX_CD P_RACE_ETHNCTY_CD P_URBRURAL_CD HEART_DISEASE_IND TOT_ICU_DAYS;
* save the ODS table "ParameterEstimates" as an intermediate dataset ;
ods output ParameterEstimates=LR_PE_implicates;
run;

 * prepare output for Proc MIANALYZE *;
  proc sort data=LR_PE_implicates ;
    by variable classval0;
  run;

  * call Proc MIANALYZE to combine the results from all imputations using Rubin's rules *;
  proc mianalyze data=LR_PE_implicates;
    by variable classval0;
    modeleffects Estimate;
    stderr StdErr ;
    ods output ParameterEstimates=LR_ParameterEstimates ;
  run;
  * The final combined estimates are printed in the list output and saved in dataset ParameterEstimates. *;




******************************************************************;
** EXAMPLE                                                      **;
** Basic Regression Analysis on a Subpopulation (or "universe") **;
** using SAS proc logistic regression                           **;
******************************************************************;

proc logistic data=OUTLIB.synth_all(where=(MORTSTAT=1));
by _imputation_;
class P_AGE_CD(ref = "1") P_SEX_CD(ref = "1") P_RACE_ETHNCTY_CD(ref = "1") P_URBRURAL_CD(ref = "1") HEART_DISEASE_IND(ref = "0") TOT_ICU_DAYS(ref = "0") / param=ref;
model UCOD_HEART_DISEASE(EVENT= "1") = P_AGE_CD P_SEX_CD P_RACE_ETHNCTY_CD P_URBRURAL_CD HEART_DISEASE_IND TOT_ICU_DAYS;
* save the ODS table "ParameterEstimates" as an intermediate dataset ;
ods output ParameterEstimates= sub_LR_PE_implicates_univ;
run;

* prepare output for Proc MIANALYZE *;
  proc sort data=sub_LR_PE_implicates_univ ;
    by variable classval0;
  run;

 * call Proc MIANALYZE to combine the results from all imputations using Rubin's rules *;
  proc mianalyze data=sub_LR_PE_implicates_univ;
    by variable classval0;
    modeleffects Estimate;
    stderr StdErr ;
    ods output ParameterEstimates=sub_LR_ParameterEstimates_univ ;
  run;

  * The final combined estimates are printed in the list output and saved in dataset ParameterEstimates. *;
