Skip to content

Instantly share code, notes, and snippets.

@gabriel-berardi
Last active May 3, 2020 14:04
Show Gist options
  • Select an option

  • Save gabriel-berardi/2598032da5ea0453cf3385c8ce73bafc to your computer and use it in GitHub Desktop.

Select an option

Save gabriel-berardi/2598032da5ea0453cf3385c8ce73bafc to your computer and use it in GitHub Desktop.
racing_bar_chart.py
import pandas as pd
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import matplotlib.animation as animation
import matplotlib.colors as mc
import colorsys
from random import randint
import re
df = pd.read_csv("EO95_LTB_07012019070138125.csv")
df = df.loc[df['Variable'] == 'GDP per capita in USA 2005 PPPs']
df = df[((df.Country != 'OECD - Total') & ( df.Country != 'Non-OECD Economies') & (df.Country != 'World') & (df.Country != 'Euro area (15 countries)'))]
df = df[['Country', 'Time', 'Value']]
df = df.pivot(index = 'Country', columns = 'Time', values = 'Value')
df = df.reset_index()
for p in range(3):
i = 0
while i < len(df.columns):
try:
a = np.array(df.iloc[:, i + 1])
b = np.array(df.iloc[:, i + 2])
c = (a + b) / 2
df.insert(i+2, str(df.iloc[:, i + 1].name) + '^' + str(len(df.columns)), c)
except:
print(f"\n Interpolation No. {p + 1} done...")
i += 2
df = pd.melt(df, id_vars = 'Country', var_name = 'Time')
frames_list = df["Time"].unique().tolist()
for i in range(10):
frames_list.append(df['Time'].iloc[-1])
def transform_color(color, amount = 0.5):
try:
c = mc.cnames[color]
except:
c = color
c = colorsys.rgb_to_hls(*mc.to_rgb(c))
return colorsys.hls_to_rgb(c[0], 1 - amount * (1 - c[1]), c[2])
all_names = df['Country'].unique().tolist()
random_hex_colors = []
for i in range(len(all_names)):
random_hex_colors.append('#' + '%06X' % randint(0, 0xFFFFFF))
rgb_colors = [transform_color(i, 1) for i in random_hex_colors]
rgb_colors_opacity = [rgb_colors[x] + (0.825,) for x in range(len(rgb_colors))]
rgb_colors_dark = [transform_color(i, 1.12) for i in random_hex_colors]
fig, ax = plt.subplots(figsize = (36, 20))
num_of_elements = 8
def draw_barchart(Time):
df_frame = df[df['Time'].eq(Time)].sort_values(by = 'value', ascending = True).tail(num_of_elements)
ax.clear()
normal_colors = dict(zip(df['Country'].unique(), rgb_colors_opacity))
dark_colors = dict(zip(df['Country'].unique(), rgb_colors_dark))
ax.barh(df_frame['Country'], df_frame['value'], color = [normal_colors[x] for x in df_frame['Country']], height = 0.8,
edgecolor =([dark_colors[x] for x in df_frame['Country']]), linewidth = '6')
dx = float(df_frame['value'].max()) / 200
for i, (value, name) in enumerate(zip(df_frame['value'], df_frame['Country'])):
ax.text(value + dx, i + (num_of_elements / 50), ' ' + name,
size = 36, weight = 'bold', ha = 'left', va = 'center', fontdict = {'fontname': 'Trebuchet MS'})
ax.text(value + dx, i - (num_of_elements / 50), f' {value:,.0f}', size = 36, ha = 'left', va = 'center')
time_unit_displayed = re.sub(r'\^(.*)', r'', str(Time))
ax.text(1.0, 1.14, time_unit_displayed, transform = ax.transAxes, color = '#666666',
size = 62, ha = 'right', weight = 'bold', fontdict = {'fontname': 'Trebuchet MS'})
ax.text(-0.005, 1.06, 'GDP/capita', transform = ax.transAxes, size = 30, color = '#666666')
ax.text(-0.005, 1.14, 'Projection of GDP/capita from 2010 to 2060', transform = ax.transAxes,
size = 62, weight = 'bold', ha = 'left', fontdict = {'fontname': 'Trebuchet MS'})
ax.xaxis.set_major_formatter(ticker.StrMethodFormatter('{x:,.0f}'))
ax.xaxis.set_ticks_position('top')
ax.tick_params(axis = 'x', colors = '#666666', labelsize = 28)
ax.set_yticks([])
ax.set_axisbelow(True)
ax.margins(0, 0.01)
ax.grid(which = 'major', axis = 'x', linestyle = '-')
plt.locator_params(axis = 'x', nbins = 4)
plt.box(False)
plt.subplots_adjust(left = 0.075, right = 0.75, top = 0.825, bottom = 0.05, wspace = 0.2, hspace = 0.2)
animator = animation.FuncAnimation(fig, draw_barchart, frames = frames_list)
animator.save("Racing Bar Chart.mp4", fps = 20, bitrate = 1800)
@jantjeu
Copy link

jantjeu commented Feb 27, 2020

i get

MovieWriter ffmpeg unavailable; trying to use <class 'matplotlib.animation.PillowWriter'> instead.

then

KeyError: '.mp4'

then

ValueError: unknown file extension: .mp4

@gabriel-berardi
Copy link
Author

@jantjeu
Copy link

jantjeu commented Feb 28, 2020

@jantjeu

Did you do this?

https://www.wikihow.com/Install-FFmpeg-on-Windows`

no, i did this in jupytter notebook:

pip install ffmpeg

but it's not working. then I do this:

conda install -c conda-forge ffmpeg

eureka.. it's working. thanks 👍

@manel00
Copy link

manel00 commented Mar 19, 2020

Hello how its going? one question, what is the format of the CSV? because I'd like to try your code but don't know what shape to use, thanks ;)

Can you put please the final result of CSV to use your code?

thanks my friend

@gabriel-berardi
Copy link
Author

@manel00

Hi there! What exactly do you mean? It is a normal Comma-separated values (CSV) file. You can see the one I used in the repository: https://github.com/6berardi/RacingBarChart

Let me know if you have any other question!

@Kshitij-s
Copy link

Hi, Thanks for this code

I get error
image

@gabriel-berardi
Copy link
Author

@Kshitij-s

I am sorry, I do not really know what is the reason for this Error. Try to reinstall FFmpeg and let me know if that solves the problem.

@Kshitij-s
Copy link

Thanks, Reinstall worked for me

@its-jd
Copy link

its-jd commented Apr 9, 2020

I tried to reproduce the result from your code and it gave me this error

_tkinter.TclError: can't invoke "wm" command: application has been destroyed

I searched for this error and it says the root windows has been killed so we can't invoke the 'wm' command.Any suggestion on what could I do to solve this problem?

@gabriel-berardi
Copy link
Author

gabriel-berardi commented Apr 9, 2020

@its-jd

I am sorry but I don't know how to solve this problem. If you find a solution please let us know here. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment