matplotlib.widgets
Как предлагается в комментариях, один из способов сделать это - использовать matplotlib.widgets
, и вы можете прочитать о них здесь , хотя для фактической реализации, Я нашел наиболее полезными их примеры ползунков и кнопок проверки . Используя ваш минимальный пример, простейшая адаптация, которую я мог придумать (выглядит нормально), будет выглядеть так:
import pandas as pd
from io import StringIO
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
from matplotlib.widgets import Slider, CheckButtons
text = '''Product,Count
Pen,10
Pencil,15
Book,10'''
df = pd.read_csv(StringIO(text))
fig, ax = plt.subplots()
gs = gridspec.GridSpec(
nrows = 2,
ncols = 2,
figure = fig,
wspace = 0.3,
hspace = 0.6,
height_ratios = [2,1]
)
ax.set_position(gs[0,:].get_position(fig))
axMinCount = fig.add_subplot(gs[1,0])
axProducts = fig.add_subplot(gs[1,1])
labels = ('Pen', 'Pencil', 'Book')
minimum = 5
actives = [True, True, True]
df.loc[actives & (df['Count'] >= minimum)].plot(
x = 'Product', y = 'Count', kind = 'bar', ax = ax, legend = False
)
sMinCount = Slider(axMinCount, 'Min Count', 0, 20, valinit = minimum, valstep = 1)
cProducts = CheckButtons(axProducts, labels, actives)
def update(val):
minimum = sMinCount.val
df_filtered = df.loc[actives & (df['Count'] >= minimum)]
if not df_filtered.empty:
df_filtered.plot(
x = 'Product', y = 'Count', kind = 'bar', ax = ax, legend = False
)
else:
ax.cla()
def check(label):
index = labels.index(label)
actives[index] = not actives[index]
df_filtered = df.loc[actives & (df['Count'] >= minimum)]
if not df_filtered.empty:
df_filtered.plot(
x = 'Product', y = 'Count', kind = 'bar', ax = ax, legend = False
)
else:
ax.cla()
sMinCount.on_changed(update)
cProducts.on_clicked(check)
plt.show()
С различными настройками фильтрации результат выглядит так:
ipywidgets (Jupyter notebook)
I'd suggest also trying ipywidgets
, which have a much nicer user interface than matplotlib.widgets
. You can read more about Использование Interact . Используя ваш минимальный пример:
import pandas as pd
from io import StringIO
from ipywidgets import interact
text = '''Product,Count
Pen,10
Pencil,15
Book,10'''
df = pd.read_csv(StringIO(text))
# This is a wrapper of the function that follows, providing the interactive input
@interact(MinCount = (0, 20, 1), pen = True, pencil = True, book = True)
# Note that in the core function below, you can set the starting values
def plotter_fun(MinCount = 0, pen = True, pencil = True, book = True):
# Filter the data using the interactive input
df_filtered = df.loc[(pen, pencil, book) & (df['Count'] >= MinCount)]
# If all data has been filtered out, announce it
if df_filtered.empty:
print('No data to show.')
# Otherwise plot
else:
df_filtered.plot(x = 'Product', y = 'Count', kind = 'bar')
Результат с различными настройками фильтрации выглядит следующим образом:
Of course, there are many options for configuring the layout etc.
This solution is designed to work primarily in Jupyter Notebook,
though if you'd like to embed this functionality somewhere else, you
can read about Встраивание виджетов Jupyter в другие контексты, кроме Notebook .