Using the Service Delivery Point data with Household and Female data

The service delivery point files were designed to describe the service delivery environment that the women in sampled households experience. Facilities within the same enumeration area (EA) as samples households were chosen to be interviewed. The EAID codes, which are unique to EAs across countries and years, can be used to merge information from the SDP files onto the female record. The codes for EAID in the household and female files and the SDP files correspond exactly.

IPUMS PMA has produced Stata, SPSS, SAS, and R code to assist users in calculating indicators at the EAID level and merge the information to the person record. Before this code can be used, users must insert variables from the SDP record.

Jump to:

  • First example (Stata only)
  • Second example (Stata, SPSS, SAS, and R)
  • Third example (accounting for facilities in nearby EAs)
  • First Example

    The outcome of this sample code is that the number of facilities that usually offer family planning services and the percent of all facilities in the EA that provide IUDs will be attached to the person records in the data file pma_00002.

    Note that cases of IUDPROV that are out of universe (code 99) are replaced with zero. The universe of IUDPROV is service delivery points that offer family planning services. Thus, out of universe cases do not offer any family planning services, and are recoded to No (code 0).


    local filepath "C:/Users/Documents/Data"
    local sdp_data "pma_00001.dta"
    local female_data "pma_00002.dta"
    local statvar1 iudprov
    local stat1 mean
    local statvar2 fpoffered
    local stat2 count
    set more off
    use "`filepath'/`sdp_data'"
    drop if consentsq == 0
    replace `stat1' = 0 if `stat1' == 99
    collapse (`stat1') `statvar1' (`stat2') `statvar2', by(eaid)
    merge 1:m eaid using "`filepath'/`female_data'"

    Second Example

    Below are examples of Stata, SPSS, SAS, and R code designed to arrive at the same outcome, which is to calculate a variable for whether there was a stockout of birth control pills in the EA and the average number of days the facilities were out of pills, if they were out of stock, also at the EA level. The original coding for PILLOBS is 1 = In stock and observed, 2 = In stock but not observed, 3 = Out of stock, and 99 = Not in universe. The universe is "service delivery points that provide birth control pills." The variable PILLOBS is recoded below so that is equal to 1 if the facility is out of stock, 0 if the facility is in stock or out of universe. When the SDP file is collapsed to the EA level, PILLOBS will keep the maximum value of all the facilities in the EA. This way, the maximum value will be 1 if at least one facility is out of stock, but will be zero if all facilities were in stock or did not provide pills.
    The universe of PILLOUTDAY is "Service providers that provide contraceptive pills, but are currently out of stock." The code below recodes PILLOUTDAY to missing if the case is not in universe or otherwise missing (eg. a non-interview). When the SDP file is collapsed to the EA level, PILLOUTDAY will become the mean number of days in each EA that the facilities were out of stock of birth control pills.


    replace pillobs = 0 if (pillobs != 3)
    replace pillobs = 1 if (pillobs ==3)
    replace pilloutday = . if pilloutday > 9000
    collapse (max) pillobs (mean) pilloutday, by (eaid)
    count if (pillobs == 1)
    merge 1:m eaid using "pma_000##"
    tab eaid if (pillobs == 1 & eligible == 1)


    recode pillobs (3=1)(1 thru 2=0)(94 thru 99=0).
    recode pilloutday (9994 thru 9999=SYSMIS).
    aggregate outfile 'sdp_aggregate.sav'
    /break = eaid
    /pillobs1 =max(pillobs)
    /pilloutday1 =mean(pilloutday).
    GET FILE='sdp_aggregate.sav'.
    descriptives pillobs1
    /statistics= sum.
    sort cases by eaid.
    save outfile='sdp_aggregate.sav'.
    GET FILE='Z:pma_000##.sav'.
    sort cases by eaid.
    save outfile ='pma_000##.sav'.
    MATCH FILES FILE='pma_000##.sav'
     /BY eaid.
    save outfile= 'merge_file.sav'.
    GET FILE= ' merge_file.sav'.
    compute outpills=0.
    if (eligible EQ 1 & pillobs1 EQ 1) outpills=1.
    recode outpills (1=1)(0=0).
    filter by outpills.
    Means tables=outpills by eaid
    filter off.


    data IPUMS.pma_000##;
    	set IPUMS.pma_000##;
    		if pilloutday >9000 then pilloutday= .;
    		if pillobs =3 then pillobs = 1;
    		else pillobs =0;
    PROC MEANS data=IPUMS.pma_000## nway;
    class eaid;
    var pillobs pilloutday;
    output out=IPUMS.pma_000##_1 max(pillobs) = pillobs mean(pilloutday) = pilloutday;
    select count(*) as N_obs
    from IPUMS.pma_000##_1
    where pillobs=1;
    PROC SORT data=IPUMS.pma_000##_1;
    by eaid;
    PROC SORT data=IPUMS.pma_000##;
    by eaid;
    data IPUMS.HHF_SDP;
     merge  IPUMS.pma_000##_1 IPUMS.pma_000##;
     by eaid;
    tables eaid;
    where pillobs=1 & eligible=1;


    ddi <- read_ipums_ddi("pma_000##.xml")
    SDP <- read_ipums_micro(ddi)
    ddi <- read_ipums_ddi("pma_000##.xml")
    HHF <- read_ipums_micro(ddi)
      mutate(pillobs = HHF$EAID %in% subset(SDP$EAID, SDP$PILLOBS == 3))%>%
      filter(pillobs==TRUE & ELIGIBLE==1)%>%
      select(EAID, n)

    Third Example

    The previous two examples calculate the service delivery environment for the facilities located within the same small enumeration area as the respondent. Below is some sample code for including information about public facilities that are not located in but serve the woman's EA. In other words, we want to count facilities that include the woman's EA in their catchment area. The code below counts the number of facilities that serve the EA but are located outside of it (outside_ea), are located in the woman's EA (inside_ea), and the total number of facilities serving or located in the EA (total_facilities). The code finds the EAs contained in variables EASERVED1 through EASERVED40 and creates another observation for the facility with the value of the EASERVED# variable assigned to EAID. The code below can work for extracts with multiple samples.


    gen inside_ea = 1
    gen outside_ea = 0
    levelsof sample, local(samp)
    forvalues i = 1(1)40 {
    *if the easerved is the same as the EA it's located in, replace with
    *missing code in order to ignore later
    replace easerved`i' = 99998 if easerved`i' == eaid
    foreach s in `samp' {
    levelsof facilityid if sample == `s', local(fac)
    foreach x in `fac' {
    forvalues i = 1(1)40 {
    *Create a new observation with that value of EAID
    set obs `=_N+1'
    levelsof easerved`i' if facilityid == `x' & sample == `s', local(temp_ea)
    *The new observation is the only one with missing values for the following
    *variables, so we assign them to the values of facility "x"
    cap replace eaid = `temp_ea' if eaid == .
    replace outside_ea = 1 if outside_ea == .
    replace facilityid = `x' if facilityid == .
    replace sample = `s' if sample == .
    *Remove observations that were not in universe
    drop if outside_ea == 1 & eaid > 90000
    gen total_facilities = 1
    collapse (sum) inside_ea outside_ea total_facilities, by(eaid sample)