Computing Confidence Interval Functions with cifunction

A Stata Package for Visualizing Statistical Uncertainty

statistics
stata
confidence intervals
data visualization
statistical methods
Learn how to compute and visualize confidence interval functions (confidence curves, p-value functions) using the cifunction Stata package. Includes practical examples and implementation guide.
Author

Zad R

Published

March 23, 2024

Last updated

May 26, 2026

Abstract

The cifunction package for Stata computes and graphically displays all possible confidence intervals around a point estimate, creating what’s known as a confidence interval function, confidence curve, p-value function, or consonance interval. This approach conveys more information than traditional single-level confidence intervals by showing the full range of values compatible with the data at all confidence levels.

Keywords

confidence interval function, confidence curve, p-value function, consonance interval, Sullivan and Foster, Stata statistical software, statistical visualization, uncertainty quantification

1 Overview

Traditional confidence intervals present a single level of uncertainty (typically 95%), but this dichotomous approach discards valuable information about the data. The confidence interval function (CI-function) provides a more complete picture by displaying all possible confidence intervals simultaneously.

NoteAlternative Names

The CI-function has been described in the literature under various names:

  • Confidence curve1
  • P-value function2, 3
  • Consonance interval4
  • Confidence density5

2 Installation

Install cifunction from SSC (Statistical Software Components):

3 Syntax

{stata, echo=TRUE, collectcode=TRUE, statapath="/Applications/StataNow/StataMP.app/Contents/MacOS/StataMP"}cifunction #b, se(#) [options]

3.1 Required Arguments

Required parameters for cifunction
Argument Description
#b Point estimate (coefficient or exponentiated value like OR, HR, IRR)
se(#) Standard error of the estimate

3.2 Optional Arguments

Optional parameters for cifunction
Option Description
df(#) Degrees of freedom (for t-distributed estimates)
eform Indicates coefficient is exponentiated (OR, RR, IRR)
figure[(options)] Produces CI-function plot with optional twoway options
saving(filename, replace) Saves results to file

4 Understanding CI-Functions

A CI-function graphically represents the relationship between confidence levels and confidence intervals:

  • Peak of curve: Indicates the point estimate
  • Concentration around peak: Reflects precision of estimate
  • Narrow curve: High precision (large sample size)
  • Broad curve: Low precision (small sample size)

4.1 Advantages Over Single-Level CIs

  1. Complete information: Shows compatibility of all values with data
  2. Precision visualization: Curve width directly shows estimate precision
  3. Multiple comparisons: Reveals whether data provide reassurance about null effects
  4. Nuanced interpretation: Moves beyond binary “significant/non-significant” thinking
TipInterpretation Guide

Values toward the peak are more compatible with the observed data (assuming the statistical model is correct). The curve explicitly shows the gradual nature of statistical evidence rather than suggesting arbitrary cutoffs.

5 Practical Examples

5.1 Example 1: Basic Risk Ratio

Reproducing Figure 1 from Sullivan and Foster (1990):

* Get standard error for RR=2.0 with p=0.05
getregstats 2.0, p(0.05) mod(rr)

* Create CI-function with log-scaled x-axis
cifunction 2.0, se(.707306) eform ///
    fig(xscale(log) xlab(0.5 1 2 5 10) ///
    xtitle("Risk Ratio (Log Scale)"))
#> Can not set Stata directory, try using -statapath(
#> > )- option
#> r(601);
#> 
#> 
#> 
#> 
#> --------------------------------------------------
#> > ----------------------------
#>              | Risk Ratio   Std. Err.      z    P>
#> > |z|                                             
#> >         [95% Conf. Interval]
#> -------------+------------------------------------
#> > ----------------------------
#>    Estimates |          2    .707306    -1.96   0.
#> > 050                                             
#> >                1                                
#> >                            4
#> --------------------------------------------------
#> > ----------------------------

5.2 Example 2: Age-Stratified Rate Ratios

Using Doll-Hill smoking data, stratified by age group:

* Load data and fit models
webuse dollhill3, clear

* Fit Poisson models for each age category
forvalues i = 1/4 {
    poisson deaths smokes if agecat==`i', exposure(pyears) irr
}

* Plot all four age-stratified CI-functions
cifunction 5.736638 2.138812 1.46824 1.35606, ///
    se(4.181258 .6520701 .295728 .2748845) eform ///
    fig(xscale(log) xlabel(.3 .5 1 2 5 10 20 50 100) ///
    legend(label(1 "35-44") label(2 "45-54") ///
           label(3 "55-64") label(4 "65-74") ///
           title("Age Group", size(small))) ///
    xtitle("Rate Ratio (Log Scale)"))
#> Can not set Stata directory, try using -statapath(
#> > )- option
#> r(601);
#> 
#> 
#> (Doll and Hill (1966))
#> 
#>   3. }
#> 
#> Iteration 0:  Log likelihood = -4.0705386  
#> Iteration 1:  Log likelihood = -3.9613823  
#> Iteration 2:  Log likelihood = -3.9612634  
#> Iteration 3:  Log likelihood = -3.9612634  
#> 
#> Poisson regression                                
#> >       Number of obs                             
#> >                     =      2
#>                                                   
#> >       LR chi2(1)                                
#> >                     =   9.73
#>                                                   
#> >       Prob > chi2                               
#> >                     = 0.0018
#> Log likelihood = -3.9612634                       
#> >       Pseudo R2                                 
#> >                     = 0.5511
#> 
#> --------------------------------------------------
#> > ----------------------------
#>       deaths |        IRR   Std. err.      z    P>
#> > |z|                                             
#> >         [95% con                                
#> >                 f. interval]
#> -------------+------------------------------------
#> > ----------------------------
#>       smokes |   5.736638   4.181258     2.40   0.
#> > 017                                             
#> >         1.374811                                
#> >                     23.93712
#>        _cons |   .0001064   .0000753   -12.94   0.
#> > 000                                             
#> >         .0000266                                
#> >                     .0004256
#>   ln(pyears) |          1  (exposure)
#> --------------------------------------------------
#> > ----------------------------
#> Note: _cons estimates baseline incidence rate.
#> 
#> Iteration 0:  Log likelihood = -5.4793565  
#> Iteration 1:  Log likelihood = -5.4104407  
#> Iteration 2:  Log likelihood =   -5.41027  
#> Iteration 3:  Log likelihood =   -5.41027  
#> 
#> Poisson regression                                
#> >       Number of obs                             
#> >                     =      2
#>                                                   
#> >       LR chi2(1)                                
#> >                     =   7.59
#>                                                   
#> >       Prob > chi2                               
#> >                     = 0.0059
#> Log likelihood = -5.41027                         
#> >       Pseudo R2                                 
#> >                     = 0.4123
#> 
#> --------------------------------------------------
#> > ----------------------------
#>       deaths |        IRR   Std. err.      z    P>
#> > |z|                                             
#> >         [95% con                                
#> >                 f. interval]
#> -------------+------------------------------------
#> > ----------------------------
#>       smokes |   2.138812   .6520701     2.49   0.
#> > 013                                             
#> >         1.176691                                
#> >                     3.887609
#>        _cons |   .0011243   .0003246   -23.52   0.
#> > 000                                             
#> >         .0006385                                
#> >                     .0019798
#>   ln(pyears) |          1  (exposure)
#> --------------------------------------------------
#> > ----------------------------
#> Note: _cons estimates baseline incidence rate.
#> 
#> Iteration 0:  Log likelihood = -6.2456963  
#> Iteration 1:  Log likelihood = -6.1713863  
#> Iteration 2:  Log likelihood =  -6.171298  
#> Iteration 3:  Log likelihood =  -6.171298  
#> 
#> Poisson regression                                
#> >       Number of obs                             
#> >                     =      2
#>                                                   
#> >       LR chi2(1)                                
#> >                     =   4.01
#>                                                   
#> >       Prob > chi2                               
#> >                     = 0.0453
#> Log likelihood = -6.171298                        
#> >       Pseudo R2                                 
#> >                     = 0.2450
#> 
#> --------------------------------------------------
#> > ----------------------------
#>       deaths |        IRR   Std. err.      z    P>
#> > |z|                                             
#> >         [95% con                                
#> >                 f. interval]
#> -------------+------------------------------------
#> > ----------------------------
#>       smokes |    1.46824    .295728     1.91   0.
#> > 057                                             
#> >         .9893522                                
#> >                      2.17893
#>        _cons |   .0049037   .0009267   -28.14   0.
#> > 000                                             
#> >         .0033858                                
#> >                     .0071021
#>   ln(pyears) |          1  (exposure)
#> --------------------------------------------------
#> > ----------------------------
#> Note: _cons estimates baseline incidence rate.
#> 
#> Iteration 0:  Log likelihood = -6.1640322  
#> Iteration 1:  Log likelihood = -6.1203079  
#> Iteration 2:  Log likelihood = -6.1202768  
#> Iteration 3:  Log likelihood = -6.1202768  
#> 
#> Poisson regression                                
#> >       Number of obs                             
#> >                     =      2
#>                                                   
#> >       LR chi2(1)                                
#> >                     =   2.43
#>                                                   
#> >       Prob > chi2                               
#> >                     = 0.1189
#> Log likelihood = -6.1202768                       
#> >       Pseudo R2                                 
#> >                     = 0.1658
#> 
#> --------------------------------------------------
#> > ----------------------------
#>       deaths |        IRR   Std. err.      z    P>
#> > |z|                                             
#> >         [95% con                                
#> >                 f. interval]
#> -------------+------------------------------------
#> > ----------------------------
#>       smokes |    1.35606   .2748845     1.50   0.
#> > 133                                             
#> >         .9114509                                
#> >                     2.017551
#>        _cons |   .0108317    .002047   -23.95   0.
#> > 000                                             
#> >         .0074789                                
#> >                     .0156877
#>   ln(pyears) |          1  (exposure)
#> --------------------------------------------------
#> > ----------------------------
#> Note: _cons estimates baseline incidence rate.

This example demonstrates how CI-functions can reveal patterns across subgroups—in this case, showing how the smoking-mortality relationship varies by age.

5.3 Example 3: Crude vs Adjusted Estimates

Comparing crude and pooled odds ratios from Mann et al. (1976):

* Case-control analysis
cci 10 36 5 40, woolf
cci 18 78 7 86, woolf

* Get standard errors
getregstats 2.835165, ucl(7.151794) mod(or)
getregstats 2.222222, ucl(7.118025) mod(or)

* Compare crude vs pooled estimates
cifunction 2.222222 2.835165, se(1.319891 1.33843) eform ///
    fig(xscale(log) xlabel(.2 .5 1 2 5 10 20) ///
    legend(label(1 Crude) label(2 Pooled)) ///
    xtitle("Odds Ratio (Log Scale)"))
#> Can not set Stata directory, try using -statapath(
#> > )- option
#> r(601);
#> 
#> 
#> 
#>                                                   
#> >        Proportion
#>                  |   Exposed   Unexposed  |      T
#> > otal      exposed
#> -----------------+------------------------+-------
#> > -----------------
#>            Cases |        10          36  |       
#> >   46       0.2174
#>         Controls |         5          40  |       
#> >   45       0.1111
#> -----------------+------------------------+-------
#> > -----------------
#>            Total |        15          76  |       
#> >   91       0.1648
#>                  |                        |
#>                  |      Point estimate    |    [95
#> > % conf. interval]
#>                  |------------------------+-------
#> > -----------------
#>       Odds ratio |         2.222222       |      .
#> > 69377    7.118025 (Woolf)
#>  Attr. frac. ex. |              .55       |      -
#> > .4414    .8595116 (Woolf)
#>  Attr. frac. pop |         .1195652       |
#>                  +--------------------------------
#> > -----------------
#>                                chi2(1) =     1.87 
#> >  Pr>chi2 = 0.1719
#> 
#> 
#>                                                   
#> >        Proportion
#>                  |   Exposed   Unexposed  |      T
#> > otal      exposed
#> -----------------+------------------------+-------
#> > -----------------
#>            Cases |        18          78  |       
#> >   96       0.1875
#>         Controls |         7          86  |       
#> >   93       0.0753
#> -----------------+------------------------+-------
#> > -----------------
#>            Total |        25         164  |       
#> >  189       0.1323
#>                  |                        |
#>                  |      Point estimate    |    [95
#> > % conf. interval]
#>                  |------------------------+-------
#> > -----------------
#>       Odds ratio |         2.835165       |    1.1
#> > 23936    7.151794 (Woolf)
#>  Attr. frac. ex. |         .6472868       |    .11
#> > 02698    .8601749 (Woolf)
#>  Attr. frac. pop |         .1213663       |
#>                  +--------------------------------
#> > -----------------
#>                                chi2(1) =     5.18 
#> >  Pr>chi2 = 0.0228
#> 
#> 
#> 
#> --------------------------------------------------
#> > ----------------------------
#>              | Odds Ratio   Std. Err.      z    P>
#> > |z|                                             
#> >         [95% Conf. Interval]
#> -------------+------------------------------------
#> > ----------------------------
#>    Estimates |   2.835165   1.338429     2.21   0.
#> > 027                                             
#> >         1.123936                                
#> >                     7.151794
#> --------------------------------------------------
#> > ----------------------------
#> 
#> 
#> 
#> --------------------------------------------------
#> > ----------------------------
#>              | Odds Ratio   Std. Err.      z    P>
#> > |z|                                             
#> >         [95% Conf. Interval]
#> -------------+------------------------------------
#> > ----------------------------
#>    Estimates |   2.222222   1.319891     1.34   0.
#> > 179                                             
#> >         .6937698                                
#> >                     7.118025
#> --------------------------------------------------
#> > ----------------------------

5.4 Example 4: Multi-Study Comparison

Comparing results across four geographic regions (Gufferman et al. 1984):

* Get standard errors from confidence limits
getregstats 0.7, l(.2) mod(rr)
getregstats 1.2, l(.8) mod(rr)
getregstats 1.3, l(.5) mod(rr)
getregstats 3.6, l(1.3) mod(rr)

* Plot all studies
cifunction .7 1.2 1.3 3.6, ///
    se(.4474236 .2482485 .6337692 1.870876) eform ///
    fig(xscale(log) xlabel(.05 .1 .2 .5 1 2 5 10 30) ///
    legend(label(1 "Finland") label(2 "NO/LA") ///
           label(3 "Denmark") label(4 "Upstate NY")) ///
    xtitle("Relative Risk (Log Scale)"))
#> Can not set Stata directory, try using -statapath(
#> > )- option
#> r(601);
#> 
#> 
#> 
#> 
#> --------------------------------------------------
#> > ----------------------------
#>              | Risk Ratio   Std. Err.      z    P>
#> > |z|                                             
#> >         [95% Conf. Interval]
#> -------------+------------------------------------
#> > ----------------------------
#>    Estimates |         .7   .4474236    -0.56   0.
#> > 577                                             
#> >               .2                                
#> >                         2.45
#> --------------------------------------------------
#> > ----------------------------
#> 
#> 
#> 
#> --------------------------------------------------
#> > ----------------------------
#>              | Risk Ratio   Std. Err.      z    P>
#> > |z|                                             
#> >         [95% Conf. Interval]
#> -------------+------------------------------------
#> > ----------------------------
#>    Estimates |        1.2   .2482485     0.88   0.
#> > 378                                             
#> >               .8                                
#> >                          1.8
#> --------------------------------------------------
#> > ----------------------------
#> 
#> 
#> 
#> --------------------------------------------------
#> > ----------------------------
#>              | Risk Ratio   Std. Err.      z    P>
#> > |z|                                             
#> >         [95% Conf. Interval]
#> -------------+------------------------------------
#> > ----------------------------
#>    Estimates |        1.3   .6337692     0.54   0.
#> > 590                                             
#> >               .5                                
#> >                         3.38
#> --------------------------------------------------
#> > ----------------------------
#> 
#> 
#> 
#> --------------------------------------------------
#> > ----------------------------
#>              | Risk Ratio   Std. Err.      z    P>
#> > |z|                                             
#> >         [95% Conf. Interval]
#> -------------+------------------------------------
#> > ----------------------------
#>    Estimates |        3.6   1.870876     2.46   0.
#> > 014                                             
#> >              1.3                                
#> >                     9.969231
#> --------------------------------------------------
#> > ----------------------------

This visualization makes it immediately apparent which studies had greater precision and how their point estimates compare.

5.5 Example 5: Meta-Analysis Context

From Rothman et al. (2008), Figure 10.5:

* Get standard errors
getregstats 0.87, l(0.70) model(or)

* Compare individual study vs meta-analysis
cifunction 0.87 0.88, se(.0965065 .0658232) eform ///
    fig(xlab(.5(.1)1.3) xtitle("Odds Ratio") ///
    legend(label(1 "Eisenberger et al (1998)") ///
           label(2 "Summary of 10 studies") ///
           ring(0) position(11))) ///
    sav(figdata, replace)
#> Can not set Stata directory, try using -statapath(
#> > )- option
#> r(601);
#> 
#> 
#> 
#> 
#> --------------------------------------------------
#> > ----------------------------
#>              | Odds Ratio   Std. Err.      z    P>
#> > |z|                                             
#> >         [95% Conf. Interval]
#> -------------+------------------------------------
#> > ----------------------------
#>    Estimates |        .87   .0965065    -1.26   0.
#> > 209                                             
#> >               .7                                
#> >                     1.081286
#> --------------------------------------------------
#> > ----------------------------

6 Output Variables

When using saving(), cifunction stores these variables:

Variables saved in output dataset
Variable Description
cilev Confidence levels (0 to 99.99)
plev P-values (0.0001 to 1.0)
sval S-values (Shannon information, see6)
lcl# Lower confidence limits for estimate #
ucl# Upper confidence limits for estimate #
NoteS-Values

S-values represent the information content against a null hypothesis, measured in bits. An S-value of 4.32 corresponds to p=0.05 (roughly 4.3 bits of information against the null). See6 for details.

7 Best Practices

  1. Always use log scale for ratio measures (OR, RR, HR, IRR)
  2. Label curves clearly when plotting multiple estimates
  3. Save output data for further analysis or custom plotting
  4. Consider degrees of freedom when using regression-based estimates
  5. Interpret curves holistically rather than focusing on single cutoffs

8 Theoretical Foundation

CI-functions rest on the principle that statistical evidence is continuous rather than dichotomous. As2 argues:

“The P-value function provides a convenient way to present the information in the data concerning the magnitude of an effect… [It] avoids the arbitrariness of any single significance level.”

The approach aligns with modern calls for moving beyond p-value thresholds7 by presenting the full gradient of statistical evidence.

9 Comparison with Other Approaches

Comparison of uncertainty visualization methods
Approach Information Provided Computational Complexity
Single CI One interval at one level Low
Multiple CIs Discrete intervals Low
CI-function Continuous curve of all intervals Low
Bootstrap distribution Empirical sampling distribution High
Likelihood profile Likelihood across parameter space Medium-High

10 Limitations

  • Assumes the statistical model is correctly specified
  • Does not account for unmeasured confounding or bias
  • Cannot compensate for poor study design or execution
  • Interpretation requires understanding of continuous evidence
WarningModel Assumptions

CI-functions, like all frequentist intervals, are valid only to the extent that the underlying statistical model and assumptions are appropriate for the data.

11 Citation

cifunction is free research software. Please cite it as:

Linden, A. (2019). CIFUNCTION: Stata module for computing and graphically displaying all possible confidence intervals around a point estimate. Statistical Software Components, Boston College Department of Economics.

12 Author

Ariel Linden President, Linden Consulting Group, LLC Email: alinden@lindenconsulting.org

13 See Also

  • getregstats (SSC): Helper for obtaining standard errors
  • niceloglabels (SSC): Improved logarithmic axis labels
  • concurve (R package): Similar functionality in R

14 References

1. Birnbaum A. (1961). “Confidence curves: An omnibus technique for estimation and testing statistical hypotheses.” Journal of the American Statistical Association. 56:246–249.
2. Poole C. (1987). “Beyond the confidence interval.” American Journal of Public Health. 77:195–199.
3. Miettinen OS. (1985). “Theoretical epidemiology: Principles of occurrence research in medicine.” New York: John Wiley & Sons.
4. Folks JL. (1981). “Ideas of statistics.” New York: John Wiley & Sons.
5. Xie M, Singh K. (2013). “Confidence Distribution, the Frequentist Distribution Estimator of a Parameter: A Review.” International Statistical Review. 81:3–39. doi: 10.1111/insr.12000.
6. Greenland S. (2019). “Valid p-values behave exactly as they should: Some misleading criticisms of p-values and their resolution with s-values.” The American Statistician. 73:106–114. doi: 10.1080/00031305.2018.1529625.
7. Wasserstein RL, Schirm AL, Lazar NA. (2019). “Moving to a world beyond "p < 0.05".” The American Statistician. 73:1–19. doi: 10.1080/00031305.2019.1583913.

Back to top

15 Appendix: Technical Details

15.1 Mathematical Formulation

For a normally distributed estimator \hat{\theta} with standard error SE(\hat{\theta}), the confidence limits at level (1-\alpha) are:

\hat{\theta} \pm z_{1-\alpha/2} \cdot SE(\hat{\theta})

The CI-function plots these limits across all values of \alpha \in [0, 1].

For t-distributed estimators (when degrees of freedom are specified):

\hat{\theta} \pm t_{1-\alpha/2, df} \cdot SE(\hat{\theta})

15.2 Exponentiated Coefficients

When eform is specified, computations occur on the log scale:

  1. Transform: \log(\hat{\theta}) with SE(\log(\hat{\theta}))
  2. Compute CI limits on log scale
  3. Back-transform: \exp(limits)

This ensures symmetric intervals on the log scale and proper geometric interpretation.


Last updated: 2026-05-26 Source code: Available on request License: Free for academic and non-commercial use

Citation

For attribution, please cite this work as:
1. Rafi Z, R Z. (2024). ‘Computing Confidence Interval Functions with cifunction’. Less Likely. https://lesslikely.com/statistics/cifunction.

Comments

Comments are loaded on demand so they don’t slow down the initial page render.