<div id="top"></div>
<h1 align="center" >
Forestplot
</h1>
<p align="center">
<a href="https://pypi.org/project/forestplot">
<img alt="PyPI - Python Version" src="https://img.shields.io/pypi/pyversions/forestplot?label=Python&logo=python&logoColor=white">
</a><br>
<b>Easy API for forest plots.</b><br>
A Python package to make publication-ready but customizable forest plots.
</p>
<p align="center"><img width="100%" src="https://raw.githubusercontent.com/LSYS/forestplot/main/docs/images/main.png"></p>
-----------------------------------------------------------
This package makes publication-ready forest plots easy to make out-of-the-box. Users provide a `dataframe` (e.g. from a spreadsheet) where rows correspond to a variable/study with columns including estimates, variable labels, and lower and upper confidence interval limits.
Additional options allow easy addition of columns in the `dataframe` as annotations in the plot.
<!---------------------- Project shields ---------------------->
| | |
| --- | --- |
| Release | [![PyPI](https://img.shields.io/pypi/v/forestplot?color=blue&label=PyPI&logo=pypi&logoColor=white)](https://pypi.org/project/forestplot/) [![Conda (channel only)](https://img.shields.io/conda/vn/conda-forge/forestplot?logo=conda-forge&logoColor=white)](https://anaconda.org/conda-forge/forestplot) [![GitHub release (latest by date)](https://img.shields.io/github/v/release/lsys/forestplot?color=blue&label=Latest%20release)](https://github.com/LSYS/forestplot/releases) |
| Status | [![CI](https://github.com/LSYS/forestplot/actions/workflows/CI.yml/badge.svg)](https://github.com/LSYS/forestplot/actions/workflows/CI.yml) [![Notebooks](https://github.com/LSYS/forestplot/actions/workflows/nb.yml/badge.svg)](https://github.com/LSYS/forestplot/actions/workflows/nb.yml) |
| Coverage | [![Codecov](https://img.shields.io/codecov/c/github/lsys/forestplot?logo=codecov&logoColor=white&label=codecov)](https://app.codecov.io/gh/LSYS/forestplot) |
| Python | [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/forestplot?label=Python%203.6%2B&logo=python&logoColor=white)](https://pypi.org/project/forestplot/) |
| Docs | [![Read the Docs (version)](https://img.shields.io/readthedocs/forestplot/stable?label=docs&logo=readthedocs&logoColor=white)](https://forestplot.readthedocs.io/en/latest/?badge=latest) [![DocLinks](https://github.com/LSYS/forestplot/actions/workflows/links.yml/badge.svg)](https://github.com/LSYS/forestplot/actions/workflows/links.yml)|
| Meta | [![GitHub](https://img.shields.io/github/license/lsys/forestplot?color=purple&label=License)](https://choosealicense.com/licenses/mit/) [![Imports: isort](https://img.shields.io/badge/%20imports-isort-%231674b1?style=flat&labelColor=ef8336)](https://pycqa.github.io/isort/) [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) [![types - Mypy](https://img.shields.io/badge/types-Mypy-blue.svg)](https://github.com/python/mypy) [![DOI](https://zenodo.org/badge/510013191.svg)](https://zenodo.org/badge/latestdoi/510013191) |
| Binder| [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/lsys/forestplot/main?labpath=examples%2Freadme-examples.ipynb) |
<!---------------------- TABLE OF CONTENT ---------------------->
# Table of Contents[![](https://raw.githubusercontent.com/LSYS/forestplot/main/docs/images/pin.svg)](#table-of-contents)
<details open><summary><b>show/hide</b></summary><p>
> - [Installation](#installation)
> - [Quick Start](#quick-start)
> - [Some Examples with Customizations](#some-examples-with-customizations)
> - [Gallery and API Options](#gallery-and-api-options)
> - [Multi-models](#multi-models)
> - [Known Issues](#known-issues)
> - [Background and Additional Resources](#background-and-additional-resources)
> - [Contributing](#contributing)
</p></details><p></p>
<!------------------------- INSTALLATION ------------------------->
## Installation[![](https://raw.githubusercontent.com/LSYS/forestplot/main/docs/images/pin.svg)](#installation)
Install from PyPI<br>
[![PyPI](https://img.shields.io/pypi/v/forestplot?color=blue&label=PyPI&logo=pypi&logoColor=white)](https://pypi.org/project/forestplot/)
```bash
pip install forestplot
```
Install from conda-forge<br>
[![Conda (channel only)](https://img.shields.io/conda/vn/conda-forge/forestplot?logo=conda-forge&logoColor=white)](https://anaconda.org/conda-forge/forestplot)
```bash
conda install forestplot
```
Install from source<br>
[![GitHub release (latest by date)](https://img.shields.io/github/v/release/lsys/forestplot?color=blue&label=Latest%20release)](https://github.com/LSYS/forestplot/releases)<br>
```bash
git clone https://github.com/LSYS/forestplot.git
cd forestplot
pip install .
```
Developer installation<br>
```bash
git clone https://github.com/LSYS/forestplot.git
cd forestplot
pip install -r requirements_dev.txt
make lint
make test
```
<p align="right">(<a href="#top">back to top</a>)</p>
<!------------------------- QUICK START ------------------------->
## Quick Start[![](https://raw.githubusercontent.com/LSYS/forestplot/main/docs/images/pin.svg)](#quick-start)
```python
import forestplot as fp
df = fp.load_data("sleep") # companion example data
df.head(3)
```
| | var | r | moerror | label | group | ll | hl | n | power | p-val |
|---:|:---------|-----------:|----------:|:--------------------------|:--------------|------:|------:|----:|---------:|----------:|
| 0 | age | 0.0903729 | 0.0696271 | in years | age | 0.02 | 0.16 | 706 | 0.671578 | 0.0163089 |
| 1 | black | -0.0270573 | 0.0770573 | =1 if black | other factors | -0.1 | 0.05 | 706 | 0.110805 | 0.472889 |
| 2 | clerical | 0.0480811 | 0.0719189 | =1 if clerical worker | occupation | -0.03 | 0.12 | 706 | 0.247768 | 0.201948 |
(* This is a toy example of how certain factors correlate with the amount of sleep one gets. See the [notebook that generates the data](https://nbviewer.org/github/LSYS/forestplot/blob/main/examples/get-sleep.ipynb).)
<details><summary><i>The example input dataframe above have 4 key columns</i></summary>
| Column | Description | Required |
|:----------|:------------------------------------------------|:----------|
| `var` | Variable label | ✓ |
| `r` | Correlation coefficients (estimates to plot) | ✓ |
| `label` | Variable labels | ✓ |
| `group` | Variable grouping labels | |
| `ll` | Conf. int. *lower limits* | |
| `hl` | Containing the conf. int. *higher limits* | |
| `n` | Sample size | |
| `power` | Statistical power | |
| `p-val` | P-value | |
(See [Gallery and API Options](#gallery-and-api-options) for more details on required and optional arguments.)
</details>
Make the forest plot
```python
fp.forestplot(df, # the dataframe with results data
estimate="r", # col containing estimated effect size
ll="ll", hl="hl", # columns containing conf. int. lower and higher limits
varlabel="label", # column containing variable label
ylabel="Confidence interval", # y-label title
xlabel="Pearson correlation", # x-label title
)
```
<p align="left"><img width="75%" src="https://raw.githubusercontent.com/LSYS/forestplot/main/docs/images/vanilla.png"></p>
Save the plot
```python
plt.savefig("plot.png", bbox_inches="tight")
```
<p align="right">(<a href="#top">back to top</a>)</p>
<!------------------ EXAMPLES of CUSTOMIZATIONS ------------------>
## Some Examples With Customizations[![](https://raw.githubusercontent.com/LSYS/forestplot/main/docs/images/pin.svg)](#some-examples-with-customizations)
1. Add variable groupings, add group order, and sort by estimate size.
```python
fp.forestplot(df, # the dataframe with results data
estimate="r", # col containing estimated effect size
ll="ll", hl="hl", # columns containing conf. int. lower and higher limits
varlabel="label", # column containing variable label
capitalize="capitalize", # Capitalize labels
groupvar="group", # Add variable groupings
# group ordering
group_order=["labor factors", "occupation", "age", "health factors",
"family factors", "area of residence", "other factors"],
sort=True # sort in ascending order (sorts within group if group is specified)
)
```
<p align="left"><img width="75%" src="https://raw.githubusercontent.com/LSYS/forestplot/main/docs/images/group-grouporder-sort.png"></p>
2. Add p-values on the right and color alternate rows gray
```python
fp.forestplot(df, # the dataframe with results data
estimate="r", # col containing estimated effect size
ll="ll", hl="hl", # columns containing conf. int. lower and higher limits
varlabel="label", # column containing variable label
capitalize="capitalize", # Capitalize labels
groupvar="group", # Add variable groupings
# group ordering
group_order=["labor factors", "occupation", "age", "health factors",
"family factors", "area of residence", "other factors"],
sort=True, # sort in ascending order (sorts within group if group is specified)
pval="p-val", # Column of p-value to be reported on right
color_alt_rows=True, # Gray alternate rows
ylabel="Est.(95% Conf. Int.)", # ylabel to print
**{"ylabel1_size": 11} # control size of printed ylabel
)
```
<p align="left"><img width="80%" src="https://raw.githubusercontent.com/LSYS/forestplot/main/docs/images/group-grouporder-pvalue-sort-colorrows.png"></p>
3. Customize annotations and make it a table
```python
fp.forestplot(df, # the dataframe with results data
estimate="r", # col containing estimated effect size
ll="ll", hl="hl", # lower & higher limits of conf. int.
varlabel="label", # column containing the varlabels to be printed on far left
capitalize="capitalize", # Capitalize labels
pval="p-val", # column containing p-values to be formatted
annote=["n", "power", "est_ci"], # columns to report on left of plot
annoteheaders=["N", "Power", "Est. (95% Conf. Int.)"], # ^corresponding headers
rightannote=["formatted_pval", "group"], # columns to report on right of plot
right_annoteheaders=["P-value", "Variable group"], # ^corresponding headers
xlabel="Pearson correlation coefficient", # x-label title
table=True, # Format as a table
)
```
<p align="left"><img width="85%" src="https://raw.githubusercontent.com/LSYS/forestplot/main/docs/images/leftannote-rightannote-table.png"></p>
4. Strip down all bells and whistle
```python
fp.forestplot(df, # the dataframe with results data
estimate="r", # col containing estimated effect size
ll="ll", hl="hl", # lower & higher limits of conf. int.
varlabel="label", # column containing the varlabels to be printed on far left
capitalize="capitalize", # Capitalize labels
ci_report=False, # Turn off conf. int. reporting
flush=False, # Turn off left-flush of text
**{'fontfamily': 'sans-serif'} # revert to sans-serif
)
```
<p align="left"><img width="50%" src="https://raw.githubusercontent.com/LSYS/forestplot/main/docs/images/vcoefplot.png"></p>
5. Example with more customizations
```python
fp.forestplot(df, # the dataframe with results data
estimate="r", # col containing estimated effect size
ll="ll", hl="hl", # lower & higher limits of conf. int.
varlabel="label", # column containing the varlabels to be printed on far left
capitalize="capitalize", # Capitalize labels
pval="p-val", # column containing p-values to be formatted
annote=["n", "power", "est_ci"], # columns to report on left of plot
annoteheaders=["N", "Power", "Est. (95% Conf. Int.)"], # ^corresponding headers
rightannote=["formatted_pval", "group"], # columns to report on right of plot
right_annoteheaders=["P-value", "Variable group"], # ^corresponding headers
groupvar="group", # column containing group labels
group_order=["labor factors", "occupation", "age", "health factors",
"family factors", "area of residence", "other factors"],
xlabel="Pearson correlation coefficient", # x-label title
xticks=[-.4,-.2,0, .2], # x-ticks to be printed
sort=True, # sort estimates in ascending order
table=True, # Format as a table
# Additional kwargs for customizations
**{"marker": "D", # set maker symbol as diamond
"markersize": 35, # adjust marker size
"xlinestyle": (0, (10, 5)), # long dash for x-reference line
"xlinecolor": "#808080", # gray color for x-reference line
"xtick_size": 12, # adjust x-ticker fontsize
}
)
```
<p align="left"><img width="100%" src="https://raw.githubusercontent.com/LSYS/forestplot/main/docs/images/main.png"></p>
<details><summary><i>Annotations arguments allowed include:</i></summary>
* `ci_range`: Confidence interval range (e.g. `(-0.39 to -0.25)`).
* `est_ci`: Estimate and CI (e.g. `-0.32(-0.39 to -0.25)`).
* `formatted_pval`: Formatted p-values (e.g. `0.01**`).
To confirm what processed `columns` are available as annotations, you can do:
```python
processed_df, ax = fp.forestplot(df,
... # other arguments here
return_df=True # return processed dataframe with processed columns
)
processed_df.head(3)
```
| | label | group | n | r | CI95% | p-val | BF10 | power | var | hl | ll | moerror | formatted_r | formatted_ll | formatted_hl | ci_range | est_ci | formatted_pval | formatted_n | formatted_power | formatted_est_ci | yticklabel | formatted_formatted_pval | formatted_group | yticklabel2 |
|---:|:---------------------|:--------------|----:|-----------:|:--------------|------------:|----------:|--------:|:-------|------:|------:|----------:|--------------:|---------------:|---------------:|:-----------------|:----------------------|:-----------------|--------------:|------------------:|:----------------------|:------------------------------------------------------------------|:---------------------------|:------------------|:-----------------------|
| 0 | Mins worked per week | Labor factors | 706 | -0.321384 | [-0.39 -0.25] | 1.99409e-18 | 1.961e+15 | 1 | totwrk | -0.25 | -0.39 | 0.0686165 | -0.32 | -0.39 | -0.25 | (-0.39 to -0.25) | -0.32(-0.39 to -0.25) | 0.0*** | 706 | 1 | -0.32(-0.39 to -0.25) | Mins worked per week 706 1.0 -0.32(-0.39 to -0.25) | 0.0*** | Labor factors | 0.0*** Labor factors |
| 1 | Years of schooling | Labor factors | 706 | -0.0950039 | [-0.17 -0.02] | 0.0115515 | 1.137 | 0.72 | educ | -0.02 | -0.17 | 0.0749961 | -0.1 | -0.17 | -0.02 | (-0.17 to -0.02) | -0.10(-0.17 to -0.02) | 0.01** | 706 | 0.72 | -0.10(-0.17 to -0.02) | Years of schooling 706 0.72 -0.10(-0.17 to -0.02) | 0.01** | Labor factors | 0.01** Labor factors |
</details>
<p align="right">(<a href="#top">back to top</a>)</p>
<!------------------- Multi-models ------------------->
## Multi-models[![](https://raw.githubusercontent.com/LSYS/forestplot/main/docs/images/pin.svg)](#multi-models)
For coefficient plots where each variable can have multiple estimates (each `model` has one).
```python
import forestplot as fp
df_mmodel = pd.read_csv("../examples/data/sleep-mmodel.csv").query(
"model=='all' | model=='young kids'"
)
df_mmodel.head(3)
```
| | var | coef | se | T | pval | r2 | adj_r2 | ll | hl | model | group | label |
|---:|:------|-----------:|---------:|----------:|---------:|---------:|-----------:|-----------:|--------:|:-----------|:--------------|:------------|
| 0 | age | 0.994889 | 1.96925 | 0.505213 | 0.613625 | 0.127289 | 0.103656 | -2.87382 | 4.8636 | all | age | in years |
| 3 | age | 22.634 | 15.4953 | 1.4607 | 0.149315 | 0.178147 | -0.0136188 | -8.36124 | 53.6293 | young kids | age | in years |
| 4 | black | -84.7966 | 82.1501 | -1.03222 | 0.302454 | 0.127289 | 0.103656 | -246.186 | 76.5925 | all | other factors | =1 if black |
```python
fp.mforestplot(
dataframe=df_mmodel,
estimate="coef",
ll="ll",
hl="hl",
varlabel="label",
capitalize="capitalize",
model_col="model",
color_alt_rows=True,
groupvar="group",
table=True,
rightannote=["var", "group"],
right_annoteheaders=["Source", "Group"],
xlabel="Coefficient (95% CI)",
modellabels=["Have young kids", "Full sample"],
xticks=[-1200, -600, 0, 600],
mcolor=["#CC6677", "#4477AA"],
# Additional kwargs for customizations
**{
"markersize": 30,
# override default vertical offset between models (0.0 to 1.0)
"offset": 0.35,
"xlinestyle": (0, (10, 5)), # long dash for x-reference line
"xlinecolor": ".8", # gray color for x-reference line
},
)
```
<p align="left"><img width="100%" src="https://raw.githubusercontent.com/LSYS/forestplot/mplot-dev/docs/images/multimodel.png"></p>
Please note: This module is still experimental. See [this jupyter notebook](https://nbviewer.org/github/LSYS/forestplot/blob/mplot-dev/examples/test-multmodel-sleep.ipynb) for more examples and tweaks.
<!------------------- GALLERY AND API OPTIONS ------------------->
## Gallery and API Options[![](https://raw.githubusercontent.com/LSYS/forestplot/main/docs/images/pin.svg)](#gallery-and-api-options)
[![Notebooks](https://github.com/LSYS/forestplot/actions/workflows/nb.yml/badge.svg)](https://github.com/LSYS/forestplot/actions/workflows/nb.yml)
Check out [this jupyter notebook](https://nbviewer.org/github/LSYS/forestplot/blob/main/examples/readme-examples.ipynb) for a gallery variations of forest plots possible out-of-the-box.
The table below shows the list of arguments users can pass in.
More fined-grained control for base plot options (eg font sizes, marker colors) can be inferred from the [example notebook gallery](https://nbviewer.org/github/LSYS/forestplot/blob/main/examples/readme-examples.ipynb).
| Option | Description | Required |
|:-------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------|:---|
| `dataframe` | Pandas dataframe where rows are variables (or studies for meta-analyses) and columns include estimated effect sizes, labels, and confidence intervals, etc. | ✓ |
| `estimate` | Name of column in `dataframe` containing the *estimates*. | ✓ |
| `varlabel` | Name of column in `dataframe` containing the *variable labels* (study labels if meta-analyses). | ✓ |
| `ll` | Name of column in `dataframe` containing the conf. int. *lower limits*. | |
| `hl` | Name of column in `dataframe` containing the conf. int. *higher limits*. | |
| `logscale` | If True, make the x-axis log scale. Default is False. | |
| `capitalize` | How to capitalize strings. Default is None. One of "capitalize", "title", "lower", "upper", "swapcase". | |
| `form_ci_report` | If True (default), report the estimates and confidence interval beside the variable labels. | |
| `ci_report` | If True (default), format the confidence interval as a string. | |
| `groupvar` | Name of column in `dataframe` containing the variable *grouping labels*. | |
| `group_order` | List of group labels indicating the order of groups to report in the plot. | |
| `annote` | List of columns to add as annotations on the left-hand side of the plot. | |
| `annoteheaders` | List of column headers for the left-hand side annotations. | |
| `rightannote` | List of columns to add as annotations on the right-hand side of the plot. | |
| `right_annoteheaders` | List of column headers for the right-hand side annotations. | |
| `pval` | Name of column in `dataframe` containing the p-values. | |
| `starpval` | If True (default), format p-values with stars indicating statistical significance. | |
| `sort` | If True, sort variables by `estimate` values in ascending order. | |
| `sortby` | Name of column to sort by. Default is `estimate`. | |
| `flush` | If True (default), left-flush variable labels and annotations. | |
| `decimal_precision` | Number of decimal places to print. (Default = 2) | |
| `figsize` | Tuple indicating core figure size. Default is (4, 8) | |
| `xticks` | List of xticklabels to print on x-axis. | |
| `ylabel` | Y-label title. | |
| `xlabel` | X-label title. | |
| `color_alt_rows` | If True, shade out alternating rows in gray. | |
| `preprocess` | If True (default), preprocess the `dataframe` before plotting. | |
| `return_df` | If True, returned the preprocessed `dataframe`. | |
<p align="right">(<a href="#top">back to top</a>)</p>
<!------------------------ KNOWN ISSUES ------------------------>
## Known Issues[![](https://raw.githubusercontent.com/LSYS/forestplot/main/docs/images/pin.svg)](#known-issues)
* Variable labels coinciding with group variables may lead to unexpected formatting issues in the graph.
* Left-flushing of annotations relies on the `monospace` font.
* Plot may give strange behavior for few rows of data (six rows or fewer. [see this issue](https://github.com/LSYS/forestplot/issues/52))
* Plot can get cluttered with too many variables/rows (~30 onwards)
* Not tested with PyCharm (#80) nor Google Colab (#110).
* Duplicated `varlabel` may lead to unexpected results (see #76, #81). `mplot` for grouped models could be useful for such cases (see #59, WIP).
<p align="right">(<a href="#top">back to top</a>)</p>
<!----------------- BACKGROUND AND ADDITIONAL RESOURCES ----------------->
## Background and Additional Resources[![](https://raw.githubusercontent.com/LSYS/forestplot/main/docs/images/pin.svg)](#background-and-additional-resources)
**More about forest plots**
[Forest plots](https://en.wikipedia.org/wiki/Forest_plot) have many aliases (h/t Chris Alexiuk). Other names include coefplots, coefficient plots, meta-analysis plots, dot-and-whisker plots, blobbograms, margins plots, regression plots, and ropeladder plots.
[Forest plots](https://en.wikipedia.org/wiki/Forest_plot) in the medical and health sciences literature are plots that report results from different studies as a meta-analysis. Markers are centered on the estimated effect and horizontal lines running through each marker depicts the confidence intervals.
The simplest version of a forest plot has two columns: one for the variables/studies, and the second for the estimated coefficients and confidence intervals.
This layout is similar to coefficient plots ([coefplots](http://repec.sowi.unibe.ch/stata/coefplot/getting-started.html)) and is thus useful for more than meta-analyses.
<details><summary><i>More resources about forest plots</i></summary><p>
* [[1]](https://doi.org/10.1038/s41433-021-01867-6) Chang, Y., Phillips, M.R., Guymer, R.H. et al. The 5 min meta-analysis: understanding how to read and interpret a forest plot. Eye 36, 673–675 (2022).
* [[2]](https://doi.org/10.1136/bmj.322.7300.1479) Lewis S, Clarke M. Forest plots: trying to see the wood and the trees BMJ 2001; 322 :1479
</p></details><p></p>
**More about this package**
The package is lightweight, built on `pandas`, `numpy`, and `matplotlib`.
It is slightly opinioniated in that the aesthetics of the plot inherits some of my sensibilities about what makes a nice figure.
You can however easily override most defaults for the look of the graph. This is possible via `**kwargs` in the `forestplot` API (see [Gallery and API options](#gallery-and-api-options)) and the `matplotlib` API.
**Planned enhancements** include forest plots where each row can have multiple coefficients (e.g. from multiple models).
<details><summary><i>Related packages</i></summary><p>
* [[1]](https://www.stata-journal.com/article.html?article=gr0059) [Stata] Jann, Ben (2014). Plotting regression coefficients and other estimates. The Stata Journal 14(4): 708-737.
* [[2]](https://www.statsmodels.org/devel/examples/notebooks/generated/metaanalysis1.html) [Python] Meta-Analysis in statsmodels
* [[3]](https://github.com/seafloor/forestplot) [Python] Matt Bracher-Smith's Forestplot
* [[4]](https://github.com/fsolt/dotwhisker) [R] Solt, Frederick and Hu, Yue (2021) dotwhisker: Dot-and-Whisker Plots of Regression Results
* [[5]](https://rpubs.com/mbounthavong/forest_plots_r) [R] Bounthavong, Mark (2021) Forest plots. RPubs by RStudio
</p></details><p></p>
<p align="right">(<a href="#top">back to top</a>)</p>
<!----------------------- CONTRIBUTING ----------------------->
## Contributing[![](https://raw.githubusercontent.com/LSYS/forestplot/main/docs/images/pin.svg)](#contributing)
Contributions are welcome, and they are greatly appreciated!
**Potential ways to contribute:**
* Raise issues/bugs/questions
* Write tests for missing coverage
* Add features (see [examples notebook](https://nbviewer.org/github/LSYS/forestplot/blob/main/examples/readme-examples.ipynb) for a survey of existing features)
* Add example datasets with companion graphs
* Add your graphs with companion code
**Issues**
Please submit bugs, questions, or issues you encounter to the [GitHub Issue Tracker](https://github.com/lsys/forestplot/issues).
For bugs, please provide a minimal reproducible example demonstrating the problem (it may help me troubleshoot if I have a version of your data).
**Pull Requests**
Please feel free to open an issue on the [Issue Tracker](https://github.com/lsys/forestplot/issues) if you'd like to discuss potential contributions via PRs.
<p align="right">(<a href="#top">back to top</a>)</p>
Raw data
{
"_id": null,
"home_page": "https://github.com/lsys/forestplot",
"name": "forestplot",
"maintainer": "Lucas Shen",
"docs_url": null,
"requires_python": null,
"maintainer_email": "lucas@lucasshen.com",
"keywords": "visualization, python, data-science, dataviz, pandas, matplotlib, mpl, forestplot, blobbogram",
"author": "Lucas Shen",
"author_email": "lucas@lucasshen.com",
"download_url": "https://files.pythonhosted.org/packages/a9/ac/b33e2050f0c69df601e9f323a0dbe49f6a49be9dc79c513536d80c5c5fcd/forestplot-0.4.1.tar.gz",
"platform": null,
"description": "<div id=\"top\"></div> \n<h1 align=\"center\" >\n Forestplot\n</h1>\n<p align=\"center\">\n <a href=\"https://pypi.org/project/forestplot\">\n <img alt=\"PyPI - Python Version\" src=\"https://img.shields.io/pypi/pyversions/forestplot?label=Python&logo=python&logoColor=white\">\n </a><br>\n <b>Easy API for forest plots.</b><br>\n A Python package to make publication-ready but customizable forest plots.\n</p>\n\n<p align=\"center\"><img width=\"100%\" src=\"https://raw.githubusercontent.com/LSYS/forestplot/main/docs/images/main.png\"></p>\n\n-----------------------------------------------------------\nThis package makes publication-ready forest plots easy to make out-of-the-box. Users provide a `dataframe` (e.g. from a spreadsheet) where rows correspond to a variable/study with columns including estimates, variable labels, and lower and upper confidence interval limits.\nAdditional options allow easy addition of columns in the `dataframe` as annotations in the plot.\n\n<!---------------------- Project shields ---------------------->\n\n| | |\n| --- | --- |\n| Release | [![PyPI](https://img.shields.io/pypi/v/forestplot?color=blue&label=PyPI&logo=pypi&logoColor=white)](https://pypi.org/project/forestplot/) [![Conda (channel only)](https://img.shields.io/conda/vn/conda-forge/forestplot?logo=conda-forge&logoColor=white)](https://anaconda.org/conda-forge/forestplot) [![GitHub release (latest by date)](https://img.shields.io/github/v/release/lsys/forestplot?color=blue&label=Latest%20release)](https://github.com/LSYS/forestplot/releases) |\n| Status | [![CI](https://github.com/LSYS/forestplot/actions/workflows/CI.yml/badge.svg)](https://github.com/LSYS/forestplot/actions/workflows/CI.yml) [![Notebooks](https://github.com/LSYS/forestplot/actions/workflows/nb.yml/badge.svg)](https://github.com/LSYS/forestplot/actions/workflows/nb.yml) |\n| Coverage | [![Codecov](https://img.shields.io/codecov/c/github/lsys/forestplot?logo=codecov&logoColor=white&label=codecov)](https://app.codecov.io/gh/LSYS/forestplot) |\n| Python | [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/forestplot?label=Python%203.6%2B&logo=python&logoColor=white)](https://pypi.org/project/forestplot/) |\n| Docs | [![Read the Docs (version)](https://img.shields.io/readthedocs/forestplot/stable?label=docs&logo=readthedocs&logoColor=white)](https://forestplot.readthedocs.io/en/latest/?badge=latest) [![DocLinks](https://github.com/LSYS/forestplot/actions/workflows/links.yml/badge.svg)](https://github.com/LSYS/forestplot/actions/workflows/links.yml)|\n| Meta | [![GitHub](https://img.shields.io/github/license/lsys/forestplot?color=purple&label=License)](https://choosealicense.com/licenses/mit/) [![Imports: isort](https://img.shields.io/badge/%20imports-isort-%231674b1?style=flat&labelColor=ef8336)](https://pycqa.github.io/isort/) [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) [![types - Mypy](https://img.shields.io/badge/types-Mypy-blue.svg)](https://github.com/python/mypy) [![DOI](https://zenodo.org/badge/510013191.svg)](https://zenodo.org/badge/latestdoi/510013191) |\n| Binder| [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/lsys/forestplot/main?labpath=examples%2Freadme-examples.ipynb) |\n\n<!---------------------- TABLE OF CONTENT ---------------------->\n# Table of Contents[![](https://raw.githubusercontent.com/LSYS/forestplot/main/docs/images/pin.svg)](#table-of-contents)\n<details open><summary><b>show/hide</b></summary><p>\n\n> - [Installation](#installation)\n> - [Quick Start](#quick-start)\n> - [Some Examples with Customizations](#some-examples-with-customizations)\n> - [Gallery and API Options](#gallery-and-api-options)\n> - [Multi-models](#multi-models)\n> - [Known Issues](#known-issues)\n> - [Background and Additional Resources](#background-and-additional-resources)\n> - [Contributing](#contributing)\n</p></details><p></p>\n\n<!------------------------- INSTALLATION ------------------------->\n## Installation[![](https://raw.githubusercontent.com/LSYS/forestplot/main/docs/images/pin.svg)](#installation)\n\nInstall from PyPI<br>\n [![PyPI](https://img.shields.io/pypi/v/forestplot?color=blue&label=PyPI&logo=pypi&logoColor=white)](https://pypi.org/project/forestplot/)\n```bash\npip install forestplot\n```\n\nInstall from conda-forge<br>\n[![Conda (channel only)](https://img.shields.io/conda/vn/conda-forge/forestplot?logo=conda-forge&logoColor=white)](https://anaconda.org/conda-forge/forestplot)\n```bash\nconda install forestplot\n```\n\nInstall from source<br>\n[![GitHub release (latest by date)](https://img.shields.io/github/v/release/lsys/forestplot?color=blue&label=Latest%20release)](https://github.com/LSYS/forestplot/releases)<br>\n```bash\ngit clone https://github.com/LSYS/forestplot.git\ncd forestplot\npip install .\n```\n\nDeveloper installation<br>\n```bash\ngit clone https://github.com/LSYS/forestplot.git\ncd forestplot\npip install -r requirements_dev.txt\n\nmake lint\nmake test\n```\n\n<p align=\"right\">(<a href=\"#top\">back to top</a>)</p>\n\n\n<!------------------------- QUICK START ------------------------->\n## Quick Start[![](https://raw.githubusercontent.com/LSYS/forestplot/main/docs/images/pin.svg)](#quick-start)\n\n```python\nimport forestplot as fp\n\ndf = fp.load_data(\"sleep\") # companion example data\ndf.head(3)\n```\n| | var | r | moerror | label | group | ll | hl | n | power | p-val |\n|---:|:---------|-----------:|----------:|:--------------------------|:--------------|------:|------:|----:|---------:|----------:|\n| 0 | age | 0.0903729 | 0.0696271 | in years | age | 0.02 | 0.16 | 706 | 0.671578 | 0.0163089 |\n| 1 | black | -0.0270573 | 0.0770573 | =1 if black | other factors | -0.1 | 0.05 | 706 | 0.110805 | 0.472889 |\n| 2 | clerical | 0.0480811 | 0.0719189 | =1 if clerical worker | occupation | -0.03 | 0.12 | 706 | 0.247768 | 0.201948 |\n\n(* This is a toy example of how certain factors correlate with the amount of sleep one gets. See the [notebook that generates the data](https://nbviewer.org/github/LSYS/forestplot/blob/main/examples/get-sleep.ipynb).)\n\n<details><summary><i>The example input dataframe above have 4 key columns</i></summary>\n\n | Column | Description | Required |\n |:----------|:------------------------------------------------|:----------|\n | `var` | Variable label | ✓ |\n | `r` | Correlation coefficients (estimates to plot) | ✓ |\n | `label` | Variable labels | ✓ |\n | `group` | Variable grouping labels | |\n | `ll` | Conf. int. *lower limits* | |\n | `hl` | Containing the conf. int. *higher limits* | |\n | `n` | Sample size | |\n | `power` | Statistical power | |\n | `p-val` | P-value | |\n\n (See [Gallery and API Options](#gallery-and-api-options) for more details on required and optional arguments.) \n</details>\n\nMake the forest plot\n```python\nfp.forestplot(df, # the dataframe with results data\n estimate=\"r\", # col containing estimated effect size \n ll=\"ll\", hl=\"hl\", # columns containing conf. int. lower and higher limits\n varlabel=\"label\", # column containing variable label\n ylabel=\"Confidence interval\", # y-label title\n xlabel=\"Pearson correlation\", # x-label title\n )\n```\n<p align=\"left\"><img width=\"75%\" src=\"https://raw.githubusercontent.com/LSYS/forestplot/main/docs/images/vanilla.png\"></p>\n\nSave the plot\n```python\nplt.savefig(\"plot.png\", bbox_inches=\"tight\")\n```\n<p align=\"right\">(<a href=\"#top\">back to top</a>)</p>\n\n<!------------------ EXAMPLES of CUSTOMIZATIONS ------------------>\n## Some Examples With Customizations[![](https://raw.githubusercontent.com/LSYS/forestplot/main/docs/images/pin.svg)](#some-examples-with-customizations)\n\n1. Add variable groupings, add group order, and sort by estimate size.\n```python\nfp.forestplot(df, # the dataframe with results data\n estimate=\"r\", # col containing estimated effect size \n ll=\"ll\", hl=\"hl\", # columns containing conf. int. lower and higher limits \n varlabel=\"label\", # column containing variable label\n capitalize=\"capitalize\", # Capitalize labels\n groupvar=\"group\", # Add variable groupings \n # group ordering\n group_order=[\"labor factors\", \"occupation\", \"age\", \"health factors\", \n \"family factors\", \"area of residence\", \"other factors\"],\n sort=True # sort in ascending order (sorts within group if group is specified) \n )\n```\n<p align=\"left\"><img width=\"75%\" src=\"https://raw.githubusercontent.com/LSYS/forestplot/main/docs/images/group-grouporder-sort.png\"></p>\n\n2. Add p-values on the right and color alternate rows gray\n```python\nfp.forestplot(df, # the dataframe with results data\n estimate=\"r\", # col containing estimated effect size \n ll=\"ll\", hl=\"hl\", # columns containing conf. int. lower and higher limits\n varlabel=\"label\", # column containing variable label\n capitalize=\"capitalize\", # Capitalize labels\n groupvar=\"group\", # Add variable groupings \n # group ordering\n group_order=[\"labor factors\", \"occupation\", \"age\", \"health factors\", \n \"family factors\", \"area of residence\", \"other factors\"],\n sort=True, # sort in ascending order (sorts within group if group is specified) \n pval=\"p-val\", # Column of p-value to be reported on right\n color_alt_rows=True, # Gray alternate rows\n ylabel=\"Est.(95% Conf. Int.)\", # ylabel to print\n **{\"ylabel1_size\": 11} # control size of printed ylabel\n )\n```\n\n<p align=\"left\"><img width=\"80%\" src=\"https://raw.githubusercontent.com/LSYS/forestplot/main/docs/images/group-grouporder-pvalue-sort-colorrows.png\"></p>\n\n\n3. Customize annotations and make it a table\n```python\nfp.forestplot(df, # the dataframe with results data\n estimate=\"r\", # col containing estimated effect size \n ll=\"ll\", hl=\"hl\", # lower & higher limits of conf. int.\n varlabel=\"label\", # column containing the varlabels to be printed on far left\n capitalize=\"capitalize\", # Capitalize labels\n pval=\"p-val\", # column containing p-values to be formatted\n annote=[\"n\", \"power\", \"est_ci\"], # columns to report on left of plot\n annoteheaders=[\"N\", \"Power\", \"Est. (95% Conf. Int.)\"], # ^corresponding headers\n rightannote=[\"formatted_pval\", \"group\"], # columns to report on right of plot \n right_annoteheaders=[\"P-value\", \"Variable group\"], # ^corresponding headers\n xlabel=\"Pearson correlation coefficient\", # x-label title\n table=True, # Format as a table\n )\n```\n\n<p align=\"left\"><img width=\"85%\" src=\"https://raw.githubusercontent.com/LSYS/forestplot/main/docs/images/leftannote-rightannote-table.png\"></p>\n\n4. Strip down all bells and whistle\n```python\nfp.forestplot(df, # the dataframe with results data\n estimate=\"r\", # col containing estimated effect size \n ll=\"ll\", hl=\"hl\", # lower & higher limits of conf. int.\n varlabel=\"label\", # column containing the varlabels to be printed on far left\n capitalize=\"capitalize\", # Capitalize labels\n ci_report=False, # Turn off conf. int. reporting\n flush=False, # Turn off left-flush of text\n **{'fontfamily': 'sans-serif'} # revert to sans-serif \n )\n``` \n<p align=\"left\"><img width=\"50%\" src=\"https://raw.githubusercontent.com/LSYS/forestplot/main/docs/images/vcoefplot.png\"></p>\n\n5. Example with more customizations\n```python\nfp.forestplot(df, # the dataframe with results data\n estimate=\"r\", # col containing estimated effect size \n ll=\"ll\", hl=\"hl\", # lower & higher limits of conf. int.\n varlabel=\"label\", # column containing the varlabels to be printed on far left\n capitalize=\"capitalize\", # Capitalize labels\n pval=\"p-val\", # column containing p-values to be formatted\n annote=[\"n\", \"power\", \"est_ci\"], # columns to report on left of plot\n annoteheaders=[\"N\", \"Power\", \"Est. (95% Conf. Int.)\"], # ^corresponding headers\n rightannote=[\"formatted_pval\", \"group\"], # columns to report on right of plot \n right_annoteheaders=[\"P-value\", \"Variable group\"], # ^corresponding headers\n groupvar=\"group\", # column containing group labels\n group_order=[\"labor factors\", \"occupation\", \"age\", \"health factors\", \n \"family factors\", \"area of residence\", \"other factors\"], \n xlabel=\"Pearson correlation coefficient\", # x-label title\n xticks=[-.4,-.2,0, .2], # x-ticks to be printed\n sort=True, # sort estimates in ascending order\n table=True, # Format as a table\n # Additional kwargs for customizations\n **{\"marker\": \"D\", # set maker symbol as diamond\n \"markersize\": 35, # adjust marker size\n \"xlinestyle\": (0, (10, 5)), # long dash for x-reference line \n \"xlinecolor\": \"#808080\", # gray color for x-reference line\n \"xtick_size\": 12, # adjust x-ticker fontsize\n } \n )\n```\n<p align=\"left\"><img width=\"100%\" src=\"https://raw.githubusercontent.com/LSYS/forestplot/main/docs/images/main.png\"></p>\n\n<details><summary><i>Annotations arguments allowed include:</i></summary>\n \n * `ci_range`: Confidence interval range (e.g. `(-0.39 to -0.25)`).\n * `est_ci`: Estimate and CI (e.g. `-0.32(-0.39 to -0.25)`).\n * `formatted_pval`: Formatted p-values (e.g. `0.01**`).\n \n To confirm what processed `columns` are available as annotations, you can do:\n \n ```python\n processed_df, ax = fp.forestplot(df, \n ... # other arguments here\n return_df=True # return processed dataframe with processed columns\n )\n processed_df.head(3)\n ```\n \n | | label | group | n | r | CI95% | p-val | BF10 | power | var | hl | ll | moerror | formatted_r | formatted_ll | formatted_hl | ci_range | est_ci | formatted_pval | formatted_n | formatted_power | formatted_est_ci | yticklabel | formatted_formatted_pval | formatted_group | yticklabel2 |\n|---:|:---------------------|:--------------|----:|-----------:|:--------------|------------:|----------:|--------:|:-------|------:|------:|----------:|--------------:|---------------:|---------------:|:-----------------|:----------------------|:-----------------|--------------:|------------------:|:----------------------|:------------------------------------------------------------------|:---------------------------|:------------------|:-----------------------|\n| 0 | Mins worked per week | Labor factors | 706 | -0.321384 | [-0.39 -0.25] | 1.99409e-18 | 1.961e+15 | 1 | totwrk | -0.25 | -0.39 | 0.0686165 | -0.32 | -0.39 | -0.25 | (-0.39 to -0.25) | -0.32(-0.39 to -0.25) | 0.0*** | 706 | 1 | -0.32(-0.39 to -0.25) | Mins worked per week 706 1.0 -0.32(-0.39 to -0.25) | 0.0*** | Labor factors | 0.0*** Labor factors |\n| 1 | Years of schooling | Labor factors | 706 | -0.0950039 | [-0.17 -0.02] | 0.0115515 | 1.137 | 0.72 | educ | -0.02 | -0.17 | 0.0749961 | -0.1 | -0.17 | -0.02 | (-0.17 to -0.02) | -0.10(-0.17 to -0.02) | 0.01** | 706 | 0.72 | -0.10(-0.17 to -0.02) | Years of schooling 706 0.72 -0.10(-0.17 to -0.02) | 0.01** | Labor factors | 0.01** Labor factors |\n \n</details>\n<p align=\"right\">(<a href=\"#top\">back to top</a>)</p>\n\n<!------------------- Multi-models ------------------->\n## Multi-models[![](https://raw.githubusercontent.com/LSYS/forestplot/main/docs/images/pin.svg)](#multi-models)\n\nFor coefficient plots where each variable can have multiple estimates (each `model` has one).\n\n```python\nimport forestplot as fp\n\ndf_mmodel = pd.read_csv(\"../examples/data/sleep-mmodel.csv\").query(\n \"model=='all' | model=='young kids'\"\n)\ndf_mmodel.head(3)\n```\n\n| | var | coef | se | T | pval | r2 | adj_r2 | ll | hl | model | group | label |\n|---:|:------|-----------:|---------:|----------:|---------:|---------:|-----------:|-----------:|--------:|:-----------|:--------------|:------------|\n| 0 | age | 0.994889 | 1.96925 | 0.505213 | 0.613625 | 0.127289 | 0.103656 | -2.87382 | 4.8636 | all | age | in years |\n| 3 | age | 22.634 | 15.4953 | 1.4607 | 0.149315 | 0.178147 | -0.0136188 | -8.36124 | 53.6293 | young kids | age | in years |\n| 4 | black | -84.7966 | 82.1501 | -1.03222 | 0.302454 | 0.127289 | 0.103656 | -246.186 | 76.5925 | all | other factors | =1 if black |\n\n```python\nfp.mforestplot(\n dataframe=df_mmodel,\n estimate=\"coef\",\n ll=\"ll\",\n hl=\"hl\",\n varlabel=\"label\",\n capitalize=\"capitalize\",\n model_col=\"model\",\n color_alt_rows=True,\n groupvar=\"group\",\n table=True,\n rightannote=[\"var\", \"group\"],\n right_annoteheaders=[\"Source\", \"Group\"],\n xlabel=\"Coefficient (95% CI)\",\n modellabels=[\"Have young kids\", \"Full sample\"],\n xticks=[-1200, -600, 0, 600],\n mcolor=[\"#CC6677\", \"#4477AA\"],\n # Additional kwargs for customizations\n **{\n \"markersize\": 30,\n # override default vertical offset between models (0.0 to 1.0)\n \"offset\": 0.35, \n \"xlinestyle\": (0, (10, 5)), # long dash for x-reference line\n \"xlinecolor\": \".8\", # gray color for x-reference line\n },\n)\n```\n<p align=\"left\"><img width=\"100%\" src=\"https://raw.githubusercontent.com/LSYS/forestplot/mplot-dev/docs/images/multimodel.png\"></p>\n\nPlease note: This module is still experimental. See [this jupyter notebook](https://nbviewer.org/github/LSYS/forestplot/blob/mplot-dev/examples/test-multmodel-sleep.ipynb) for more examples and tweaks.\n\n<!------------------- GALLERY AND API OPTIONS ------------------->\n## Gallery and API Options[![](https://raw.githubusercontent.com/LSYS/forestplot/main/docs/images/pin.svg)](#gallery-and-api-options)\n\n[![Notebooks](https://github.com/LSYS/forestplot/actions/workflows/nb.yml/badge.svg)](https://github.com/LSYS/forestplot/actions/workflows/nb.yml)\n\nCheck out [this jupyter notebook](https://nbviewer.org/github/LSYS/forestplot/blob/main/examples/readme-examples.ipynb) for a gallery variations of forest plots possible out-of-the-box.\nThe table below shows the list of arguments users can pass in.\nMore fined-grained control for base plot options (eg font sizes, marker colors) can be inferred from the [example notebook gallery](https://nbviewer.org/github/LSYS/forestplot/blob/main/examples/readme-examples.ipynb). \n\n\n| Option | Description | Required |\n|:-------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------|:---|\n| `dataframe` | Pandas dataframe where rows are variables (or studies for meta-analyses) and columns include estimated effect sizes, labels, and confidence intervals, etc. | ✓ |\n| `estimate` | Name of column in `dataframe` containing the *estimates*. | ✓ |\n| `varlabel` | Name of column in `dataframe` containing the *variable labels* (study labels if meta-analyses). | ✓ |\n| `ll` | Name of column in `dataframe` containing the conf. int. *lower limits*. | |\n| `hl` | Name of column in `dataframe` containing the conf. int. *higher limits*. | |\n| `logscale` | If True, make the x-axis log scale. Default is False. | |\n| `capitalize` | How to capitalize strings. Default is None. One of \"capitalize\", \"title\", \"lower\", \"upper\", \"swapcase\". | |\n| `form_ci_report` | If True (default), report the estimates and confidence interval beside the variable labels. | |\n| `ci_report` | If True (default), format the confidence interval as a string. | |\n| `groupvar` | Name of column in `dataframe` containing the variable *grouping labels*. | |\n| `group_order` | List of group labels indicating the order of groups to report in the plot. | |\n| `annote` | List of columns to add as annotations on the left-hand side of the plot. | |\n| `annoteheaders` | List of column headers for the left-hand side annotations. | |\n| `rightannote` | List of columns to add as annotations on the right-hand side of the plot. | |\n| `right_annoteheaders` | List of column headers for the right-hand side annotations. | |\n| `pval` | Name of column in `dataframe` containing the p-values. | |\n| `starpval` | If True (default), format p-values with stars indicating statistical significance. | |\n| `sort` | If True, sort variables by `estimate` values in ascending order. | |\n| `sortby` | Name of column to sort by. Default is `estimate`. | |\n| `flush` | If True (default), left-flush variable labels and annotations. | |\n| `decimal_precision` | Number of decimal places to print. (Default = 2) | |\n| `figsize` | Tuple indicating core figure size. Default is (4, 8) | |\n| `xticks` | List of xticklabels to print on x-axis. | |\n| `ylabel` | Y-label title. | |\n| `xlabel` | X-label title. | |\n| `color_alt_rows` | If True, shade out alternating rows in gray. | |\n| `preprocess` | If True (default), preprocess the `dataframe` before plotting. | |\n| `return_df` | If True, returned the preprocessed `dataframe`. | |\n\n<p align=\"right\">(<a href=\"#top\">back to top</a>)</p>\n\n<!------------------------ KNOWN ISSUES ------------------------>\n## Known Issues[![](https://raw.githubusercontent.com/LSYS/forestplot/main/docs/images/pin.svg)](#known-issues)\n\n* Variable labels coinciding with group variables may lead to unexpected formatting issues in the graph.\n* Left-flushing of annotations relies on the `monospace` font.\n* Plot may give strange behavior for few rows of data (six rows or fewer. [see this issue](https://github.com/LSYS/forestplot/issues/52))\n* Plot can get cluttered with too many variables/rows (~30 onwards) \n* Not tested with PyCharm (#80) nor Google Colab (#110).\n* Duplicated `varlabel` may lead to unexpected results (see #76, #81). `mplot` for grouped models could be useful for such cases (see #59, WIP).\n<p align=\"right\">(<a href=\"#top\">back to top</a>)</p>\n\n<!----------------- BACKGROUND AND ADDITIONAL RESOURCES ----------------->\n## Background and Additional Resources[![](https://raw.githubusercontent.com/LSYS/forestplot/main/docs/images/pin.svg)](#background-and-additional-resources)\n\n**More about forest plots**\n\n[Forest plots](https://en.wikipedia.org/wiki/Forest_plot) have many aliases (h/t Chris Alexiuk). Other names include coefplots, coefficient plots, meta-analysis plots, dot-and-whisker plots, blobbograms, margins plots, regression plots, and ropeladder plots. \n\n[Forest plots](https://en.wikipedia.org/wiki/Forest_plot) in the medical and health sciences literature are plots that report results from different studies as a meta-analysis. Markers are centered on the estimated effect and horizontal lines running through each marker depicts the confidence intervals.\n\nThe simplest version of a forest plot has two columns: one for the variables/studies, and the second for the estimated coefficients and confidence intervals.\nThis layout is similar to coefficient plots ([coefplots](http://repec.sowi.unibe.ch/stata/coefplot/getting-started.html)) and is thus useful for more than meta-analyses.\n\n<details><summary><i>More resources about forest plots</i></summary><p>\n\n* [[1]](https://doi.org/10.1038/s41433-021-01867-6) Chang, Y., Phillips, M.R., Guymer, R.H. et al. The 5 min meta-analysis: understanding how to read and interpret a forest plot. Eye 36, 673\u2013675 (2022).\n* [[2]](https://doi.org/10.1136/bmj.322.7300.1479) Lewis S, Clarke M. Forest plots: trying to see the wood and the trees BMJ 2001; 322 :1479 \n</p></details><p></p>\n\n**More about this package**\n\nThe package is lightweight, built on `pandas`, `numpy`, and `matplotlib`.\n\nIt is slightly opinioniated in that the aesthetics of the plot inherits some of my sensibilities about what makes a nice figure.\nYou can however easily override most defaults for the look of the graph. This is possible via `**kwargs` in the `forestplot` API (see [Gallery and API options](#gallery-and-api-options)) and the `matplotlib` API.\n\n**Planned enhancements** include forest plots where each row can have multiple coefficients (e.g. from multiple models). \n\n<details><summary><i>Related packages</i></summary><p>\n\n* [[1]](https://www.stata-journal.com/article.html?article=gr0059) [Stata] Jann, Ben (2014). Plotting regression coefficients and other estimates. The Stata Journal 14(4): 708-737. \n* [[2]](https://www.statsmodels.org/devel/examples/notebooks/generated/metaanalysis1.html) [Python] Meta-Analysis in statsmodels\n* [[3]](https://github.com/seafloor/forestplot) [Python] Matt Bracher-Smith's Forestplot\n* [[4]](https://github.com/fsolt/dotwhisker) [R] Solt, Frederick and Hu, Yue (2021) dotwhisker: Dot-and-Whisker Plots of Regression Results\n* [[5]](https://rpubs.com/mbounthavong/forest_plots_r) [R] Bounthavong, Mark (2021) Forest plots. RPubs by RStudio\n</p></details><p></p>\n\n<p align=\"right\">(<a href=\"#top\">back to top</a>)</p>\n\n\n<!----------------------- CONTRIBUTING ----------------------->\n## Contributing[![](https://raw.githubusercontent.com/LSYS/forestplot/main/docs/images/pin.svg)](#contributing)\n\nContributions are welcome, and they are greatly appreciated!\n\n**Potential ways to contribute:**\n\n* Raise issues/bugs/questions\n* Write tests for missing coverage\n* Add features (see [examples notebook](https://nbviewer.org/github/LSYS/forestplot/blob/main/examples/readme-examples.ipynb) for a survey of existing features)\n* Add example datasets with companion graphs\n* Add your graphs with companion code\n\n**Issues**\n\nPlease submit bugs, questions, or issues you encounter to the [GitHub Issue Tracker](https://github.com/lsys/forestplot/issues).\nFor bugs, please provide a minimal reproducible example demonstrating the problem (it may help me troubleshoot if I have a version of your data).\n\n**Pull Requests**\n\nPlease feel free to open an issue on the [Issue Tracker](https://github.com/lsys/forestplot/issues) if you'd like to discuss potential contributions via PRs.\n\n<p align=\"right\">(<a href=\"#top\">back to top</a>)</p>\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "A Python package to make publication-ready but customizable forest plots.",
"version": "0.4.1",
"project_urls": {
"Homepage": "https://github.com/lsys/forestplot"
},
"split_keywords": [
"visualization",
" python",
" data-science",
" dataviz",
" pandas",
" matplotlib",
" mpl",
" forestplot",
" blobbogram"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "2f91d58d82633a8f48838c5ca2c34fa459dceefc56b227c90db90393ffbc4c75",
"md5": "cbec623c889d083d7af68f513660d7dd",
"sha256": "f863f255d336d690e3c3e36f7045bceff779542270b6b886a0e84562e98739c4"
},
"downloads": -1,
"filename": "forestplot-0.4.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "cbec623c889d083d7af68f513660d7dd",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 37055,
"upload_time": "2024-07-28T07:25:36",
"upload_time_iso_8601": "2024-07-28T07:25:36.185433Z",
"url": "https://files.pythonhosted.org/packages/2f/91/d58d82633a8f48838c5ca2c34fa459dceefc56b227c90db90393ffbc4c75/forestplot-0.4.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "a9acb33e2050f0c69df601e9f323a0dbe49f6a49be9dc79c513536d80c5c5fcd",
"md5": "71bcce28732cfa40106a8f2a7adab83e",
"sha256": "ffba9fe7781d8cddd468ff63942e751786a312bc810d6fa0ff311187f577b9c0"
},
"downloads": -1,
"filename": "forestplot-0.4.1.tar.gz",
"has_sig": false,
"md5_digest": "71bcce28732cfa40106a8f2a7adab83e",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 44854,
"upload_time": "2024-07-28T07:25:38",
"upload_time_iso_8601": "2024-07-28T07:25:38.321782Z",
"url": "https://files.pythonhosted.org/packages/a9/ac/b33e2050f0c69df601e9f323a0dbe49f6a49be9dc79c513536d80c5c5fcd/forestplot-0.4.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-07-28 07:25:38",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "lsys",
"github_project": "forestplot",
"travis_ci": true,
"coveralls": false,
"github_actions": true,
"requirements": [],
"tox": true,
"lcname": "forestplot"
}