Source code for postreise.plot.plot_tornado

import matplotlib.pyplot as plt
import pandas as pd


[docs]def plot_tornado(title, data, sorted=False, plot_show=True): """Plots a tornado graph (horizontal bar with both positive and neg values) :param str title: title of the plot :param dict data: dictionary of data to be plotted :param bool sorted: whether the values should be sorted smallest to largest :param bool plot_show: show the plot or not, default to True. :return: (*matplotlib.axes.Axes*) -- axes object of the plot. :raises TypeError: if ``title`` is not a str. if ``data`` is not a dict, keys are not str and values are not int or float. if ``sorted`` is not a bool. if ``plot_show`` is not a bool. """ if not isinstance(title, str): raise TypeError("title must be a str") if not isinstance(data, dict): raise TypeError("data must be a dict") if not all(isinstance(k, str) for k in data): raise TypeError("all keys of data must be str") if not all(isinstance(v, (int, float)) for v in data.values()): raise TypeError("all values of data must be int or float") if not isinstance(sorted, bool): raise TypeError("sorted must be a bool") if not isinstance(plot_show, bool): raise TypeError("plot_show must be a bool") df = pd.Series(data).to_frame() if sorted is True: df = df.sort_values(by=0, ascending=True) # Horizontal bar charts start at the bottom # so we reverse the row order before plotting df = df.iloc[::-1] ax = df.plot.barh(figsize=(10, len(df.index) * 0.4), legend=False) ax.set_title(title, fontsize=18) ax.spines["left"].set_visible(False) ax.spines["right"].set_visible(False) ax.spines["top"].set_visible(False) ax.spines["bottom"].set_visible(False) ax.set_xticks([]) ax.set_yticks([]) ax.axvline(x=0, color="black", lw=0.8) for (p, resource) in zip(ax.patches, list(df.index)): b = p.get_bbox() x_pos = b.x1 if b.x1 >= 0 else b.x0 val = "%.2e" % b.x1 ax.annotate( f" {resource}: {val} ", (x_pos, b.y1), fontsize=12, verticalalignment="top" ) if plot_show: plt.show() return ax