{"id":895,"date":"2024-12-31T07:03:38","date_gmt":"2024-12-31T07:03:38","guid":{"rendered":"https:\/\/mailitics.com\/index.php\/2024\/12\/31\/from-default-python-line-chart-to-journal-quality-infographics-80e3949eacc3\/"},"modified":"2024-12-31T07:03:38","modified_gmt":"2024-12-31T07:03:38","slug":"from-default-python-line-chart-to-journal-quality-infographics-80e3949eacc3","status":"publish","type":"post","link":"https:\/\/mailitics.com\/index.php\/2024\/12\/31\/from-default-python-line-chart-to-journal-quality-infographics-80e3949eacc3\/","title":{"rendered":"From Default Python Line Chart to Journal-Quality Infographics"},"content":{"rendered":"<p>    From Default Python Line Chart to Journal-Quality Infographics<br \/>\n \t<BR><br \/>\n<BR><\/BR><br \/>\n    <!-- no image --><br \/>\n \t<BR><br \/>\n<BR><\/BR><\/p>\n<div>\n<h4>Transform boring default Matplotlib line charts into stunning, customized visualizations<\/h4>\n<figure><img data-recalc-dims=\"1\" decoding=\"async\" alt=\"\" src=\"https:\/\/i0.wp.com\/cdn-images-1.medium.com\/max\/1024\/1%2Ab1LDteFrK29Fj3Tkd2R2lw.png?ssl=1\"><figcaption>Cover, image by the\u00a0Author<\/figcaption><\/figure>\n<p>Everyone who has used Matplotlib knows how ugly the default charts look like. In this series of posts, I\u2019ll share some tricks to make your visualizations stand out and reflect your individual style.<\/p>\n<p>We\u2019ll start with a simple line chart, which is widely used. The main highlight will be adding a gradient fill below the plot\u200a\u2014\u200aa task that\u2019s not entirely straightforward.<\/p>\n<p>So, let\u2019s dive in and walk through all the key steps of this transformation!<\/p>\n<p>Let\u2019s make all the necessary imports\u00a0first.<\/p>\n<pre>import pandas as pd<br>import numpy as np<br>import matplotlib.dates as mdates<br>import matplotlib.pyplot as plt<br>import matplotlib.ticker as ticker<br>from matplotlib import rcParams<br>from matplotlib.path import Path<br>from matplotlib.patches import PathPatch<br><br>np.random.seed(38)<\/pre>\n<p>Now we need to generate sample data for our visualization. We will create something similar to what stock prices look\u00a0like.<\/p>\n<pre>dates = pd.date_range(start='2024-02-01', periods=100, freq='D')<br>initial_rate = 75<br>drift = 0.003<br>volatility = 0.1<br>returns = np.random.normal(drift, volatility, len(dates))<br>rates = initial_rate * np.cumprod(1 + returns)<br><br>x, y = dates, rates<\/pre>\n<p>Let\u2019s check how it looks with the default Matplotlib settings.<\/p>\n<pre>fix, ax = plt.subplots(figsize=(8, 4))<br>ax.plot(dates, rates)<br>ax.xaxis.set_major_locator(mdates.DayLocator(interval=30))<br>plt.show()<\/pre>\n<figure><img data-recalc-dims=\"1\" decoding=\"async\" alt=\"\" src=\"https:\/\/i0.wp.com\/cdn-images-1.medium.com\/max\/1024\/1%2AAf_F_NsipiSVLqpyEJyodQ.png?ssl=1\"><figcaption>Default plot, image by\u00a0Author<\/figcaption><\/figure>\n<p>Not really fascination, right? But we will gradually make it looking\u00a0better.<\/p>\n<ul>\n<li>set the\u00a0title<\/li>\n<li>set general chart parameters\u200a\u2014\u200asize and\u00a0font<\/li>\n<li>placing the Y ticks to the\u00a0right<\/li>\n<li>changing the main line color, style and\u00a0width<\/li>\n<\/ul>\n<pre># General parameters<br>fig, ax = plt.subplots(figsize=(10, 6))<br>plt.title(\"Daily visitors\", fontsize=18, color=\"black\")<br>rcParams['font.family'] = 'DejaVu Sans'<br>rcParams['font.size'] = 14<br><br># Axis Y to the right<br>ax.yaxis.tick_right()<br>ax.yaxis.set_label_position(\"right\")<br><br># Plotting main line<br>ax.plot(dates, rates, color='#268358', linewidth=2)<\/pre>\n<figure><img data-recalc-dims=\"1\" decoding=\"async\" alt=\"\" src=\"https:\/\/i0.wp.com\/cdn-images-1.medium.com\/max\/1024\/1%2AS5LOXKOeA-LfEN8xbV2n3Q.png?ssl=1\"><figcaption>General params applied, image by\u00a0Author<\/figcaption><\/figure>\n<p>Alright, now it looks a bit\u00a0cleaner.<\/p>\n<p>Now we\u2019d like to add minimalistic grid to the background, remove borders for a cleaner look and remove ticks from the Y\u00a0axis.<\/p>\n<pre># Grid<br>ax.grid(color=\"gray\", linestyle=(0, (10, 10)), linewidth=0.5, alpha=0.6)<br>ax.tick_params(axis=\"x\", colors=\"black\")<br>ax.tick_params(axis=\"y\", left=False, labelleft=False) <br><br># Borders<br>ax.spines[\"top\"].set_visible(False)<br>ax.spines['right'].set_visible(False)<br>ax.spines[\"bottom\"].set_color(\"black\")<br>ax.spines['left'].set_color('white')<br>ax.spines['left'].set_linewidth(1)<br><br># Remove ticks from axis Y<br>ax.tick_params(axis='y', length=0)<\/pre>\n<figure><img data-recalc-dims=\"1\" decoding=\"async\" alt=\"\" src=\"https:\/\/i0.wp.com\/cdn-images-1.medium.com\/max\/1024\/1%2AM0apu5LOjWDzLjuL5uWIdw.png?ssl=1\"><figcaption>Grid added, image by\u00a0Author<\/figcaption><\/figure>\n<p>Now we\u2019re adding a tine esthetic detail\u200a\u2014\u200ayear near the first tick on the axis X. Also we make the font color of tick labels more\u00a0pale.<\/p>\n<pre># Add year to the first date on the axis<br>def custom_date_formatter(t, pos, dates, x_interval):<br>    date = dates[pos*x_interval]<br>    if pos == 0:<br>        return date.strftime('%d %b '%y')  <br>    else:<br>        return date.strftime('%d %b')  <br>ax.xaxis.set_major_formatter(ticker.FuncFormatter((lambda x, pos: custom_date_formatter(x, pos, dates=dates, x_interval=x_interval))))<br><br># Ticks label color<br>[t.set_color('#808079') for t in ax.yaxis.get_ticklabels()]<br>[t.set_color('#808079') for t in ax.xaxis.get_ticklabels()]<\/pre>\n<figure><img data-recalc-dims=\"1\" decoding=\"async\" alt=\"\" src=\"https:\/\/i0.wp.com\/cdn-images-1.medium.com\/max\/1024\/1%2APM1epwg4DwGv81tQ8nt7EQ.png?ssl=1\"><figcaption>Year near first date, image by\u00a0Author<\/figcaption><\/figure>\n<p>And we\u2019re getting closer to the trickiest moment\u200a\u2014\u200ahow to create a gradient under the curve. Actually there is no such option in Matplotlib, but we can simulate it creating a gradient image and then clipping it with the\u00a0chart.<\/p>\n<pre># Gradient<br>numeric_x = np.array([i for i in range(len(x))])<br>numeric_x_patch = np.append(numeric_x, max(numeric_x))<br>numeric_x_patch = np.append(numeric_x_patch[0], numeric_x_patch)<br>y_patch = np.append(y, 0)<br>y_patch = np.append(0, y_patch)<br><br>path = Path(np.array([numeric_x_patch, y_patch]).transpose())<br>patch = PathPatch(path, facecolor='none')<br>plt.gca().add_patch(patch)<br><br>ax.imshow(numeric_x.reshape(len(numeric_x), 1),  interpolation=\"bicubic\",<br>                cmap=plt.cm.Greens, <br>                origin='lower',<br>                alpha=0.3,<br>                extent=[min(numeric_x), max(numeric_x), min(y_patch), max(y_patch) * 1.2], <br>                aspect=\"auto\", clip_path=patch, clip_on=True)<\/pre>\n<figure><img data-recalc-dims=\"1\" decoding=\"async\" alt=\"\" src=\"https:\/\/i0.wp.com\/cdn-images-1.medium.com\/max\/1024\/1%2AQrjIGpczNZkVuuNyjef3yw.png?ssl=1\"><figcaption>Gradient added, image by\u00a0Author<\/figcaption><\/figure>\n<p>Now it looks clean and nice. We just need to add several details using any editor (I prefer Google Slides)\u200a\u2014\u200atitle, round border corners and some numeric indicators.<\/p>\n<figure><img data-recalc-dims=\"1\" decoding=\"async\" alt=\"\" src=\"https:\/\/i0.wp.com\/cdn-images-1.medium.com\/max\/1024\/1%2AcYpYFPFAHJmjfuBpJ2XVag.png?ssl=1\"><figcaption>Final visualization, image by\u00a0Author<\/figcaption><\/figure>\n<p>The full code to reproduce the visualization is\u00a0below:<\/p>\n<p><iframe loading=\"lazy\" src=\"\" width=\"0\" height=\"0\" frameborder=\"0\" scrolling=\"no\"><a href=\"https:\/\/medium.com\/media\/6986ff9cd74116aad0f10458818cfd42\/href\">https:\/\/medium.com\/media\/6986ff9cd74116aad0f10458818cfd42\/href<\/a><\/iframe><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/medium.com\/_\/stat?event=post.clientViewed&amp;referrerSource=full_rss&amp;postId=80e3949eacc3\" width=\"1\" height=\"1\" alt=\"\"><\/p>\n<hr>\n<p><a href=\"https:\/\/towardsdatascience.com\/from-default-python-line-chart-to-journal-quality-infographics-80e3949eacc3\">From Default Python Line Chart to Journal-Quality Infographics<\/a> was originally published in <a href=\"https:\/\/towardsdatascience.com\/\">Towards Data Science<\/a> on Medium, where people are continuing the conversation by highlighting and responding to this story.<\/p>\n<\/div>\n<p> \t<BR><br \/>\n <BR><\/BR><br \/>\n    Vladimir Zhyvov<br \/>\n \t<BR><br \/>\n<BR><\/BR><br \/>\n<a href=\"https:\/\/medium.com\/m\/global-identity-2?redirectUrl=https%3A%2F%2Ftowardsdatascience.com%2Ffrom-default-python-line-chart-to-journal-quality-infographics-80e3949eacc3\">Go to original source<\/a><br \/>\n \t<BR><br \/>\n <BR><\/BR><\/p>\n","protected":false},"excerpt":{"rendered":"<p>From Default Python Line Chart to Journal-Quality Infographics Transform boring default Matplotlib line charts into stunning, customized visualizations Cover, image by the\u00a0Author Everyone who has used Matplotlib knows how ugly the default charts look like. In this series of posts, I\u2019ll share some tricks to make your visualizations stand out and reflect your individual style. [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[62,1037,1034,1038,1036,1035],"tags":[1039,1040,883],"class_list":["post-895","post","type-post","status-publish","format-standard","hentry","category-aimldsaimlds","category-analytics","category-charts","category-infographics","category-matplotlib","category-visualization","tag-ax","tag-matplotlib","tag-set"],"_links":{"self":[{"href":"https:\/\/mailitics.com\/index.php\/wp-json\/wp\/v2\/posts\/895"}],"collection":[{"href":"https:\/\/mailitics.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mailitics.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mailitics.com\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/mailitics.com\/index.php\/wp-json\/wp\/v2\/comments?post=895"}],"version-history":[{"count":0,"href":"https:\/\/mailitics.com\/index.php\/wp-json\/wp\/v2\/posts\/895\/revisions"}],"wp:attachment":[{"href":"https:\/\/mailitics.com\/index.php\/wp-json\/wp\/v2\/media?parent=895"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mailitics.com\/index.php\/wp-json\/wp\/v2\/categories?post=895"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mailitics.com\/index.php\/wp-json\/wp\/v2\/tags?post=895"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}