Last active
February 18, 2025 05:05
-
-
Save csghone/bbee9e0325ac8ccf50ead1a997b7f69b to your computer and use it in GitHub Desktop.
Matplotlib helpers
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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