ays*_*ysh 4 python filtering graph widget matplotlib
代码如下
from io import StringIO
text = '''Product,Count
Pen,10
Pencil,15
Book, 10'''
df = pd.read_csv(StringIO(text))
df.plot(x="Product", y="Count", kind="bar")
Run Code Online (Sandbox Code Playgroud)
如何在图表本身中添加过滤器,用户必须有权选择哪些product
必须显示在图表中,count
并且假设count > 11
只有 Pencil 必须出现。
有没有其他方法可以做到这一点?
如果一列是日期列,我们是否也可以使用日期列进行过滤
正如评论中所建议的那样,一种方法是使用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()
Run Code Online (Sandbox Code Playgroud)
使用各种过滤设置,结果如下所示:
我建议也尝试ipywidgets
,它的用户界面比matplotlib.widgets
. 您可以阅读有关使用 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')
Run Code Online (Sandbox Code Playgroud)
具有各种过滤设置的结果如下所示:
当然,配置布局等有很多选项。
此解决方案旨在主要在Jupyter Notebook 中工作,但如果您想将此功能嵌入其他地方,您可以阅读有关在 Notebook 之外的其他上下文中嵌入 Jupyter 小部件的信息。