Skip to content

Instantly share code, notes, and snippets.

@csghone
Last active February 18, 2025 05:05
Show Gist options
  • Save csghone/bbee9e0325ac8ccf50ead1a997b7f69b to your computer and use it in GitHub Desktop.
Save csghone/bbee9e0325ac8ccf50ead1a997b7f69b to your computer and use it in GitHub Desktop.
Matplotlib helpers
# Refs:
# https://matplotlib.org/3.9.3/users/explain/quick_start.html
# https://stackoverflow.com/questions/7908636/how-to-add-hovering-annotations-to-a-plot
# https://www.geeksforgeeks.org/how-to-draw-a-line-inside-a-scatter-plot/
# https://python-graph-gallery.com/scatterplot-with-regression-fit-in-matplotlib/
# https://stackoverflow.com/questions/22239691/code-for-best-fit-straight-line-of-a-scatter-plot
# https://stackoverflow.com/questions/27878217/how-do-i-extend-the-margin-at-the-bottom-of-a-figure-in-matplotlib
# https://stackoverflow.com/questions/51473993/plot-an-histogram-with-y-axis-as-percentage-using-funcformatter
def plot_cols(inp_df: pandas.DataFrame, *args):
plt.figure(figsize=(10, 10))
for x in args:
plt.plot(inp_df[X_AXIS_KEY], inp_df[x], label=x)
plt.xlabel("Graph Name")
plt.ylabel("Values")
plt.legend()
plt.xticks(rotation=90)
plt.subplots_adjust(bottom=0.7)
plt.show()
def plot_scatter_y_x(inp_df: pandas.DataFrame, col_y: str, col_x: str):
plt.figure(figsize=(10, 10))
slope, intercept = numpy.polyfit(inp_df[col_y], inp_df[col_x], 1)
line = slope * inp_df[col_y] + intercept
sc = plt.scatter(inp_df[col_y], inp_df[col_x])
fig = plt.figure(1)
ax = fig.axes[0]
plt.plot(inp_df[col_y], line, label=f"Linear best-fit: Slope: {slope:,.2f} Offset: {intercept:,.2e}")
plt.xlabel(col_x)
plt.ylabel(col_y)
plt.legend()
annot = ax.annotate("",
xy=(0,0),
xytext=(-20,-20),
textcoords="offset points",
# arrowprops=dict(arrowstyle="->"),
bbox=dict(boxstyle="round", fc="w")
)
annot.set_visible(False)
xlim = ax.get_xlim()
ylim = ax.get_ylim()
xl = (xlim[1] - xlim[0]) * 0.2 + xlim[0]
xr = (xlim[1] - xlim[0]) * 0.8 + xlim[0]
yt = (ylim[1] - ylim[0]) * 0.2 + ylim[0]
yb = (ylim[1] - ylim[0]) * 0.8 + ylim[0]
def update_annot(ind):
data_idx = ind["ind"][0]
pos = sc.get_offsets()[data_idx]
df_entry = inp_df.iloc[data_idx]
graph_name = df_entry[X_AXIS_KEY]
xval = df_entry[col_y]
yval = df_entry[col_x]
out_text = graph_name
out_text += f"\n{xval:,.2e}, {yval:,.2e}"
out_text += f"\n{xval:,.2f}, {yval:,.2f}"
out_pos = pos
if pos[0] > xr:
out_pos = (out_pos[0] - 100, out_pos[1])
if pos[1] > yt:
out_pos = (out_pos[0], out_pos[1] - 100)
if pos[0] < xl:
out_pos = (out_pos[0] + 20, out_pos[1])
if pos[1] < yb:
out_pos = (out_pos[0], out_pos[1] + 20)
annot.set_text(out_text)
annot.xy = out_pos
def hover(event):
vis = annot.get_visible()
if event.inaxes == ax:
cont, ind = sc.contains(event)
if cont:
# breakpoint()
update_annot(ind)
annot.set_visible(True)
fig.canvas.draw_idle()
else:
if vis:
annot.set_visible(False)
fig.canvas.draw_idle()
fig.canvas.mpl_connect("motion_notify_event", hover)
plt.show()
def plot_hist(inp_df: pandas.DataFrame, col_x: str, bins=5):
plt.figure(figsize=(10, 5))
plt.subplot(1, 2, 1)
plt.hist(inp_df[col_x], bins=bins, edgecolor='black')
plt.xlabel(col_x)
plt.ylabel("Frequency")
plt.subplot(1, 2, 2)
n, bins, patches = plt.hist(
inp_df[col_x],
bins=bins,
edgecolor='black',
weights=[1/len(inp_df[col_x])]*len(inp_df[col_x])
)
plt.xlabel(col_x)
plt.ylabel("Percentage")
plt.tight_layout()
# Display the plot
plt.show()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment