sinaplot
sinaplot draws SinaPlots from pandas data
with Matplotlib. A SinaPlot shows every observation while using the width of
the point distribution to represent the estimated density.
This implementation has two features intended to make comparisons more truthful:
- The area of each violin is proportional to the number of observations in that group. A larger group therefore has a larger envelope instead of every violin being normalized independently.
jitter_method="even"spreads nearby points in display space, reducing overlap and producing a more even visual density.
Installation
pip install sinaplot
Python 3.10 or later is required.
Quick start
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from sinaplot import sinaplot
rng = np.random.default_rng(7)
data = pd.DataFrame(
{
"condition": np.repeat(["Control", "Treatment A", "Treatment B"], [50, 90, 130]),
"response": np.concatenate(
[
rng.normal(0.0, 0.8, 50),
rng.normal(0.7, 1.0, 90),
np.r_[rng.normal(-0.2, 0.45, 65), rng.normal(1.7, 0.55, 65)],
]
),
}
)
fig, ax = plt.subplots(figsize=(7, 4.5))
sinaplot(
x="condition",
y="response",
data=data,
jitter_method="even",
random_seed=42,
ax=ax,
)
fig.tight_layout()
plt.show()
sinaplot returns the Matplotlib Axes, so normal Matplotlib customization
continues to work:
ax = sinaplot(
"condition",
"response",
data,
order=["Treatment B", "Treatment A", "Control"],
color="tab:purple",
violin_kws={"alpha": 0.2},
scatter_kws={"edgecolor": "white", "linewidth": 0.3},
)
ax.set_title("Response by condition")
Main options
| Option | Meaning |
|---|---|
violin=True |
Draw the sample-size-scaled density envelope. |
max_width=0.8 |
Set the maximum full width in category-axis units. |
jitter_method="random" |
Randomly place points inside the envelope. |
jitter_method="even" |
Iteratively spread nearby points to reduce overlap. |
random_seed=None |
Make either placement method reproducible. |
order=None |
Set an explicit category order. Ordered pandas categoricals are respected automatically. |
bw_method=None |
Pass a KDE bandwidth method to SciPy. |
violin_kws, scatter_kws |
Pass styling options to Matplotlib. |
Rows with missing categories or missing/non-finite numerical values are omitted. Groups with fewer than two distinct values cannot have a kernel density estimate and are represented by a horizontal line.
How area scaling works
For each group, the displayed kernel density is numerically normalized over the plotted range and then multiplied by the number of finite observations in that group. All groups use one common horizontal scale. Consequently, violin area is proportional to sample size, while the local width still represents density.
The points are always constrained to the corresponding density envelope.
With jitter_method="even", an iterative repulsion calculation in display
coordinates gives nearby points more uniform spacing. Set random_seed when
you need exactly reproducible coordinates.
Development
git clone https://github.com/okumuralab/sinaplot.git
cd sinaplot
python -m pip install -e ".[test]"
python -m pytest
Build the wheel and source distribution with:
python -m pip install build
python -m build
Reference
Sidiropoulos N, Sohi SH, Pedersen TL, Porse BT, Winther O, Rapin N, Bagger FO. “SinaPlot: an enhanced chart for simple and truthful representation of single observations over multiple classes.” Journal of Computational and Graphical Statistics 27(3), 673–676 (2018). doi:10.1080/10618600.2017.1366914. Preprint: doi:10.1101/028191.
This project is an independent Python implementation and is not affiliated with the authors of the paper or the R packages that implement SinaPlot.
License
MIT
Metadata
Release files for sinaplot 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| sinaplot-0.1.0.tar.gz | 80.9 kB | With provenance | Details for sinaplot-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| sinaplot-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for sinaplot-0.1.0-py3-none-any.whl |
Total release size: 89.2 kB
Release files / sinaplot-0.1.0.tar.gz
| Download URL | sinaplot-0.1.0.tar.gz |
|---|---|
| Size | 80.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
462d8d62c6daaba7d973583974fefc5d8d22434de521ad9eab95c807f9b7ebe0
|
|
BLAKE2b-256 checksum How to use checksums |
f75d05618890ea41016bb8a2508c8b3740e6aa84eae7397417b1a33c3d64998d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 24, 2026.
Transparency logRelease files / sinaplot-0.1.0-py3-none-any.whl
| Download URL | sinaplot-0.1.0-py3-none-any.whl |
|---|---|
| Size | 8.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3e90cd16fa2ccaec0f56af9e6f6ca08007680f8e80714caae35dc67af82cebde
|
|
BLAKE2b-256 checksum How to use checksums |
a6c466626e9ce7f9242316a01d2c2d6b3f50b4dae828d29b50b4de45c93e1925
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 24, 2026.
Transparency logSecurity for sinaplot 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
Both files in this release have been uploaded with provenance metadata.
Attestation for sinaplot-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 24, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.