Computing Confidence Interval Functions with cifunction
A Stata Package for Visualizing Statistical Uncertainty
The cifunction package for Stata computes and plots all possible confidence intervals around a point estimate, which gives us what is known as a confidence interval function (also called a confidence curve, P-value function, or consonance interval). Here, we go through how to use it, since the curve tells us more than a single interval at one level by showing the full range of values that are compatible with the data at every confidence level.
confidence interval function, confidence curve, p-value function, consonance interval, Sullivan and Foster, Stata statistical software, statistical visualization, uncertainty quantification
1 Overview
Most of the time, we only report a confidence interval at a single level (typically 95%). However, that one interval throws away a fair amount of information about the data, since it invites us to sort values into those inside the interval and those outside of it. The confidence interval function (CI-function) gives us a more complete picture by displaying all possible confidence intervals at once. In this post, I’d like to go through cifunction, a Stata package written by Ariel Linden that computes and plots these functions.
2 Installation
Let’s start by installing 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
| Argument | Description |
|---|---|
#b |
Point estimate (coefficient or exponentiated value like OR, HR, IRR) |
se(#) |
Standard error of the estimate |
3.2 Optional Arguments
| 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
So what are we looking at when we plot one of these? A CI-function shows the relationship between confidence levels and their corresponding confidence intervals, and there are a few features that we can read off the curve:
- Peak of the curve: this is where the point estimate sits
- Concentration around the peak: this reflects the precision of the estimate
- Narrow curve: high precision (usually a large sample size)
- Broad curve: low precision (usually a small sample size)
4.1 Advantages Over Single-Level CIs
- Complete information: we can see how compatible every value is with the data
- Precision visualization: the width of the curve directly shows how precise the estimate is
- Multiple comparisons: we can see whether the data provide any reassurance about null effects
- Graded interpretation: it moves us away from binary “significant/non-significant” thinking
Values toward the peak are more compatible with the observed data (assuming that the statistical model is correct). Thus, the curve shows us that statistical evidence changes gradually, and it does not suggest any particular cutoff.
5 Practical Examples
5.1 Example 1: Basic Risk Ratio
First, we’ll reproduce 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)"))
## | Risk Ratio Std. Err. z P>|z| [95% Conf. Inte
## > rval]
## -------------+-----------------------------------------------------------
## > -----
## Estimates | 2 .707306 -1.96 0.050 1
## > 4
## -------------------------------------------------------------------------
## > -----5.2 Example 2: Age-Stratified Rate Ratios
Next, we’ll use the 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)"))
## (Doll and Hill (1966))
##
##
## 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% conf. inte
## > rval]
## -------------+-----------------------------------------------------------
## > -----
## smokes | 5.736638 4.181258 2.40 0.017 1.374811 23.
## > 93712
## _cons | .0001064 .0000753 -12.94 0.000 .0000266 .00
## > 04256
## 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% conf. inte
## > rval]
## -------------+-----------------------------------------------------------
## > -----
## smokes | 2.138812 .6520701 2.49 0.013 1.176691 3.8
## > 87609
## _cons | .0011243 .0003246 -23.52 0.000 .0006385 .00
## > 19798
## 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% conf. inte
## > rval]
## -------------+-----------------------------------------------------------
## > -----
## smokes | 1.46824 .295728 1.91 0.057 .9893522 2.
## > 17893
## _cons | .0049037 .0009267 -28.14 0.000 .0033858 .00
## > 71021
## 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% conf. inte
## > rval]
## -------------+-----------------------------------------------------------
## > -----
## smokes | 1.35606 .2748845 1.50 0.133 .9114509 2.0
## > 17551
## _cons | .0108317 .002047 -23.95 0.000 .0074789 .01
## > 56877
## ln(pyears) | 1 (exposure)
## -------------------------------------------------------------------------
## > -----
## Note: _cons estimates baseline incidence rate.Here, the CI-functions let us see patterns across subgroups (in this case, how the smoking-mortality relationship varies by age).
5.3 Example 3: Crude vs Adjusted Estimates
Now, let’s compare the 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)"))
## Proportion
## | Exposed Unexposed | Total 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 (Wool
## > f)
## Attr. frac. ex. | .55 | -.4414 .8595116 (Wool
## > f)
## Attr. frac. pop | .1195652 |
## +-------------------------------------------------
## chi2(1) = 1.87 Pr>chi2 = 0.1719
##
##
## Proportion
## | Exposed Unexposed | Total 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.123936 7.151794 (Wool
## > f)
## Attr. frac. ex. | .6472868 | .1102698 .8601749 (Wool
## > f)
## Attr. frac. pop | .1213663 |
## +-------------------------------------------------
## chi2(1) = 5.18 Pr>chi2 = 0.0228
##
##
##
## -------------------------------------------------------------------------
## > -----
## | Odds Ratio Std. Err. z P>|z| [95% Conf. Inte
## > rval]
## -------------+-----------------------------------------------------------
## > -----
## Estimates | 2.835165 1.338429 2.21 0.027 1.123936 7.1
## > 51794
## -------------------------------------------------------------------------
## > -----
##
##
##
## -------------------------------------------------------------------------
## > -----
## | Odds Ratio Std. Err. z P>|z| [95% Conf. Inte
## > rval]
## -------------+-----------------------------------------------------------
## > -----
## Estimates | 2.222222 1.319891 1.34 0.179 .6937698 7.1
## > 18025
## -------------------------------------------------------------------------
## > -----5.4 Example 4: Multi-Study Comparison
We can also compare 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)"))
## | Risk Ratio Std. Err. z P>|z| [95% Conf. Inte
## > rval]
## -------------+-----------------------------------------------------------
## > -----
## Estimates | .7 .4474236 -0.56 0.577 .2
## > 2.45
## -------------------------------------------------------------------------
## > -----
##
##
##
## -------------------------------------------------------------------------
## > -----
## | Risk Ratio Std. Err. z P>|z| [95% Conf. Inte
## > rval]
## -------------+-----------------------------------------------------------
## > -----
## Estimates | 1.2 .2482485 0.88 0.378 .8
## > 1.8
## -------------------------------------------------------------------------
## > -----
##
##
##
## -------------------------------------------------------------------------
## > -----
## | Risk Ratio Std. Err. z P>|z| [95% Conf. Inte
## > rval]
## -------------+-----------------------------------------------------------
## > -----
## Estimates | 1.3 .6337692 0.54 0.590 .5
## > 3.38
## -------------------------------------------------------------------------
## > -----
##
##
##
## -------------------------------------------------------------------------
## > -----
## | Risk Ratio Std. Err. z P>|z| [95% Conf. Inte
## > rval]
## -------------+-----------------------------------------------------------
## > -----
## Estimates | 3.6 1.870876 2.46 0.014 1.3 9.9
## > 69231
## -------------------------------------------------------------------------
## > -----As we can see from the plot, it becomes fairly easy to tell which studies had greater precision and how their point estimates compare.
5.5 Example 5: Meta-Analysis Context
Lastly, here’s an example taken 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)
## | Odds Ratio Std. Err. z P>|z| [95% Conf. Inte
## > rval]
## -------------+-----------------------------------------------------------
## > -----
## Estimates | .87 .0965065 -1.26 0.209 .7 1.0
## > 81286
## -------------------------------------------------------------------------
## > -----6 Output Variables
When we use saving(), cifunction stores the following variables:
| 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 # |
S-values measure the information against a null hypothesis (or any other test hypothesis) in bits. An S-value of 4.32 corresponds to p=0.05 (roughly 4.3 bits of information against the null). See6 for the details.
7 Best Practices
- Use the log scale for ratio measures (OR, RR, HR, IRR)
- Label the curves clearly when plotting more than one estimate
- Save the output data so that we can analyze it further or build custom plots
- Consider the degrees of freedom when the estimates come from a regression
- Look at the whole curve instead of focusing on any single cutoff
8 Theoretical Foundation
CI-functions rest on the idea that statistical evidence is continuous, and that we lose something when we dichotomize it. 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.”
This also seems to fit with more recent calls to move beyond P-value thresholds7, since the curve presents the full gradient of statistical evidence.
9 Comparison with Other Approaches
| 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
However, there are a few things that a CI-function cannot do for us:
- It assumes that the statistical model is correctly specified
- It does not account for unmeasured confounding or bias
- It cannot compensate for poor study design or execution
- Interpreting it requires some understanding of continuous evidence
CI-functions, like all frequentist intervals, are only valid to the extent that the underlying statistical model and its assumptions are appropriate for the data.
11 Citation
cifunction is free research software. If you use it, 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.
13 See Also
getregstats(SSC): Helper for obtaining standard errorsniceloglabels(SSC): Improved logarithmic axis labelsconcurve(R package): Similar functionality in R
14 References
Abstract
R\'esum\'e Il est courant, en inf\'erence fr\'equentielle, d'utiliser un point unique (une estimation ponctuelle) ou un intervalle (intervalle de confiance) dans le but d'estimer un param\`etre d'int\'er\^t. Une question tr\`es simple se pose: peut-on \'egalement utiliser, dans le m\^eme but, et dans la m\^eme optique fr\'equentielle, \`a la facon dont les Bay\'esiens utilisent une loi a posteriori, une distribution de probabilit\'e? La r\'eponse est affirmative, et les distributions de confiance apparaissent comme un choix naturel dans ce contexte. Le concept de distribution de confiance a une longue histoire, longtemps associ\'ee, \`a tort, aux th\'eories d'inf\'erence fiducielle, ce qui a compromis son d\'eveloppement dans l'optique fr\'equentielle. Les distributions de confiance ont r\'ecemment attir\'e un regain d'int\'er\^et, et plusieurs r\'esultats ont mis en \'evidence leur potentiel consid\'erable en tant qu'outil inf\'erentiel. Cet article pr\'esente une d\'efinition moderne du concept, et examine les ses \'evolutions r\'ecentes. Il aborde les m\'ethodes d'inf\'erence, les probl\`emes d'optimalit\'e, et les applications …
Abstract
The present note explores sources of misplaced criticisms of P-values, such as conflicting definitions of “significance levels” and “P-values” in authoritative sources, and the consequent misinterpretation of P-values as error probabilities. It then discusses several properties of P-values that have been presented as fatal flaws: That P-values exhibit extreme variation across samples (and thus are “unreliable”), confound effect size with sample size, are sensitive to sample size, and depend on investigator sampling intentions. These properties are often criticized from a likelihood or Bayesian framework, yet they are exactly the properties P-values should exhibit when they are constructed and interpreted correctly within their originating framework. Other common criticisms are that P-values force users to focus on irrelevant hypotheses and overstate evidence against those hypotheses. These problems are not however properties of P-values but are faults of researchers who focus on null hypotheses and overstate evidence based on misperceptions that p = 0.05 represents enough evidence to reject hypotheses …
Abstract
EDITORIAL: The editorial was written by the three editors acting as individuals and reflects their scientific views not an endorsed position of the American Statistical Association.Some of you expl...
15 Appendix: Technical Details
15.1 Mathematical Formulation
For a normally distributed estimator with standard error , the confidence limits at level are:
The CI-function plots these limits across all values of .
For t-distributed estimators (when degrees of freedom are specified):
15.2 Exponentiated Coefficients
When eform is specified, computations occur on the log scale:
- Transform: with
- Compute CI limits on log scale
- Back-transform:
Thus, the intervals are symmetric on the log scale and keep their proper geometric interpretation.
Last updated: 2026-10-01 Source code: Available on request License: Free for academic and non-commercial use
Citation
@article{rafi2024,
author = {Rafi, Zad and R, Zad},
title = {Computing {Confidence} {Interval} {Functions} with
Cifunction},
journal = {Less Likely},
date = {2024-03-23},
url = {https://lesslikely.com/statistics/cifunction},
langid = {en-US},
abstract = {The cifunction package for Stata computes and plots all
possible confidence intervals around a point estimate, which gives
us what is known as a confidence interval function (also called a
confidence curve, P-value function, or consonance interval). Here,
we go through how to use it, since the curve tells us more than a
single interval at one level by showing the full range of values
that are compatible with the data at every confidence level.}
}
Linked from (6)
- All Posts
- Blog § All Posts
- Constructing Likelihood Functions in R, Stata, Python, Julia, MATLAB, and SQL § Validation status SSC module; conventions per the cifunction guide
- How to Be a Good Collaborator to a Statistician and a Data Engineer § What Statisticians and Data Engineers Owe Back …of what the analysis produced, since it is continuous evidence. This is the case for S-values and for the full compatibility/consonance function over a single dichotomized interval.
- Site Map § Search & Navigation
- Statistics § Latest Statistics Articles
Comments