Skip to main content

Convenient plotting wrapper around matplotlib.

Project description

MatChart

MatChart is a convenient one-line wrapper around matplotlib plotting library.

Usage

from matchart import plot

plot([x1, y1], [y2], [x3, y3], y4, ...,
	# common parameters
	kind='plot',
	show: bool = True,
	block: Optional[bool] = None,
	context: bool = False,
	clear_on_error: bool = True,
	
	# plotter explict parameters
	label: ClippedArguments = None,
	color: CycledArguments = None,
	marker: ClippedArguments = None,
	linestyle: ClippedArguments = None,
	linewidth: ClippedArguments = None,
	markersize: ClippedArguments = None,
	
	# figure and axes parameters
	legend: Optional[bool] = None,
	legend_kwargs: Optional[Dict[str, Any]] = None,
	title: Optional[str] = None,
	title_kwargs: Optional[Dict[str, Any]] = None,
	xlabel: Optional[str] = None,
	xlabel_kwargs: Optional[Dict[str, Any]] = None,
	ylabel: Optional[str] = None,
	ylabel_kwargs: Optional[Dict[str, Any]] = None,
	limit: Union[Tuple[Any, Any, Any, Any], bool] = True,
	xticks: Optional[Union[Iterable, Dict[str, Any], bool]] = None,
	yticks: Optional[Union[Iterable, Dict[str, Any], bool]] = None,
	ticks: Optional[Dict[str, Union[Iterable, Dict[str, Any], bool]]] = None,
	figsize: Tuple[float, float] = (10, 8),
	dpi: float = 100,
	subplots_kwargs: Optional[Dict[str, Any]] = None,
	grid: Optional[bool] = False,
	grid_kwargs: Optional[Dict[str, Any]] = None,
	theme = 'seaborn-v0_8-deep',

	# plotter rest parameters
	** plotter_kwargs 
) -> Tuple[Figure, Axes, List[Artist]]

kind - pyplot function name, e.g. plot or scatter.

show - whether to show plot or just to draw it.

block - whether to block running code when showing plot or just display windows and run next lines. By default, detected from environment.

context - delay showing plot by using context manager (see below).

clear_on_error - whether to clean up on any error.

label, color, marker, linestyle, linewidth, markersize and rest plotter_kwargs - plotter parameters. Can differ per kind. See common parameters for kind='plot'. Can be list or tuple to define per-dataset values. Values can also be None or even clipped to skip definition for particular dataset.

legend - set True, False or None to autodetect. legend_kwargs - additional parameters.

title - plot's title. title_kwargs - additional parameters.

xlabel - horizontal axis label. xlabel_kwargs - additional parameters.

ylabel - vertical axis label. ylabel_kwargs - additional parameters.

limit - set True to autodetect 2D plot's borders or False to use default matplot's behaviour. Set to (left, right, bottom, top) to use custom borders.

ticks, xticks, yticks - set corresponding ticks. Can be False to disable ticks. Can be dictionary of kwargs. Can be array-like value to define ticks locations. Argument xticks defines ticks for X axis, yticks - for Y axis. Alternatively argument ticks can be defined as dictionary with keys 'x' or 'y' containing same values as xticks and yticks arguments. Argument xticks must be used solely.

figsize - plot's size as (width, height) in inches. By default, is overriden with 10x8.

dpi - plot's resolution in dots-per-inch.

subplots_kwargs - additional plot's parameters and Figure's parameters.

grid - plot's grid visibility with grid_kwargs as additional parameters.

theme - plot's style. By default is overriden with seaborn-v0_8-deep.

Examples

Just plot something

Firstly prepare data:

import numpy as np

x1 = np.arange(21)
y1 = x1 ** 2
y2 = x1 ** 1.9
x3 = 5, 15
y3 = 300, 100
y4 = x1 ** 2.1

Then plot data:

from matchart import plot

plot([x1, y1], [y2], [x3, y3], y4,
	 label=['$x^{2}$', '$x^{1.9}$', 'Points'],
	 xlabel='X', ylabel='Y',
	 title='Power of $x$ comparison.',
	 grid=True,
	 color=[None, 'green', 'red', 'gray'],
	 marker=['o', None, '*'],
	 linestyle=[None, '--'],
	 linewidth=[None, 3, 0],
	 markersize=20,
	 fillstyle='top')

Migrate from matplotlib simple

Let's take FiveThirtyEight style sheet example:

import matplotlib.pyplot as plt
import numpy as np

plt.style.use('fivethirtyeight')

x = np.linspace(0, 10)
np.random.seed(19680801)  # Fixing random state for reproducibility

fig, ax = plt.subplots()
ax.plot(x, np.sin(x) + x + np.random.randn(50))
ax.plot(x, np.sin(x) + 0.5 * x + np.random.randn(50))
ax.plot(x, np.sin(x) + 2 * x + np.random.randn(50))
ax.plot(x, np.sin(x) - 0.5 * x + np.random.randn(50))
ax.plot(x, np.sin(x) - 2 * x + np.random.randn(50))
ax.plot(x, np.sin(x) + np.random.randn(50))
ax.set_title("'fivethirtyeight' style sheet")
plt.show()

and rewrite it with MatChart:

from matchart import plot
import numpy as np

x = np.linspace(0, 10)
np.random.seed(19680801)  # Fixing random state for reproducibility

plot([x, np.sin(x) + x + np.random.randn(50)],
	 [x, np.sin(x) + 0.5 * x + np.random.randn(50)],
	 [x, np.sin(x) + 2 * x + np.random.randn(50)],
	 [x, np.sin(x) - 0.5 * x + np.random.randn(50)],
	 [x, np.sin(x) - 2 * x + np.random.randn(50)],
	 [x, np.sin(x) + np.random.randn(50)],
	 title="'fivethirtyeight' style sheet",
	 theme='fivethirtyeight')

Note that default figure size differs.

Migrate from matplotlib stackplot

Let's take stackplots example:

import matplotlib.pyplot as plt

# data from United Nations World Population Prospects (Revision 2019)
# https://population.un.org/wpp/, license: CC BY 3.0 IGO
year = [1950, 1960, 1970, 1980, 1990, 2000, 2010, 2018]
population_by_continent = {
	'africa'  : [228, 284, 365, 477, 631, 814, 1044, 1275],
	'americas': [340, 425, 519, 619, 727, 840, 943, 1006],
	'asia'    : [1394, 1686, 2120, 2625, 3202, 3714, 4169, 4560],
	'europe'  : [220, 253, 276, 295, 310, 303, 294, 293],
	'oceania' : [12, 15, 19, 22, 26, 31, 36, 39],
}

fig, ax = plt.subplots()
ax.stackplot(year, population_by_continent.values(),
			 labels=population_by_continent.keys(), alpha=0.8)
ax.legend(loc='upper left')
ax.set_title('World population')
ax.set_xlabel('Year')
ax.set_ylabel('Number of people (millions)')

plt.show()

and rewrite it with MatChart:

from matchart import plot

# data from United Nations World Population Prospects (Revision 2019)
# https://population.un.org/wpp/, license: CC BY 3.0 IGO
year = [1950, 1960, 1970, 1980, 1990, 2000, 2010, 2018]
population_by_continent = {
	'africa'  : [228, 284, 365, 477, 631, 814, 1044, 1275],
	'americas': [340, 425, 519, 619, 727, 840, 943, 1006],
	'asia'    : [1394, 1686, 2120, 2625, 3202, 3714, 4169, 4560],
	'europe'  : [220, 253, 276, 295, 310, 303, 294, 293],
	'oceania' : [12, 15, 19, 22, 26, 31, 36, 39],
}

plot([year, population_by_continent.values()],
	 kind='stackplot',
	 labels=population_by_continent.keys(),
	 alpha=0.8,
	 legend=True,
	 legend_kwargs=dict(loc='upper left'),
	 limit=False,
	 title='World population',
	 xlabel='Year',
	 ylabel='Number of people (millions)')

Note that default figure size and theme differ.

Customization of plots

Let's take FiveThirtyEight style sheet example above and customize it before showing.

Imagine now we want to remove X and Y axes.

Straightforward solution (not bad)

To do the trick we can:

  1. only draw plot with show=False;
  2. customize figure with matplotlib stuff;
  3. show plot with matplotlib.pyplot.show().
from matchart import plot
import numpy as np
from matplotlib import pyplot as plt

x = np.linspace(0, 10)
np.random.seed(19680801)  # Fixing random state for reproducibility

fig, ax, arts = plot(
		[x, np.sin(x) + x + np.random.randn(50)],
		[x, np.sin(x) + 0.5 * x + np.random.randn(50)],
		[x, np.sin(x) + 2 * x + np.random.randn(50)],
		[x, np.sin(x) - 0.5 * x + np.random.randn(50)],
		[x, np.sin(x) - 2 * x + np.random.randn(50)],
		[x, np.sin(x) + np.random.randn(50)],
		title="'fivethirtyeight' style sheet",
		theme='fivethirtyeight',
		show=False)
ax.xaxis.set_visible(False)
ax.yaxis.set_visible(False)
plt.show()

Clever solution (better)

To solve such kind of problems there is context manager support:

  1. draw plot with context=True;
  2. customize figure with matplotlib stuff within context manager.
from matchart import plot
import numpy as np

x = np.linspace(0, 10)
np.random.seed(19680801)  # Fixing random state for reproducibility

with plot(
		[x, np.sin(x) + x + np.random.randn(50)],
		[x, np.sin(x) + 0.5 * x + np.random.randn(50)],
		[x, np.sin(x) + 2 * x + np.random.randn(50)],
		[x, np.sin(x) - 0.5 * x + np.random.randn(50)],
		[x, np.sin(x) - 2 * x + np.random.randn(50)],
		[x, np.sin(x) + np.random.randn(50)],
		title="'fivethirtyeight' style sheet",
		theme='fivethirtyeight',
		context=True) as results:
	ax = results[1]
	ax.xaxis.set_visible(False)
	ax.yaxis.set_visible(False)

The best solution

Specially for lazy people there is special alias to be used within context manager:

  1. draw plot with matchart.cplot();
  2. customize figure with matplotlib stuff within context manager.
from matchart import cplot
import numpy as np

x = np.linspace(0, 10)
np.random.seed(19680801)  # Fixing random state for reproducibility

with cplot(
		[x, np.sin(x) + x + np.random.randn(50)],
		[x, np.sin(x) + 0.5 * x + np.random.randn(50)],
		[x, np.sin(x) + 2 * x + np.random.randn(50)],
		[x, np.sin(x) - 0.5 * x + np.random.randn(50)],
		[x, np.sin(x) - 2 * x + np.random.randn(50)],
		[x, np.sin(x) + np.random.randn(50)],
		title="'fivethirtyeight' style sheet",
		theme='fivethirtyeight') as plotter:
	plotter.axis.xaxis.set_visible(False)
	plotter.axis.yaxis.set_visible(False)

Now you can customize plots just adding literally one letter.

Changelog

1.1.5:

  • Add getters to context plotter.

1.1.4:

  • Add ticks control parameters.
  • Add automatic cleanup on any error (parameter clear_on_error).

1.1.3:

  • Add context parameter and alias matchart.cplot(...) to delay plot showing within context manager.
  • Add block parameter of matplotlib's show function.
  • Small enhancements and bugs fixes.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

matchart-1.1.5.tar.gz (414.2 kB view details)

Uploaded Source

Built Distribution

matchart-1.1.5-py3-none-any.whl (7.2 kB view details)

Uploaded Python 3

File details

Details for the file matchart-1.1.5.tar.gz.

File metadata

  • Download URL: matchart-1.1.5.tar.gz
  • Upload date:
  • Size: 414.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: python-requests/2.31.0

File hashes

Hashes for matchart-1.1.5.tar.gz
Algorithm Hash digest
SHA256 094f7558ada87d784f705e28dc09cb6e34a49e6502d4428c1bc3951e15c7d8aa
MD5 cd87128fad327dfd0753bd7bec9b0bbe
BLAKE2b-256 63183e9aa3993e88793576043ce2cb8afa21cc8df39b29a2edad2ee1045519eb

See more details on using hashes here.

File details

Details for the file matchart-1.1.5-py3-none-any.whl.

File metadata

  • Download URL: matchart-1.1.5-py3-none-any.whl
  • Upload date:
  • Size: 7.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: python-requests/2.31.0

File hashes

Hashes for matchart-1.1.5-py3-none-any.whl
Algorithm Hash digest
SHA256 d521ab4573deb90b4ab84b5ee806d194825d49845c688c603ebf6df3b114eb6c
MD5 9f3ddedab65a1a7670f9c77ec9f5f0bc
BLAKE2b-256 5f523bc5831d5b0f164316363bf7f42fb02e8972da1554d0358d0c9d0fe7b178

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page