Hi, and welcome to this tutorial, where I’ll teach you to create a country ranking chart using Python and Matplotlib.
What I like about this visualization is its clean and beautiful way of showing how countries rank compared to each other on a particular metric.
The alternative to using a standard line chart showing the actual values get messy if some countries are close to each other or if some countries outperform others by a lot.
If you want access to the code for this tutorial, you can find it in this GitHub repository.
If you enjoy this tutorial, make sure to check out my other accounts.
- Data Wonder on Substack
- oscarl3o on Twitter
- oscarleo on Medium
Let’s get started.
About the data
I’ve created a simple CSV containing GDP values for today’s ten largest economies for this tutorial.
The data comes from the World Bank, and the full name of the indicator is “GDP (constant 2015 us$)”.
If you want to know more about different ways of measuring GDP, you can look at this Medium story, where I use the same type of data visualization.
Let’s get on with the tutorial.
Step 1: Creating rankings
Step one is to rank the countries for each year in the dataset, which is easy to do with pandas.
<span>def</span> <span>create_rankings</span><span>(</span><span>df</span><span>,</span> <span>columns</span><span>):</span><span>rank_columns</span> <span>=</span> <span>[</span><span>"</span><span>rank_{}</span><span>"</span><span>.</span><span>format</span><span>(</span><span>i</span><span>)</span> <span>for</span> <span>i</span> <span>in</span> <span>range</span><span>(</span><span>len</span><span>(</span><span>columns</span><span>))]</span><span>for</span> <span>i</span><span>,</span> <span>column</span> <span>in</span> <span>enumerate</span><span>(</span><span>columns</span><span>):</span><span>df</span><span>[</span><span>rank_columns</span><span>[</span><span>i</span><span>]]</span> <span>=</span> <span>df</span><span>[</span><span>column</span><span>].</span><span>rank</span><span>(</span><span>ascending</span><span>=</span><span>False</span><span>)</span><span>return</span> <span>df</span><span>,</span> <span>rank_columns</span><span>def</span> <span>create_rankings</span><span>(</span><span>df</span><span>,</span> <span>columns</span><span>):</span> <span>rank_columns</span> <span>=</span> <span>[</span><span>"</span><span>rank_{}</span><span>"</span><span>.</span><span>format</span><span>(</span><span>i</span><span>)</span> <span>for</span> <span>i</span> <span>in</span> <span>range</span><span>(</span><span>len</span><span>(</span><span>columns</span><span>))]</span> <span>for</span> <span>i</span><span>,</span> <span>column</span> <span>in</span> <span>enumerate</span><span>(</span><span>columns</span><span>):</span> <span>df</span><span>[</span><span>rank_columns</span><span>[</span><span>i</span><span>]]</span> <span>=</span> <span>df</span><span>[</span><span>column</span><span>].</span><span>rank</span><span>(</span><span>ascending</span><span>=</span><span>False</span><span>)</span> <span>return</span> <span>df</span><span>,</span> <span>rank_columns</span>def create_rankings(df, columns): rank_columns = ["rank_{}".format(i) for i in range(len(columns))] for i, column in enumerate(columns): df[rank_columns[i]] = df[column].rank(ascending=False) return df, rank_columns
Enter fullscreen mode Exit fullscreen mode
The resulting columns look like this.
That’s all the preprocessing we need to continue with the data visualization.
Step 2: Creating and styling a grid
Now that we have prepared our data, it’s time to create a grid where we can draw our lines and flags.
Here’s a function using Seaborn that creates the overall style. It defines things like the background color and font family. I’m also removing spines and ticks.
<span>def</span> <span>set_style</span><span>(</span><span>font_family</span><span>,</span> <span>background_color</span><span>,</span> <span>grid_color</span><span>,</span> <span>text_color</span><span>):</span><span>sns</span><span>.</span><span>set_style</span><span>({</span><span>"</span><span>axes.facecolor</span><span>"</span><span>:</span> <span>background_color</span><span>,</span><span>"</span><span>figure.facecolor</span><span>"</span><span>:</span> <span>background_color</span><span>,</span><span>"</span><span>axes.grid</span><span>"</span><span>:</span> <span>True</span><span>,</span><span>"</span><span>axes.axisbelow</span><span>"</span><span>:</span> <span>True</span><span>,</span><span>"</span><span>grid.color</span><span>"</span><span>:</span> <span>grid_color</span><span>,</span><span>"</span><span>text.color</span><span>"</span><span>:</span> <span>text_color</span><span>,</span><span>"</span><span>font.family</span><span>"</span><span>:</span> <span>font_family</span><span>,</span><span>"</span><span>xtick.bottom</span><span>"</span><span>:</span> <span>False</span><span>,</span><span>"</span><span>xtick.top</span><span>"</span><span>:</span> <span>False</span><span>,</span><span>"</span><span>ytick.left</span><span>"</span><span>:</span> <span>False</span><span>,</span><span>"</span><span>ytick.right</span><span>"</span><span>:</span> <span>False</span><span>,</span><span>"</span><span>axes.spines.left</span><span>"</span><span>:</span> <span>False</span><span>,</span><span>"</span><span>axes.spines.bottom</span><span>"</span><span>:</span> <span>False</span><span>,</span><span>"</span><span>axes.spines.right</span><span>"</span><span>:</span> <span>False</span><span>,</span><span>"</span><span>axes.spines.top</span><span>"</span><span>:</span> <span>False</span><span>,</span><span>}</span><span>)</span><span>def</span> <span>set_style</span><span>(</span><span>font_family</span><span>,</span> <span>background_color</span><span>,</span> <span>grid_color</span><span>,</span> <span>text_color</span><span>):</span> <span>sns</span><span>.</span><span>set_style</span><span>({</span> <span>"</span><span>axes.facecolor</span><span>"</span><span>:</span> <span>background_color</span><span>,</span> <span>"</span><span>figure.facecolor</span><span>"</span><span>:</span> <span>background_color</span><span>,</span> <span>"</span><span>axes.grid</span><span>"</span><span>:</span> <span>True</span><span>,</span> <span>"</span><span>axes.axisbelow</span><span>"</span><span>:</span> <span>True</span><span>,</span> <span>"</span><span>grid.color</span><span>"</span><span>:</span> <span>grid_color</span><span>,</span> <span>"</span><span>text.color</span><span>"</span><span>:</span> <span>text_color</span><span>,</span> <span>"</span><span>font.family</span><span>"</span><span>:</span> <span>font_family</span><span>,</span> <span>"</span><span>xtick.bottom</span><span>"</span><span>:</span> <span>False</span><span>,</span> <span>"</span><span>xtick.top</span><span>"</span><span>:</span> <span>False</span><span>,</span> <span>"</span><span>ytick.left</span><span>"</span><span>:</span> <span>False</span><span>,</span> <span>"</span><span>ytick.right</span><span>"</span><span>:</span> <span>False</span><span>,</span> <span>"</span><span>axes.spines.left</span><span>"</span><span>:</span> <span>False</span><span>,</span> <span>"</span><span>axes.spines.bottom</span><span>"</span><span>:</span> <span>False</span><span>,</span> <span>"</span><span>axes.spines.right</span><span>"</span><span>:</span> <span>False</span><span>,</span> <span>"</span><span>axes.spines.top</span><span>"</span><span>:</span> <span>False</span><span>,</span> <span>}</span> <span>)</span>def set_style(font_family, background_color, grid_color, text_color): sns.set_style({ "axes.facecolor": background_color, "figure.facecolor": background_color, "axes.grid": True, "axes.axisbelow": True, "grid.color": grid_color, "text.color": text_color, "font.family": font_family, "xtick.bottom": False, "xtick.top": False, "ytick.left": False, "ytick.right": False, "axes.spines.left": False, "axes.spines.bottom": False, "axes.spines.right": False, "axes.spines.top": False, } )
Enter fullscreen mode Exit fullscreen mode
I run the function with the following values.
<span>font_family</span> <span>=</span> <span>"</span><span>PT Mono</span><span>"</span><span>background_color</span> <span>=</span> <span>"</span><span>#FAF0F1</span><span>"</span><span>text_color</span> <span>=</span> <span>"</span><span>#080520</span><span>"</span><span>grid_color</span> <span>=</span> <span>"</span><span>#E4C9C9</span><span>"</span><span>set_style</span><span>(</span><span>font_family</span><span>,</span> <span>background_color</span><span>,</span> <span>grid_color</span><span>,</span> <span>text_color</span><span>)</span><span>font_family</span> <span>=</span> <span>"</span><span>PT Mono</span><span>"</span> <span>background_color</span> <span>=</span> <span>"</span><span>#FAF0F1</span><span>"</span> <span>text_color</span> <span>=</span> <span>"</span><span>#080520</span><span>"</span> <span>grid_color</span> <span>=</span> <span>"</span><span>#E4C9C9</span><span>"</span> <span>set_style</span><span>(</span><span>font_family</span><span>,</span> <span>background_color</span><span>,</span> <span>grid_color</span><span>,</span> <span>text_color</span><span>)</span>font_family = "PT Mono" background_color = "#FAF0F1" text_color = "#080520" grid_color = "#E4C9C9" set_style(font_family, background_color, grid_color, text_color)
Enter fullscreen mode Exit fullscreen mode
To create the actual grid, I have a function that formats the y- and x-axis. It takes a few parameters that allow me to try different setups, such as the size of the labels.
<span>def</span> <span>format_ticks</span><span>(</span><span>ax</span><span>,</span> <span>years</span><span>,</span> <span>padx</span><span>=</span><span>0.25</span><span>,</span> <span>pady</span><span>=</span><span>0.5</span><span>,</span> <span>y_label_size</span><span>=</span><span>20</span><span>,</span> <span>x_label_size</span><span>=</span><span>24</span><span>):</span><span>ax</span><span>.</span><span>set</span><span>(</span><span>xlim</span><span>=</span><span>(</span><span>-</span><span>padx</span><span>,</span> <span>len</span><span>(</span><span>years</span><span>)</span> <span>-</span><span>1</span> <span>+</span> <span>padx</span><span>),</span> <span>ylim</span><span>=</span><span>(</span><span>-</span><span>len</span><span>(</span><span>df</span><span>)</span> <span>-</span> <span>pady</span><span>,</span> <span>-</span> <span>pady</span><span>))</span><span>xticks</span> <span>=</span> <span>[</span><span>i</span> <span>for</span> <span>i</span> <span>in</span> <span>range</span><span>(</span><span>len</span><span>(</span><span>years</span><span>))]</span><span>ax</span><span>.</span><span>set_xticks</span><span>(</span><span>ticks</span><span>=</span><span>xticks</span><span>,</span> <span>labels</span><span>=</span><span>years</span><span>)</span><span>yticks</span> <span>=</span> <span>[</span><span>-</span><span>i</span> <span>for</span> <span>i</span> <span>in</span> <span>range</span><span>(</span><span>1</span><span>,</span> <span>len</span><span>(</span><span>df</span><span>)</span> <span>+</span> <span>1</span><span>)]</span><span>ylabels</span> <span>=</span> <span>[</span><span>"</span><span>{}</span><span>"</span><span>.</span><span>format</span><span>(</span><span>i</span><span>)</span> <span>for</span> <span>i</span> <span>in</span> <span>range</span><span>(</span><span>1</span><span>,</span> <span>len</span><span>(</span><span>df</span><span>)</span> <span>+</span> <span>1</span><span>)]</span><span>ax</span><span>.</span><span>set_yticks</span><span>(</span><span>ticks</span><span>=</span><span>yticks</span><span>,</span> <span>labels</span><span>=</span><span>ylabels</span><span>)</span><span>ax</span><span>.</span><span>tick_params</span><span>(</span><span>"</span><span>y</span><span>"</span><span>,</span><span>labelsize</span><span>=</span><span>y_label_size</span><span>,</span> <span>pad</span><span>=</span><span>16</span><span>)</span><span>ax</span><span>.</span><span>tick_params</span><span>(</span><span>"</span><span>x</span><span>"</span><span>,</span> <span>labeltop</span><span>=</span><span>True</span><span>,</span> <span>labelsize</span><span>=</span><span>x_label_size</span><span>,</span> <span>pad</span><span>=</span><span>8</span><span>)</span><span>def</span> <span>format_ticks</span><span>(</span><span>ax</span><span>,</span> <span>years</span><span>,</span> <span>padx</span><span>=</span><span>0.25</span><span>,</span> <span>pady</span><span>=</span><span>0.5</span><span>,</span> <span>y_label_size</span><span>=</span><span>20</span><span>,</span> <span>x_label_size</span><span>=</span><span>24</span><span>):</span> <span>ax</span><span>.</span><span>set</span><span>(</span><span>xlim</span><span>=</span><span>(</span><span>-</span><span>padx</span><span>,</span> <span>len</span><span>(</span><span>years</span><span>)</span> <span>-</span><span>1</span> <span>+</span> <span>padx</span><span>),</span> <span>ylim</span><span>=</span><span>(</span><span>-</span><span>len</span><span>(</span><span>df</span><span>)</span> <span>-</span> <span>pady</span><span>,</span> <span>-</span> <span>pady</span><span>))</span> <span>xticks</span> <span>=</span> <span>[</span><span>i</span> <span>for</span> <span>i</span> <span>in</span> <span>range</span><span>(</span><span>len</span><span>(</span><span>years</span><span>))]</span> <span>ax</span><span>.</span><span>set_xticks</span><span>(</span><span>ticks</span><span>=</span><span>xticks</span><span>,</span> <span>labels</span><span>=</span><span>years</span><span>)</span> <span>yticks</span> <span>=</span> <span>[</span><span>-</span><span>i</span> <span>for</span> <span>i</span> <span>in</span> <span>range</span><span>(</span><span>1</span><span>,</span> <span>len</span><span>(</span><span>df</span><span>)</span> <span>+</span> <span>1</span><span>)]</span> <span>ylabels</span> <span>=</span> <span>[</span><span>"</span><span>{}</span><span>"</span><span>.</span><span>format</span><span>(</span><span>i</span><span>)</span> <span>for</span> <span>i</span> <span>in</span> <span>range</span><span>(</span><span>1</span><span>,</span> <span>len</span><span>(</span><span>df</span><span>)</span> <span>+</span> <span>1</span><span>)]</span> <span>ax</span><span>.</span><span>set_yticks</span><span>(</span><span>ticks</span><span>=</span><span>yticks</span><span>,</span> <span>labels</span><span>=</span><span>ylabels</span><span>)</span> <span>ax</span><span>.</span><span>tick_params</span><span>(</span><span>"</span><span>y</span><span>"</span><span>,</span><span>labelsize</span><span>=</span><span>y_label_size</span><span>,</span> <span>pad</span><span>=</span><span>16</span><span>)</span> <span>ax</span><span>.</span><span>tick_params</span><span>(</span><span>"</span><span>x</span><span>"</span><span>,</span> <span>labeltop</span><span>=</span><span>True</span><span>,</span> <span>labelsize</span><span>=</span><span>x_label_size</span><span>,</span> <span>pad</span><span>=</span><span>8</span><span>)</span>def format_ticks(ax, years, padx=0.25, pady=0.5, y_label_size=20, x_label_size=24): ax.set(xlim=(-padx, len(years) -1 + padx), ylim=(-len(df) - pady, - pady)) xticks = [i for i in range(len(years))] ax.set_xticks(ticks=xticks, labels=years) yticks = [-i for i in range(1, len(df) + 1)] ylabels = ["{}".format(i) for i in range(1, len(df) + 1)] ax.set_yticks(ticks=yticks, labels=ylabels) ax.tick_params("y",labelsize=y_label_size, pad=16) ax.tick_params("x", labeltop=True, labelsize=x_label_size, pad=8)
Enter fullscreen mode Exit fullscreen mode
Here’s what it looks like when I run everything we have so far.
<span># Load data </span><span>years</span> <span>=</span> <span>[</span><span>"</span><span>2000</span><span>"</span><span>,</span> <span>"</span><span>2005</span><span>"</span><span>,</span> <span>"</span><span>2010</span><span>"</span><span>,</span> <span>"</span><span>2015</span><span>"</span><span>,</span> <span>"</span><span>2020</span><span>"</span><span>,</span> <span>"</span><span>2022</span><span>"</span><span>]</span><span>df</span> <span>=</span> <span>pd</span><span>.</span><span>read_csv</span><span>(</span><span>"</span><span>rankings.csv</span><span>"</span><span>,</span> <span>index_col</span><span>=</span><span>None</span><span>)</span><span>df</span><span>,</span> <span>rank_columns</span> <span>=</span> <span>create_rankings</span><span>(</span><span>df</span><span>,</span> <span>years</span><span>)</span><span># Create chart </span><span>fig</span><span>,</span> <span>ax</span> <span>=</span> <span>plt</span><span>.</span><span>subplots</span><span>(</span><span>nrows</span><span>=</span><span>1</span><span>,</span> <span>ncols</span><span>=</span><span>1</span><span>,</span> <span>figsize</span><span>=</span><span>(</span><span>15</span><span>,</span> <span>1.6</span><span>*</span><span>len</span><span>(</span><span>df</span><span>)))</span><span>format_ticks</span><span>(</span><span>ax</span><span>,</span> <span>years</span><span>)</span><span># Load data </span><span>years</span> <span>=</span> <span>[</span><span>"</span><span>2000</span><span>"</span><span>,</span> <span>"</span><span>2005</span><span>"</span><span>,</span> <span>"</span><span>2010</span><span>"</span><span>,</span> <span>"</span><span>2015</span><span>"</span><span>,</span> <span>"</span><span>2020</span><span>"</span><span>,</span> <span>"</span><span>2022</span><span>"</span><span>]</span> <span>df</span> <span>=</span> <span>pd</span><span>.</span><span>read_csv</span><span>(</span><span>"</span><span>rankings.csv</span><span>"</span><span>,</span> <span>index_col</span><span>=</span><span>None</span><span>)</span> <span>df</span><span>,</span> <span>rank_columns</span> <span>=</span> <span>create_rankings</span><span>(</span><span>df</span><span>,</span> <span>years</span><span>)</span> <span># Create chart </span><span>fig</span><span>,</span> <span>ax</span> <span>=</span> <span>plt</span><span>.</span><span>subplots</span><span>(</span><span>nrows</span><span>=</span><span>1</span><span>,</span> <span>ncols</span><span>=</span><span>1</span><span>,</span> <span>figsize</span><span>=</span><span>(</span><span>15</span><span>,</span> <span>1.6</span><span>*</span><span>len</span><span>(</span><span>df</span><span>)))</span> <span>format_ticks</span><span>(</span><span>ax</span><span>,</span> <span>years</span><span>)</span># Load data years = ["2000", "2005", "2010", "2015", "2020", "2022"] df = pd.read_csv("rankings.csv", index_col=None) df, rank_columns = create_rankings(df, years) # Create chart fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(15, 1.6*len(df))) format_ticks(ax, years)
Enter fullscreen mode Exit fullscreen mode
And here’s the resulting grid.
Now we can start to add some data.
Step 3: Adding lines
I want a line showing each country’s rank for each year in the dataset—an easy task in Matplotlib.
<span>def</span> <span>add_line</span><span>(</span><span>ax</span><span>,</span> <span>row</span><span>,</span> <span>columns</span><span>,</span> <span>linewidth</span><span>=</span><span>3</span><span>):</span><span>x</span> <span>=</span> <span>[</span><span>i</span> <span>for</span> <span>i</span> <span>in</span> <span>range</span><span>(</span><span>len</span><span>(</span><span>columns</span><span>))]</span><span>y</span> <span>=</span> <span>[</span><span>-</span><span>row</span><span>[</span><span>rc</span><span>]</span> <span>for</span> <span>rc</span> <span>in</span> <span>columns</span><span>]</span><span>ax</span><span>.</span><span>add_artist</span><span>(</span><span>Line2D</span><span>(</span><span>x</span><span>,</span> <span>y</span><span>,</span> <span>linewidth</span><span>=</span><span>linewidth</span><span>,</span> <span>color</span><span>=</span><span>text_color</span><span>)</span><span>)</span><span>def</span> <span>add_line</span><span>(</span><span>ax</span><span>,</span> <span>row</span><span>,</span> <span>columns</span><span>,</span> <span>linewidth</span><span>=</span><span>3</span><span>):</span> <span>x</span> <span>=</span> <span>[</span><span>i</span> <span>for</span> <span>i</span> <span>in</span> <span>range</span><span>(</span><span>len</span><span>(</span><span>columns</span><span>))]</span> <span>y</span> <span>=</span> <span>[</span><span>-</span><span>row</span><span>[</span><span>rc</span><span>]</span> <span>for</span> <span>rc</span> <span>in</span> <span>columns</span><span>]</span> <span>ax</span><span>.</span><span>add_artist</span><span>(</span> <span>Line2D</span><span>(</span><span>x</span><span>,</span> <span>y</span><span>,</span> <span>linewidth</span><span>=</span><span>linewidth</span><span>,</span> <span>color</span><span>=</span><span>text_color</span><span>)</span> <span>)</span>def add_line(ax, row, columns, linewidth=3): x = [i for i in range(len(columns))] y = [-row[rc] for rc in columns] ax.add_artist( Line2D(x, y, linewidth=linewidth, color=text_color) )
Enter fullscreen mode Exit fullscreen mode
Then I run the function for each row in the dataset like this.
<span># Load data </span><span>years</span> <span>=</span> <span>[</span><span>"</span><span>2000</span><span>"</span><span>,</span> <span>"</span><span>2005</span><span>"</span><span>,</span> <span>"</span><span>2010</span><span>"</span><span>,</span> <span>"</span><span>2015</span><span>"</span><span>,</span> <span>"</span><span>2020</span><span>"</span><span>,</span> <span>"</span><span>2022</span><span>"</span><span>]</span><span>df</span> <span>=</span> <span>pd</span><span>.</span><span>read_csv</span><span>(</span><span>"</span><span>rankings.csv</span><span>"</span><span>,</span> <span>index_col</span><span>=</span><span>None</span><span>)</span><span>df</span><span>,</span> <span>rank_columns</span> <span>=</span> <span>create_rankings</span><span>(</span><span>df</span><span>,</span> <span>years</span><span>)</span><span># Create chart </span><span>fig</span><span>,</span> <span>ax</span> <span>=</span> <span>plt</span><span>.</span><span>subplots</span><span>(</span><span>nrows</span><span>=</span><span>1</span><span>,</span> <span>ncols</span><span>=</span><span>1</span><span>,</span> <span>figsize</span><span>=</span><span>(</span><span>15</span><span>,</span> <span>1.6</span><span>*</span><span>len</span><span>(</span><span>df</span><span>)))</span><span>format_ticks</span><span>(</span><span>ax</span><span>,</span> <span>years</span><span>)</span><span># Draw lines </span><span>for</span> <span>i</span><span>,</span> <span>row</span> <span>in</span> <span>df</span><span>.</span><span>iterrows</span><span>():</span><span>add_line</span><span>(</span><span>ax</span><span>,</span> <span>row</span><span>,</span> <span>rank_columns</span><span>)</span><span># Load data </span><span>years</span> <span>=</span> <span>[</span><span>"</span><span>2000</span><span>"</span><span>,</span> <span>"</span><span>2005</span><span>"</span><span>,</span> <span>"</span><span>2010</span><span>"</span><span>,</span> <span>"</span><span>2015</span><span>"</span><span>,</span> <span>"</span><span>2020</span><span>"</span><span>,</span> <span>"</span><span>2022</span><span>"</span><span>]</span> <span>df</span> <span>=</span> <span>pd</span><span>.</span><span>read_csv</span><span>(</span><span>"</span><span>rankings.csv</span><span>"</span><span>,</span> <span>index_col</span><span>=</span><span>None</span><span>)</span> <span>df</span><span>,</span> <span>rank_columns</span> <span>=</span> <span>create_rankings</span><span>(</span><span>df</span><span>,</span> <span>years</span><span>)</span> <span># Create chart </span><span>fig</span><span>,</span> <span>ax</span> <span>=</span> <span>plt</span><span>.</span><span>subplots</span><span>(</span><span>nrows</span><span>=</span><span>1</span><span>,</span> <span>ncols</span><span>=</span><span>1</span><span>,</span> <span>figsize</span><span>=</span><span>(</span><span>15</span><span>,</span> <span>1.6</span><span>*</span><span>len</span><span>(</span><span>df</span><span>)))</span> <span>format_ticks</span><span>(</span><span>ax</span><span>,</span> <span>years</span><span>)</span> <span># Draw lines </span><span>for</span> <span>i</span><span>,</span> <span>row</span> <span>in</span> <span>df</span><span>.</span><span>iterrows</span><span>():</span> <span>add_line</span><span>(</span><span>ax</span><span>,</span> <span>row</span><span>,</span> <span>rank_columns</span><span>)</span># Load data years = ["2000", "2005", "2010", "2015", "2020", "2022"] df = pd.read_csv("rankings.csv", index_col=None) df, rank_columns = create_rankings(df, years) # Create chart fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(15, 1.6*len(df))) format_ticks(ax, years) # Draw lines for i, row in df.iterrows(): add_line(ax, row, rank_columns)
Enter fullscreen mode Exit fullscreen mode
I’m using the same color for each line because I want to use country flags to guide the eye. Using a unique color for each line makes sense, but it looks messy.
Step 4: Drawing pie charts
I want to indicate how a country’s economy grows over time without adding text. Instead, I aim to inform in a visual format.
My idea is to draw a pie chart on each point showing the size of a country’s economy compared to its best year.
I’m using PIL to create a pie chart image, but you can use Matplotlib directly. I don’t because I had some issues with aspect ratios.
<span>def</span> <span>add_pie</span><span>(</span><span>ax</span><span>,</span> <span>x</span><span>,</span> <span>y</span><span>,</span> <span>ratio</span><span>,</span> <span>size</span><span>=</span><span>572</span><span>,</span> <span>zoom</span><span>=</span><span>0.1</span><span>):</span><span>image</span> <span>=</span> <span>Image</span><span>.</span><span>new</span><span>(</span><span>'</span><span>RGBA</span><span>'</span><span>,</span> <span>(</span><span>size</span><span>,</span> <span>size</span><span>))</span><span>draw</span> <span>=</span> <span>ImageDraw</span><span>.</span><span>Draw</span><span>(</span><span>image</span><span>)</span><span>draw</span><span>.</span><span>pieslice</span><span>((</span><span>0</span><span>,</span> <span>0</span><span>,</span> <span>size</span><span>,</span> <span>size</span><span>),</span> <span>start</span><span>=-</span><span>90</span><span>,</span> <span>end</span><span>=</span><span>360</span><span>*</span><span>ratio</span><span>-</span><span>90</span><span>,</span> <span>fill</span><span>=</span><span>text_color</span><span>,</span> <span>outline</span><span>=</span><span>text_color</span><span>)</span><span>im</span> <span>=</span> <span>OffsetImage</span><span>(</span><span>image</span><span>,</span> <span>zoom</span><span>=</span><span>zoom</span><span>,</span> <span>interpolation</span><span>=</span><span>"</span><span>lanczos</span><span>"</span><span>,</span> <span>resample</span><span>=</span><span>True</span><span>,</span> <span>visible</span><span>=</span><span>True</span><span>)</span><span>ax</span><span>.</span><span>add_artist</span><span>(</span><span>AnnotationBbox</span><span>(</span><span>im</span><span>,</span> <span>(</span><span>x</span><span>,</span> <span>y</span><span>),</span> <span>frameon</span><span>=</span><span>False</span><span>,</span><span>xycoords</span><span>=</span><span>"</span><span>data</span><span>"</span><span>,</span><span>))</span><span>def</span> <span>add_pie</span><span>(</span><span>ax</span><span>,</span> <span>x</span><span>,</span> <span>y</span><span>,</span> <span>ratio</span><span>,</span> <span>size</span><span>=</span><span>572</span><span>,</span> <span>zoom</span><span>=</span><span>0.1</span><span>):</span> <span>image</span> <span>=</span> <span>Image</span><span>.</span><span>new</span><span>(</span><span>'</span><span>RGBA</span><span>'</span><span>,</span> <span>(</span><span>size</span><span>,</span> <span>size</span><span>))</span> <span>draw</span> <span>=</span> <span>ImageDraw</span><span>.</span><span>Draw</span><span>(</span><span>image</span><span>)</span> <span>draw</span><span>.</span><span>pieslice</span><span>((</span><span>0</span><span>,</span> <span>0</span><span>,</span> <span>size</span><span>,</span> <span>size</span><span>),</span> <span>start</span><span>=-</span><span>90</span><span>,</span> <span>end</span><span>=</span><span>360</span><span>*</span><span>ratio</span><span>-</span><span>90</span><span>,</span> <span>fill</span><span>=</span><span>text_color</span><span>,</span> <span>outline</span><span>=</span><span>text_color</span><span>)</span> <span>im</span> <span>=</span> <span>OffsetImage</span><span>(</span><span>image</span><span>,</span> <span>zoom</span><span>=</span><span>zoom</span><span>,</span> <span>interpolation</span><span>=</span><span>"</span><span>lanczos</span><span>"</span><span>,</span> <span>resample</span><span>=</span><span>True</span><span>,</span> <span>visible</span><span>=</span><span>True</span><span>)</span> <span>ax</span><span>.</span><span>add_artist</span><span>(</span><span>AnnotationBbox</span><span>(</span> <span>im</span><span>,</span> <span>(</span><span>x</span><span>,</span> <span>y</span><span>),</span> <span>frameon</span><span>=</span><span>False</span><span>,</span> <span>xycoords</span><span>=</span><span>"</span><span>data</span><span>"</span><span>,</span> <span>))</span>def add_pie(ax, x, y, ratio, size=572, zoom=0.1): image = Image.new('RGBA', (size, size)) draw = ImageDraw.Draw(image) draw.pieslice((0, 0, size, size), start=-90, end=360*ratio-90, fill=text_color, outline=text_color) im = OffsetImage(image, zoom=zoom, interpolation="lanczos", resample=True, visible=True) ax.add_artist(AnnotationBbox( im, (x, y), frameon=False, xycoords="data", ))
Enter fullscreen mode Exit fullscreen mode
The value for the size parameter is slightly larger than the size of my flag images which are 512×512. Later, I want to paste the flags on the pie charts.
Here’s the updated code.
<span># Load data </span><span>years</span> <span>=</span> <span>[</span><span>"</span><span>2000</span><span>"</span><span>,</span> <span>"</span><span>2005</span><span>"</span><span>,</span> <span>"</span><span>2010</span><span>"</span><span>,</span> <span>"</span><span>2015</span><span>"</span><span>,</span> <span>"</span><span>2020</span><span>"</span><span>,</span> <span>"</span><span>2022</span><span>"</span><span>]</span><span>df</span> <span>=</span> <span>pd</span><span>.</span><span>read_csv</span><span>(</span><span>"</span><span>rankings.csv</span><span>"</span><span>,</span> <span>index_col</span><span>=</span><span>None</span><span>)</span><span>df</span><span>,</span> <span>rank_columns</span> <span>=</span> <span>create_rankings</span><span>(</span><span>df</span><span>,</span> <span>years</span><span>)</span><span># Create chart </span><span>fig</span><span>,</span> <span>ax</span> <span>=</span> <span>plt</span><span>.</span><span>subplots</span><span>(</span><span>nrows</span><span>=</span><span>1</span><span>,</span> <span>ncols</span><span>=</span><span>1</span><span>,</span> <span>figsize</span><span>=</span><span>(</span><span>15</span><span>,</span> <span>1.6</span><span>*</span><span>len</span><span>(</span><span>df</span><span>)))</span><span>format_ticks</span><span>(</span><span>ax</span><span>,</span> <span>years</span><span>)</span><span># Draw lines </span><span>for</span> <span>i</span><span>,</span> <span>row</span> <span>in</span> <span>df</span><span>.</span><span>iterrows</span><span>():</span><span>add_line</span><span>(</span><span>ax</span><span>,</span> <span>row</span><span>,</span> <span>rank_columns</span><span>)</span><span>for</span> <span>j</span><span>,</span> <span>rc</span> <span>in</span> <span>enumerate</span><span>(</span><span>rank_columns</span><span>):</span><span>add_pie</span><span>(</span><span>ax</span><span>,</span> <span>j</span><span>,</span> <span>-</span><span>row</span><span>[</span><span>rc</span><span>],</span> <span>ratio</span><span>=</span><span>row</span><span>[</span><span>years</span><span>[</span><span>j</span><span>]]</span> <span>/</span> <span>row</span><span>[</span><span>years</span><span>].</span><span>max</span><span>())</span><span># Load data </span><span>years</span> <span>=</span> <span>[</span><span>"</span><span>2000</span><span>"</span><span>,</span> <span>"</span><span>2005</span><span>"</span><span>,</span> <span>"</span><span>2010</span><span>"</span><span>,</span> <span>"</span><span>2015</span><span>"</span><span>,</span> <span>"</span><span>2020</span><span>"</span><span>,</span> <span>"</span><span>2022</span><span>"</span><span>]</span> <span>df</span> <span>=</span> <span>pd</span><span>.</span><span>read_csv</span><span>(</span><span>"</span><span>rankings.csv</span><span>"</span><span>,</span> <span>index_col</span><span>=</span><span>None</span><span>)</span> <span>df</span><span>,</span> <span>rank_columns</span> <span>=</span> <span>create_rankings</span><span>(</span><span>df</span><span>,</span> <span>years</span><span>)</span> <span># Create chart </span><span>fig</span><span>,</span> <span>ax</span> <span>=</span> <span>plt</span><span>.</span><span>subplots</span><span>(</span><span>nrows</span><span>=</span><span>1</span><span>,</span> <span>ncols</span><span>=</span><span>1</span><span>,</span> <span>figsize</span><span>=</span><span>(</span><span>15</span><span>,</span> <span>1.6</span><span>*</span><span>len</span><span>(</span><span>df</span><span>)))</span> <span>format_ticks</span><span>(</span><span>ax</span><span>,</span> <span>years</span><span>)</span> <span># Draw lines </span><span>for</span> <span>i</span><span>,</span> <span>row</span> <span>in</span> <span>df</span><span>.</span><span>iterrows</span><span>():</span> <span>add_line</span><span>(</span><span>ax</span><span>,</span> <span>row</span><span>,</span> <span>rank_columns</span><span>)</span> <span>for</span> <span>j</span><span>,</span> <span>rc</span> <span>in</span> <span>enumerate</span><span>(</span><span>rank_columns</span><span>):</span> <span>add_pie</span><span>(</span><span>ax</span><span>,</span> <span>j</span><span>,</span> <span>-</span><span>row</span><span>[</span><span>rc</span><span>],</span> <span>ratio</span><span>=</span><span>row</span><span>[</span><span>years</span><span>[</span><span>j</span><span>]]</span> <span>/</span> <span>row</span><span>[</span><span>years</span><span>].</span><span>max</span><span>())</span># Load data years = ["2000", "2005", "2010", "2015", "2020", "2022"] df = pd.read_csv("rankings.csv", index_col=None) df, rank_columns = create_rankings(df, years) # Create chart fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(15, 1.6*len(df))) format_ticks(ax, years) # Draw lines for i, row in df.iterrows(): add_line(ax, row, rank_columns) for j, rc in enumerate(rank_columns): add_pie(ax, j, -row[rc], ratio=row[years[j]] / row[years].max())
Enter fullscreen mode Exit fullscreen mode
And here’s the result.
It’s starting to look informative, so it’s time to make it beautiful.
Step 5: Adding flags
I love using flags in my charts because they are simply beautiful.
Here, the purpose of the flags is to make the chart visually appealing, explain which countries we’re looking at, and guide the eye along the lines.
I’m using these rounded flags. They require a license, so, unfortunately, I can’t share them, but you can find similar flags in other places.
I’ve had some issues getting the pie and flag to align perfectly, so instead of creating a separate function to add a flag, I’m rewriting the add_pie() function.
<span>def</span> <span>add_pie_and_flag</span><span>(</span><span>ax</span><span>,</span> <span>x</span><span>,</span> <span>y</span><span>,</span> <span>name</span><span>,</span> <span>ratio</span><span>,</span> <span>size</span><span>=</span><span>572</span><span>,</span> <span>zoom</span><span>=</span><span>0.1</span><span>):</span><span>flag</span> <span>=</span> <span>Image</span><span>.</span><span>open</span><span>(</span><span>"</span><span><location>/{}.png</span><span>"</span><span>.</span><span>format</span><span>(</span><span>name</span><span>.</span><span>lower</span><span>()))</span><span>image</span> <span>=</span> <span>Image</span><span>.</span><span>new</span><span>(</span><span>'</span><span>RGBA</span><span>'</span><span>,</span> <span>(</span><span>size</span><span>,</span> <span>size</span><span>))</span><span>draw</span> <span>=</span> <span>ImageDraw</span><span>.</span><span>Draw</span><span>(</span><span>image</span><span>)</span><span>pad</span> <span>=</span> <span>int</span><span>((</span><span>size</span> <span>-</span> <span>512</span><span>)</span> <span>/</span> <span>2</span><span>)</span><span>draw</span><span>.</span><span>pieslice</span><span>((</span><span>0</span><span>,</span> <span>0</span><span>,</span> <span>size</span><span>,</span> <span>size</span><span>),</span> <span>start</span><span>=-</span><span>90</span><span>,</span> <span>end</span><span>=</span><span>360</span><span>*</span><span>ratio</span><span>-</span><span>90</span><span>,</span> <span>fill</span><span>=</span><span>text_color</span><span>,</span> <span>outline</span><span>=</span><span>text_color</span><span>)</span><span>image</span><span>.</span><span>paste</span><span>(</span><span>flag</span><span>,</span> <span>(</span><span>pad</span><span>,</span> <span>pad</span><span>),</span> <span>flag</span><span>.</span><span>split</span><span>()[</span><span>-</span><span>1</span><span>])</span><span>im</span> <span>=</span> <span>OffsetImage</span><span>(</span><span>image</span><span>,</span> <span>zoom</span><span>=</span><span>zoom</span><span>,</span> <span>interpolation</span><span>=</span><span>"</span><span>lanczos</span><span>"</span><span>,</span> <span>resample</span><span>=</span><span>True</span><span>,</span> <span>visible</span><span>=</span><span>True</span><span>)</span><span>ax</span><span>.</span><span>add_artist</span><span>(</span><span>AnnotationBbox</span><span>(</span><span>im</span><span>,</span> <span>(</span><span>x</span><span>,</span> <span>y</span><span>),</span> <span>frameon</span><span>=</span><span>False</span><span>,</span><span>xycoords</span><span>=</span><span>"</span><span>data</span><span>"</span><span>,</span><span>))</span><span>def</span> <span>add_pie_and_flag</span><span>(</span><span>ax</span><span>,</span> <span>x</span><span>,</span> <span>y</span><span>,</span> <span>name</span><span>,</span> <span>ratio</span><span>,</span> <span>size</span><span>=</span><span>572</span><span>,</span> <span>zoom</span><span>=</span><span>0.1</span><span>):</span> <span>flag</span> <span>=</span> <span>Image</span><span>.</span><span>open</span><span>(</span><span>"</span><span><location>/{}.png</span><span>"</span><span>.</span><span>format</span><span>(</span><span>name</span><span>.</span><span>lower</span><span>()))</span> <span>image</span> <span>=</span> <span>Image</span><span>.</span><span>new</span><span>(</span><span>'</span><span>RGBA</span><span>'</span><span>,</span> <span>(</span><span>size</span><span>,</span> <span>size</span><span>))</span> <span>draw</span> <span>=</span> <span>ImageDraw</span><span>.</span><span>Draw</span><span>(</span><span>image</span><span>)</span> <span>pad</span> <span>=</span> <span>int</span><span>((</span><span>size</span> <span>-</span> <span>512</span><span>)</span> <span>/</span> <span>2</span><span>)</span> <span>draw</span><span>.</span><span>pieslice</span><span>((</span><span>0</span><span>,</span> <span>0</span><span>,</span> <span>size</span><span>,</span> <span>size</span><span>),</span> <span>start</span><span>=-</span><span>90</span><span>,</span> <span>end</span><span>=</span><span>360</span><span>*</span><span>ratio</span><span>-</span><span>90</span><span>,</span> <span>fill</span><span>=</span><span>text_color</span><span>,</span> <span>outline</span><span>=</span><span>text_color</span><span>)</span> <span>image</span><span>.</span><span>paste</span><span>(</span><span>flag</span><span>,</span> <span>(</span><span>pad</span><span>,</span> <span>pad</span><span>),</span> <span>flag</span><span>.</span><span>split</span><span>()[</span><span>-</span><span>1</span><span>])</span> <span>im</span> <span>=</span> <span>OffsetImage</span><span>(</span><span>image</span><span>,</span> <span>zoom</span><span>=</span><span>zoom</span><span>,</span> <span>interpolation</span><span>=</span><span>"</span><span>lanczos</span><span>"</span><span>,</span> <span>resample</span><span>=</span><span>True</span><span>,</span> <span>visible</span><span>=</span><span>True</span><span>)</span> <span>ax</span><span>.</span><span>add_artist</span><span>(</span><span>AnnotationBbox</span><span>(</span> <span>im</span><span>,</span> <span>(</span><span>x</span><span>,</span> <span>y</span><span>),</span> <span>frameon</span><span>=</span><span>False</span><span>,</span> <span>xycoords</span><span>=</span><span>"</span><span>data</span><span>"</span><span>,</span> <span>))</span>def add_pie_and_flag(ax, x, y, name, ratio, size=572, zoom=0.1): flag = Image.open("<location>/{}.png".format(name.lower())) image = Image.new('RGBA', (size, size)) draw = ImageDraw.Draw(image) pad = int((size - 512) / 2) draw.pieslice((0, 0, size, size), start=-90, end=360*ratio-90, fill=text_color, outline=text_color) image.paste(flag, (pad, pad), flag.split()[-1]) im = OffsetImage(image, zoom=zoom, interpolation="lanczos", resample=True, visible=True) ax.add_artist(AnnotationBbox( im, (x, y), frameon=False, xycoords="data", ))
Enter fullscreen mode Exit fullscreen mode
I add it right after the pie chart function.
<span># Load data </span><span>years</span> <span>=</span> <span>[</span><span>"</span><span>2000</span><span>"</span><span>,</span> <span>"</span><span>2005</span><span>"</span><span>,</span> <span>"</span><span>2010</span><span>"</span><span>,</span> <span>"</span><span>2015</span><span>"</span><span>,</span> <span>"</span><span>2020</span><span>"</span><span>,</span> <span>"</span><span>2022</span><span>"</span><span>]</span><span>df</span> <span>=</span> <span>pd</span><span>.</span><span>read_csv</span><span>(</span><span>"</span><span>rankings.csv</span><span>"</span><span>,</span> <span>index_col</span><span>=</span><span>None</span><span>)</span><span>df</span><span>,</span> <span>rank_columns</span> <span>=</span> <span>create_rankings</span><span>(</span><span>df</span><span>,</span> <span>years</span><span>)</span><span># Create chart </span><span>fig</span><span>,</span> <span>ax</span> <span>=</span> <span>plt</span><span>.</span><span>subplots</span><span>(</span><span>nrows</span><span>=</span><span>1</span><span>,</span> <span>ncols</span><span>=</span><span>1</span><span>,</span> <span>figsize</span><span>=</span><span>(</span><span>15</span><span>,</span> <span>1.6</span><span>*</span><span>len</span><span>(</span><span>df</span><span>)))</span><span>format_ticks</span><span>(</span><span>ax</span><span>,</span> <span>years</span><span>)</span><span># Draw lines </span><span>for</span> <span>i</span><span>,</span> <span>row</span> <span>in</span> <span>df</span><span>.</span><span>iterrows</span><span>():</span><span>add_line</span><span>(</span><span>ax</span><span>,</span> <span>row</span><span>,</span> <span>rank_columns</span><span>)</span><span>for</span> <span>j</span><span>,</span> <span>rc</span> <span>in</span> <span>enumerate</span><span>(</span><span>rank_columns</span><span>):</span><span>add_pie_and_flag</span><span>(</span><span>ax</span><span>,</span> <span>j</span><span>,</span> <span>-</span><span>row</span><span>[</span><span>rc</span><span>],</span><span>name</span><span>=</span><span>row</span><span>.</span><span>country_name</span><span>,</span><span>ratio</span><span>=</span><span>row</span><span>[</span><span>years</span><span>[</span><span>j</span><span>]]</span> <span>/</span> <span>row</span><span>[</span><span>years</span><span>].</span><span>max</span><span>()</span><span>)</span><span># Load data </span><span>years</span> <span>=</span> <span>[</span><span>"</span><span>2000</span><span>"</span><span>,</span> <span>"</span><span>2005</span><span>"</span><span>,</span> <span>"</span><span>2010</span><span>"</span><span>,</span> <span>"</span><span>2015</span><span>"</span><span>,</span> <span>"</span><span>2020</span><span>"</span><span>,</span> <span>"</span><span>2022</span><span>"</span><span>]</span> <span>df</span> <span>=</span> <span>pd</span><span>.</span><span>read_csv</span><span>(</span><span>"</span><span>rankings.csv</span><span>"</span><span>,</span> <span>index_col</span><span>=</span><span>None</span><span>)</span> <span>df</span><span>,</span> <span>rank_columns</span> <span>=</span> <span>create_rankings</span><span>(</span><span>df</span><span>,</span> <span>years</span><span>)</span> <span># Create chart </span><span>fig</span><span>,</span> <span>ax</span> <span>=</span> <span>plt</span><span>.</span><span>subplots</span><span>(</span><span>nrows</span><span>=</span><span>1</span><span>,</span> <span>ncols</span><span>=</span><span>1</span><span>,</span> <span>figsize</span><span>=</span><span>(</span><span>15</span><span>,</span> <span>1.6</span><span>*</span><span>len</span><span>(</span><span>df</span><span>)))</span> <span>format_ticks</span><span>(</span><span>ax</span><span>,</span> <span>years</span><span>)</span> <span># Draw lines </span><span>for</span> <span>i</span><span>,</span> <span>row</span> <span>in</span> <span>df</span><span>.</span><span>iterrows</span><span>():</span> <span>add_line</span><span>(</span><span>ax</span><span>,</span> <span>row</span><span>,</span> <span>rank_columns</span><span>)</span> <span>for</span> <span>j</span><span>,</span> <span>rc</span> <span>in</span> <span>enumerate</span><span>(</span><span>rank_columns</span><span>):</span> <span>add_pie_and_flag</span><span>(</span> <span>ax</span><span>,</span> <span>j</span><span>,</span> <span>-</span><span>row</span><span>[</span><span>rc</span><span>],</span> <span>name</span><span>=</span><span>row</span><span>.</span><span>country_name</span><span>,</span> <span>ratio</span><span>=</span><span>row</span><span>[</span><span>years</span><span>[</span><span>j</span><span>]]</span> <span>/</span> <span>row</span><span>[</span><span>years</span><span>].</span><span>max</span><span>()</span> <span>)</span># Load data years = ["2000", "2005", "2010", "2015", "2020", "2022"] df = pd.read_csv("rankings.csv", index_col=None) df, rank_columns = create_rankings(df, years) # Create chart fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(15, 1.6*len(df))) format_ticks(ax, years) # Draw lines for i, row in df.iterrows(): add_line(ax, row, rank_columns) for j, rc in enumerate(rank_columns): add_pie_and_flag( ax, j, -row[rc], name=row.country_name, ratio=row[years[j]] / row[years].max() )
Enter fullscreen mode Exit fullscreen mode
And now you can behold the visual magic of using flags. It’s a huge difference compared to the previous output.
We suddenly have something that looks nice and is easy to understand. The last thing to do is to add some helpful information.
Step 5: Adding additional information
Since not everyone knows all the flags by heart, I want to add the country’s name to the right.
I also want to show the size of the economy and how each country compares to the highest ranking.
Here’s my code for doing that.
<span>def</span> <span>add_text</span><span>(</span><span>ax</span><span>,</span> <span>value</span><span>,</span> <span>max_value</span><span>,</span> <span>y</span><span>):</span><span>trillions</span> <span>=</span> <span>round</span><span>(</span><span>value</span> <span>/</span> <span>1e12</span><span>,</span> <span>1</span><span>)</span><span>ratio_to_max</span> <span>=</span> <span>round</span><span>(</span><span>100</span> <span>*</span> <span>value</span> <span>/</span> <span>max_value</span><span>,</span> <span>1</span><span>)</span><span>text</span> <span>=</span> <span>"</span><span>{}</span><span>\n</span><span>${:,}T ({}%)</span><span>"</span><span>.</span><span>format</span><span>(</span><span>row</span><span>.</span><span>country_name</span><span>,</span><span>trillions</span><span>,</span><span>ratio_to_max</span><span>)</span><span>ax</span><span>.</span><span>annotate</span><span>(</span><span>text</span><span>,</span> <span>(</span><span>1.03</span><span>,</span> <span>y</span><span>),</span><span>fontsize</span><span>=</span><span>20</span><span>,</span><span>linespacing</span><span>=</span><span>1.7</span><span>,</span><span>va</span><span>=</span><span>"</span><span>center</span><span>"</span><span>,</span><span>xycoords</span><span>=</span><span>(</span><span>"</span><span>axes fraction</span><span>"</span><span>,</span> <span>"</span><span>data</span><span>"</span><span>)</span><span>)</span><span>def</span> <span>add_text</span><span>(</span><span>ax</span><span>,</span> <span>value</span><span>,</span> <span>max_value</span><span>,</span> <span>y</span><span>):</span> <span>trillions</span> <span>=</span> <span>round</span><span>(</span><span>value</span> <span>/</span> <span>1e12</span><span>,</span> <span>1</span><span>)</span> <span>ratio_to_max</span> <span>=</span> <span>round</span><span>(</span><span>100</span> <span>*</span> <span>value</span> <span>/</span> <span>max_value</span><span>,</span> <span>1</span><span>)</span> <span>text</span> <span>=</span> <span>"</span><span>{}</span><span>\n</span><span>${:,}T ({}%)</span><span>"</span><span>.</span><span>format</span><span>(</span> <span>row</span><span>.</span><span>country_name</span><span>,</span> <span>trillions</span><span>,</span> <span>ratio_to_max</span> <span>)</span> <span>ax</span><span>.</span><span>annotate</span><span>(</span> <span>text</span><span>,</span> <span>(</span><span>1.03</span><span>,</span> <span>y</span><span>),</span> <span>fontsize</span><span>=</span><span>20</span><span>,</span> <span>linespacing</span><span>=</span><span>1.7</span><span>,</span> <span>va</span><span>=</span><span>"</span><span>center</span><span>"</span><span>,</span> <span>xycoords</span><span>=</span><span>(</span><span>"</span><span>axes fraction</span><span>"</span><span>,</span> <span>"</span><span>data</span><span>"</span><span>)</span> <span>)</span>def add_text(ax, value, max_value, y): trillions = round(value / 1e12, 1) ratio_to_max = round(100 * value / max_value, 1) text = "{}\n${:,}T ({}%)".format( row.country_name, trillions, ratio_to_max ) ax.annotate( text, (1.03, y), fontsize=20, linespacing=1.7, va="center", xycoords=("axes fraction", "data") )
Enter fullscreen mode Exit fullscreen mode
As before, I add the function to the main code block. Note that I’m also adding a title.
<span>years</span> <span>=</span> <span>[</span><span>"</span><span>2000</span><span>"</span><span>,</span> <span>"</span><span>2005</span><span>"</span><span>,</span> <span>"</span><span>2010</span><span>"</span><span>,</span> <span>"</span><span>2015</span><span>"</span><span>,</span> <span>"</span><span>2020</span><span>"</span><span>,</span> <span>"</span><span>2022</span><span>"</span><span>]</span><span>df</span> <span>=</span> <span>pd</span><span>.</span><span>read_csv</span><span>(</span><span>"</span><span>rankings.csv</span><span>"</span><span>,</span> <span>index_col</span><span>=</span><span>None</span><span>)</span><span>df</span><span>,</span> <span>rank_columns</span> <span>=</span> <span>create_rankings</span><span>(</span><span>df</span><span>,</span> <span>years</span><span>)</span><span>fig</span><span>,</span> <span>ax</span> <span>=</span> <span>plt</span><span>.</span><span>subplots</span><span>(</span><span>nrows</span><span>=</span><span>1</span><span>,</span> <span>ncols</span><span>=</span><span>1</span><span>,</span> <span>figsize</span><span>=</span><span>(</span><span>15</span><span>,</span> <span>1.6</span><span>*</span><span>len</span><span>(</span><span>df</span><span>)))</span><span>format_ticks</span><span>(</span><span>ax</span><span>,</span> <span>years</span><span>)</span><span>for</span> <span>i</span><span>,</span> <span>row</span> <span>in</span> <span>df</span><span>.</span><span>iterrows</span><span>():</span><span>add_line</span><span>(</span><span>ax</span><span>,</span> <span>row</span><span>,</span> <span>rank_columns</span><span>)</span><span>for</span> <span>j</span><span>,</span> <span>rc</span> <span>in</span> <span>enumerate</span><span>(</span><span>rank_columns</span><span>):</span><span>add_pie_and_flag</span><span>(</span><span>ax</span><span>,</span> <span>j</span><span>,</span> <span>-</span><span>row</span><span>[</span><span>rc</span><span>],</span><span>name</span><span>=</span><span>row</span><span>.</span><span>country_name</span><span>,</span><span>ratio</span><span>=</span><span>row</span><span>[</span><span>years</span><span>[</span><span>j</span><span>]]</span> <span>/</span> <span>row</span><span>[</span><span>years</span><span>].</span><span>max</span><span>()</span><span>)</span><span>add_text</span><span>(</span><span>ax</span><span>,</span> <span>value</span><span>=</span><span>row</span><span>[</span><span>years</span><span>[</span><span>-</span><span>1</span><span>]],</span> <span>max_value</span><span>=</span><span>df</span><span>.</span><span>iloc</span><span>[</span><span>0</span><span>][</span><span>years</span><span>[</span><span>-</span><span>1</span><span>]],</span> <span>y</span><span>=-</span><span>(</span><span>i</span> <span>+</span> <span>1</span><span>))</span><span>plt</span><span>.</span><span>title</span><span>(</span><span>"</span><span>Comparing Today</span><span>'</span><span>s Largest Economies</span><span>\n</span><span>GDP (constant 2015 us$)</span><span>"</span><span>,</span> <span>linespacing</span><span>=</span><span>1.8</span><span>,</span> <span>fontsize</span><span>=</span><span>32</span><span>,</span> <span>x</span><span>=</span><span>0.58</span><span>,</span> <span>y</span><span>=</span><span>1.12</span><span>)</span><span>years</span> <span>=</span> <span>[</span><span>"</span><span>2000</span><span>"</span><span>,</span> <span>"</span><span>2005</span><span>"</span><span>,</span> <span>"</span><span>2010</span><span>"</span><span>,</span> <span>"</span><span>2015</span><span>"</span><span>,</span> <span>"</span><span>2020</span><span>"</span><span>,</span> <span>"</span><span>2022</span><span>"</span><span>]</span> <span>df</span> <span>=</span> <span>pd</span><span>.</span><span>read_csv</span><span>(</span><span>"</span><span>rankings.csv</span><span>"</span><span>,</span> <span>index_col</span><span>=</span><span>None</span><span>)</span> <span>df</span><span>,</span> <span>rank_columns</span> <span>=</span> <span>create_rankings</span><span>(</span><span>df</span><span>,</span> <span>years</span><span>)</span> <span>fig</span><span>,</span> <span>ax</span> <span>=</span> <span>plt</span><span>.</span><span>subplots</span><span>(</span><span>nrows</span><span>=</span><span>1</span><span>,</span> <span>ncols</span><span>=</span><span>1</span><span>,</span> <span>figsize</span><span>=</span><span>(</span><span>15</span><span>,</span> <span>1.6</span><span>*</span><span>len</span><span>(</span><span>df</span><span>)))</span> <span>format_ticks</span><span>(</span><span>ax</span><span>,</span> <span>years</span><span>)</span> <span>for</span> <span>i</span><span>,</span> <span>row</span> <span>in</span> <span>df</span><span>.</span><span>iterrows</span><span>():</span> <span>add_line</span><span>(</span><span>ax</span><span>,</span> <span>row</span><span>,</span> <span>rank_columns</span><span>)</span> <span>for</span> <span>j</span><span>,</span> <span>rc</span> <span>in</span> <span>enumerate</span><span>(</span><span>rank_columns</span><span>):</span> <span>add_pie_and_flag</span><span>(</span> <span>ax</span><span>,</span> <span>j</span><span>,</span> <span>-</span><span>row</span><span>[</span><span>rc</span><span>],</span> <span>name</span><span>=</span><span>row</span><span>.</span><span>country_name</span><span>,</span> <span>ratio</span><span>=</span><span>row</span><span>[</span><span>years</span><span>[</span><span>j</span><span>]]</span> <span>/</span> <span>row</span><span>[</span><span>years</span><span>].</span><span>max</span><span>()</span> <span>)</span> <span>add_text</span><span>(</span><span>ax</span><span>,</span> <span>value</span><span>=</span><span>row</span><span>[</span><span>years</span><span>[</span><span>-</span><span>1</span><span>]],</span> <span>max_value</span><span>=</span><span>df</span><span>.</span><span>iloc</span><span>[</span><span>0</span><span>][</span><span>years</span><span>[</span><span>-</span><span>1</span><span>]],</span> <span>y</span><span>=-</span><span>(</span><span>i</span> <span>+</span> <span>1</span><span>))</span> <span>plt</span><span>.</span><span>title</span><span>(</span><span>"</span><span>Comparing Today</span><span>'</span><span>s Largest Economies</span><span>\n</span><span>GDP (constant 2015 us$)</span><span>"</span><span>,</span> <span>linespacing</span><span>=</span><span>1.8</span><span>,</span> <span>fontsize</span><span>=</span><span>32</span><span>,</span> <span>x</span><span>=</span><span>0.58</span><span>,</span> <span>y</span><span>=</span><span>1.12</span><span>)</span>years = ["2000", "2005", "2010", "2015", "2020", "2022"] df = pd.read_csv("rankings.csv", index_col=None) df, rank_columns = create_rankings(df, years) fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(15, 1.6*len(df))) format_ticks(ax, years) for i, row in df.iterrows(): add_line(ax, row, rank_columns) for j, rc in enumerate(rank_columns): add_pie_and_flag( ax, j, -row[rc], name=row.country_name, ratio=row[years[j]] / row[years].max() ) add_text(ax, value=row[years[-1]], max_value=df.iloc[0][years[-1]], y=-(i + 1)) plt.title("Comparing Today's Largest Economies\nGDP (constant 2015 us$)", linespacing=1.8, fontsize=32, x=0.58, y=1.12)
Enter fullscreen mode Exit fullscreen mode
Voila.
That’s it; we’re done.
Conclusion
Today, you’ve learned an alternative way to visualize.
I like this type of data visualization because it’s easy on the eye and conveys a ton of information with very little text.
If you enjoyed it as much as I did, make sure to subscribe to my channel for more of the same! 🙂
Thank you for reading.
原文链接:How to Create Eye-Catching Country Rankings Using Python and Matplotlib
暂无评论内容