I'm indebted to this answer.

The code that produced the scrollable figure is below, using only Numpy and Matplotlib.
import numpy as np import matplotlib.pyplot as plt from matplotlib.widgets import Slider from itertools import product n_bars = 100 n_shown = 10 names = ["".join(t) for t in product("ABCDE", "ABCDE", "ABCDE")][:n_bars] np.random.seed(20250502) values = np.random.randint(1, 11, n_bars) fig, ax_d = plt.subplot_mosaic("a" * 7 + "b") ax_d["a"].barh(names, values) ax_d["a"].axis([-0.2, 10.2, -0.5, n_shown-0.5]) ax_d["a"].invert_yaxis() spos = Slider(ax_d["b"], "", -0.5, n_bars-n_shown-0.5, orientation="vertical") def update(val): pos = spos.val ax_d["a"].axis([-0.2, 10.2, pos+n_shown, pos]) fig.canvas.draw_idle() spos.on_changed(update) plt.show()
The code above is OK, but I want to post a more refined (overly refined?) version of it… that somehow addresses the OP desire of an answer dealing with data incoming from a CSV file: below, I write a CSV file from my data and next I read from it (3 statements, no external modules).

Below the code, it's quite longer than the original one, but not more complex. Note that I've inverted the direction of scrolling and suppressed the display of the value from the Slider object.
import numpy as np import matplotlib.pyplot as plt from matplotlib.widgets import Slider from itertools import product # create some data n_bars = 100 _names = ["".join(t) for t in product("ABCDE", "ABCDE", "ABCDE")][:n_bars] np.random.seed(20250502) _values = np.random.randint(1, 11, n_bars) # write data to CSV with open("dummy.csv", "w") as out: out.write("Names,Values\n") for n, v in zip(_names, _values): out.write("%s,%d\n" % (n, v)) # read data from CSV with open("dummy.csv") as inp: inp.readline() names, values = zip( *[[n, int(v)] for n, v in [line.strip().split(",") for line in inp.readlines()]] ) # how many data points? how many bars in the scrollable window n_bars = len(names) n_shown = 10 # we need an Axes for the bars, a thinner Axes for the Slider bars, slider = "b", "s" fig, ax_d = plt.subplot_mosaic(bars * 19 + slider, layout="constrained") fig.suptitle("A Scrollable Window Over a Largish Plot") # plot the bars ax_d[bars].barh(names, values) ax_d[bars].axvline(color="grey", lw=1) ax_d[bars].set_xlabel("Value") ax_d[bars].set_ylabel("Name") # adjust x- and y-axis limits ax_d[bars].set_xlim(xmin=-0.2) ax_d[bars].set_ylim([-0.5, n_shown - 0.5]) # inverting the y-axis forces the names to go from top to bottom ax_d[bars].invert_yaxis() # instantiate the Slider inside the thinner Axes s = Slider( ax_d[slider], "", 0, n_bars - n_shown, orientation="vertical", valinit=0, valstep=1 ) s.valtext.set_visible(False) # ty https://stackoverflow.com/a/15477329/2749397 ax_d[slider].invert_yaxis() # the callback def update(val): # higher y value comes first because I've inverted the y-axis ax_d[bars].set_ylim([val + n_shown - 0.5, val - 0.5]) fig.canvas.draw_idle() # when we call the callback? s.on_changed(update) # That's All Folks plt.show()
heightto much bigger.