I have the code to create my 2D histogram as below. It works for creating a statics chart but I need to create an animated heatmap which change with 'minute_play' column. How can I do that? The picture of the data sample and the output are attached. Below is the code I used to create the 2D histogram (heatmap)
multicolor = ["#ffffff","#e2eeff", "#c3d8f9","#80bdff", "#42b0f5",
"#a0e242", "#d1cb1c", "#a06a20", "#872a10", "#630d02", "#000000"]
bins = 100
densities,_,_ = np.histogram2d(heatmap_df.params_pos_x, heatmap_df.params_pos_y, bins=bins)
percentiles = [0,1,10,20,30,40,50,60,70,80,99,100]
bounds = []
for i in percentiles:
bounds.append(np.percentile(np.unique(densities),i))
cmaplist = multicolor
cmap = mpl.colors.LinearSegmentedColormap.from_list(
'Custom cmap',
cmaplist,
len(percentiles))
norm = mpl.colors.BoundaryNorm(bounds, cmap.N)
plt.hist2d(heatmap_df.params_pos_x,
heatmap_df.params_pos_y,
bins = bins,
norm = norm,
cmap = cmap)
cbar = plt.colorbar(ticks = bounds)
plt.show()
I have try to follow this but did not really understand what to do next to migrate my code to this guide
Here is an example of how to achieve this together with sample data. In my case, I did it in jupyter notebook:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import matplotlib.colors as mcolors
from IPython.display import HTML
np.random.seed(0)
num_entries = 1000
num_minutes = 10
minute_play = np.random.choice(range(num_minutes), size=num_entries)
params_pos_x = np.random.uniform(0, 100, num_entries)
params_pos_y = np.random.uniform(0, 100, num_entries)
heatmap_df = pd.DataFrame({
'minute_play': minute_play,
'params_pos_x': params_pos_x,
'params_pos_y': params_pos_y
})
bins = 50
multicolor = ["#ffffff", "#e2eeff", "#c3d8f9", "#80bdff", "#42b0f5",
"#a0e242", "#d1cb1c", "#a06a20", "#872a10", "#630d02", "#000000"]
percentiles = [0, 1, 10, 20, 30, 40, 50, 60, 70, 80, 99, 100]
densities, _, _ = np.histogram2d(heatmap_df['params_pos_x'], heatmap_df['params_pos_y'], bins=bins)
bounds = [np.percentile(np.unique(densities), i) for i in percentiles]
cmap = mcolors.LinearSegmentedColormap.from_list('Custom cmap', multicolor, len(percentiles))
norm = mcolors.BoundaryNorm(bounds, cmap.N)
fig, ax = plt.subplots()
cbar = fig.colorbar(plt.cm.ScalarMappable(norm=norm, cmap=cmap), ax=ax, ticks=bounds)
cbar.set_label('Density')
def update(frame):
ax.clear() # Clear the previous plot
minute_data = heatmap_df[heatmap_df['minute_play'] == frame]
hist = ax.hist2d(minute_data['params_pos_x'], minute_data['params_pos_y'], bins=bins, cmap=cmap, norm=norm)
ax.set_title(f'Minute: {frame}')
ani = animation.FuncAnimation(fig, update, frames=np.arange(heatmap_df['minute_play'].min(), heatmap_df['minute_play'].max() + 1),
repeat=False)
HTML(ani.to_jshtml())
which gives
To save it:
ani.save('animated_heatmap.mp4', writer='ffmpeg')
or
ani.save('animated_heatmap.gif', writer='imagemagick')