Skip to content

Commit

Permalink
Patch (#55)
Browse files Browse the repository at this point in the history
* Fix spacing issue at top of plot (fixes #48, #47)
* Create notebook for some simple regression tests (closes #49)
* Tidy imports using isort (closes #50)
* Allowed thresholds and symbols for p-values to be passedthrough (fixes #51)
* Fix different heigh and fontsize for confidence interval and p-value labels (fixes #53)
* Update docs for RTD (closes #54) 
* Freeze matplotlib-inline dependency in setup.py (closes #56)
  • Loading branch information
LSYS committed Feb 10, 2023
1 parent 8641fe4 commit 30ee8d0
Show file tree
Hide file tree
Showing 31 changed files with 1,331 additions and 207 deletions.
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,16 @@ lint:
mypy $(SRC_FILES) --ignore-missing-imports
python -m pyflakes tests/*.py $(SRC_FILES)
python -m pyflakes setup.py
isort --profile black $(BLACK_OPTS) .
black forestplot/*.py $(BLACK_OPTS)
black forestplot/*.py $(BLACK_OPTS)
black tests/*.py $(BLACK_OPTS)
black setup.py $(BLACK_OPTS)

.PHONY: docstring
docstring: # Check docstrings using pydocstyle
pydocstyle --convention numpy

.PHONY: prepack
prepack: # Prepare packaging for PyPi
prepack:
Expand Down
31 changes: 16 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<div id="top"></div>
<h1 align="center" >
<strong>Forestplot</strong>
Forestplot
</h1>
<p align="center">
<a href="https://pypi.org/project/forestplot">
Expand All @@ -13,24 +13,24 @@
<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) [![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) |
| 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) [![Language grade: Python](https://img.shields.io/lgtm/grade/python/g/LSYS/forestplot.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/LSYS/forestplot/context:python) [![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) |
| 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 ---------------------->
<details open><summary><b>Table of Contents</b></summary><p>
# 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)
Expand All @@ -51,7 +51,7 @@ 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)
[![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
```
Expand All @@ -78,7 +78,7 @@ make test


<!------------------------- QUICK START ------------------------->
## Quick start[![](https://raw.githubusercontent.com/LSYS/forestplot/main/docs/images/pin.svg)](#quick-start)
## Quick Start[![](https://raw.githubusercontent.com/LSYS/forestplot/main/docs/images/pin.svg)](#quick-start)

```python
import forestplot as fp
Expand Down Expand Up @@ -119,7 +119,7 @@ fp.forestplot(df, # the dataframe with results data
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
xlabel="Pearson correlation", # x-label title
)
```
<p align="left"><img width="55%" src="https://raw.githubusercontent.com/LSYS/forestplot/main/docs/images/vanilla.png"></p>
Expand All @@ -131,8 +131,7 @@ 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)](#examples-with-customizations)

## Some Examples With Customizations[![](https://raw.githubusercontent.com/LSYS/forestplot/main/docs/images/pin.svg)](#examples-with-customizations)

1. Add variable groupings, add group order, and sort by estimate size.
```python
Expand All @@ -145,10 +144,10 @@ fp.forestplot(df, # the dataframe with results data
# 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)
sort=True, # sort in ascending order (sorts within group if group is specified)
)
```
<p align="left"><img width="65%" src="https://raw.githubusercontent.com/LSYS/forestplot/main/docs/images/group-grouporder-sort.png"></p>
<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
Expand All @@ -169,7 +168,7 @@ fp.forestplot(df, # the dataframe with results data
)
```

<p align="left"><img width="70%" src="https://raw.githubusercontent.com/LSYS/forestplot/main/docs/images/group-grouporder-pvalue-sort-colorrows.png"></p>
<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
Expand All @@ -189,7 +188,7 @@ fp.forestplot(df, # the dataframe with results data
)
```

<p align="left"><img width="75%" src="https://raw.githubusercontent.com/LSYS/forestplot/main/docs/images/leftannote-rightannote-table.png"></p>
<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
Expand Down Expand Up @@ -233,7 +232,7 @@ fp.forestplot(df, # the dataframe with results data
}
)
```
<p align="left"><img width="70%" src="https://raw.githubusercontent.com/LSYS/forestplot/main/docs/images/main.png"></p>
<p align="left"><img width="80%" src="https://raw.githubusercontent.com/LSYS/forestplot/main/docs/images/main.png"></p>

<details><summary><i>Annotations arguments allowed include:</i></summary>

Expand Down Expand Up @@ -307,8 +306,10 @@ More fined-grained control for base plot options (eg font sizes, marker colors)

<!------------------------ 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)
<p align="right">(<a href="#top">back to top</a>)</p>

Expand Down
3 changes: 2 additions & 1 deletion codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ coverage:
target: auto
# adjust accordingly based on how flaky your tests are
# this allows a 10% drop from the previous base commit coverage
threshold: 50% # Relax my coverage target, because I have flaky tests
threshold: 10% # Relax my coverage target, because I have flaky tests
patch: off
Empty file added docs/README.rst
Empty file.
328 changes: 328 additions & 0 deletions docs/assets/issue52-table-does-not-work-6rows-or-fewer.ipynb

Large diffs are not rendered by default.

18 changes: 14 additions & 4 deletions docs/conf.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"""Config file for Sphinx."""
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
Expand All @@ -17,8 +18,8 @@

# -- Project information -----------------------------------------------------

project = 'pyForestplot'
copyright = '2022, Lucas Shen'
project = 'Forestplot'
copyright = '2023, Lucas Shen'
author = 'Lucas Shen'

# The full version, including alpha/beta/rc tags
Expand All @@ -33,7 +34,7 @@
extensions = [
'myst_parser'
]

myst_heading_anchors = 2
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']

Expand All @@ -49,7 +50,16 @@
# a list of builtin themes.
#
html_theme = 'furo'

html_sidebars = {
"**": [
"sidebar/scroll-start.html",
"sidebar/brand.html",
"sidebar/search.html",
"sidebar/navigation.html",
"sidebar/ethical-ads.html",
"sidebar/scroll-end.html",
]
}
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
Expand Down
Binary file modified docs/images/group-grouporder-pvalue-sort-colorrows.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/images/group-grouporder-sort.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/images/leftannote-rightannote-table.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/images/main.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/images/vanilla.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/images/vcoefplot.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@

```{toctree}
:caption: 'Contents:'
:maxdepth: 1
:maxdepth: 2
```
3 changes: 2 additions & 1 deletion docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
myst_parser
furo
furo
forestplot
1 change: 1 addition & 0 deletions examples/data/regression1.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
varname,or,low,higha,1.761471,0.926563,3.022285b,1.44366,0.517059,3.130794c,1.525227,0.603459,3.082003d,0.895682,0.463703,1.660016e,4.02567,1.196941,8.932753f,1.086105,0.555171,2.045735
Expand Down
64 changes: 36 additions & 28 deletions examples/readme-examples.ipynb

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions forestplot/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
VERSION = (0, 2, 1)
"""State version and import user-facing functions."""
VERSION = (0, 2, 2)

__version__ = ".".join(map(str, VERSION))

from forestplot.plot import forestplot
from forestplot.dataframe_utils import load_data
from forestplot.plot import forestplot
87 changes: 44 additions & 43 deletions forestplot/arg_validators.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import pandas.api.types as ptypes
import pandas as pd
from typing import Optional, Union, Sequence
"""Holds functions to check data and validate arguments from users."""
import warnings
from typing import Optional, Sequence, Union

import pandas as pd
import pandas.api.types as ptypes


def check_data(
Expand All @@ -19,46 +21,45 @@ def check_data(
pval: Optional[str] = None,
ylabel2: Optional[str] = None,
) -> pd.core.frame.DataFrame:
"""
Checks and validate that dataframe has the correct data. If data is missing, create them.
"""Check and validate that dataframe has the correct data. If data is missing, create them.
Checks and validates key arguments.
Parameters
----------
dataframe (pandas.core.frame.DataFrame)
Pandas DataFrame where rows are variables. Columns are variable name, estimates,
margin of error, etc.
estimate (str)
Name of column containing the estimates (e.g. pearson correlation coefficient,
OR, regression estimates, etc.).
varlabel (str)
Name of column containing the variable label to be printed out.
groupvar (str)
Name of column containing group of variables.
group_order (list-like)
List of groups by order to report in the figure.
ll (str)
Name of column containing the lower limit of the confidence intervals.
hl (str)
Name of column containing the upper limit of the confidence intervals.
annote (list-like)
List of columns to add as additional annotation in the plot.
annoteheaders (list-like)
List of table headers to use as column headers for the additional annotations.
rightannote (list-like)
List of columns to add as additional annotation on the right-hand side of the plot.
right_annoteheaders (list-like)
List of table headers to use as column headers for the additional annotations
on the right-hand side of the plot.
pval (str)
Name of column containing the p-values.
ylabel2 (str)
Title of the right-hand side y-axis.
Returns
-------
pd.core.frame.DataFrame.
Parameters
----------
dataframe (pandas.core.frame.DataFrame)
Pandas DataFrame where rows are variables. Columns are variable name, estimates,
margin of error, etc.
estimate (str)
Name of column containing the estimates (e.g. pearson correlation coefficient,
OR, regression estimates, etc.).
varlabel (str)
Name of column containing the variable label to be printed out.
groupvar (str)
Name of column containing group of variables.
group_order (list-like)
List of groups by order to report in the figure.
ll (str)
Name of column containing the lower limit of the confidence intervals.
hl (str)
Name of column containing the upper limit of the confidence intervals.
annote (list-like)
List of columns to add as additional annotation in the plot.
annoteheaders (list-like)
List of table headers to use as column headers for the additional annotations.
rightannote (list-like)
List of columns to add as additional annotation on the right-hand side of the plot.
right_annoteheaders (list-like)
List of table headers to use as column headers for the additional annotations
on the right-hand side of the plot.
pval (str)
Name of column containing the p-values.
ylabel2 (str)
Title of the right-hand side y-axis.
Returns
-------
pd.core.frame.DataFrame.
"""
##########################################################################
## Check that numeric data are numeric
Expand Down Expand Up @@ -203,7 +204,7 @@ def check_data(


def check_iterables_samelen(*args): # type: ignore
"""Assert that provided iterables have same length"""
"""Assert that provided iterables have same length."""
try:
assert all(len(args[0]) == len(_arg) for _arg in args[1:])
except Exception:
Expand All @@ -214,8 +215,7 @@ def check_iterables_samelen(*args): # type: ignore
def check_groups(
dataframe: pd.core.frame.DataFrame, groupvar: str, group_order: Optional[Sequence]
) -> None:
"""
Check that provided group-related args are well-behaved.
"""Check that provided group-related args are well-behaved.
Parameters
----------
Expand All @@ -226,6 +226,7 @@ def check_groups(
Name of column containing group of variables.
group_order (list-like)
List of groups by order to report in the figure.
Returns
-------
None
Expand Down
6 changes: 4 additions & 2 deletions forestplot/dataframe_utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import pandas as pd
"""Holds functions to check prepare dataframe for plotting."""
from typing import Any, Optional, Union

import numpy as np
from typing import Optional, Union, Any
import pandas as pd


def insert_groups(
Expand Down

0 comments on commit 30ee8d0

Please sign in to comment.