如何在图表中添加过滤器

How to add filter in the graph

代码如下

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")

matplotlib.widgets

正如评论中所建议的那样,一种方法是使用 matplotlib.widgets,您可以阅读更多关于它们的信息 here, though for the actual implementation, I found most useful their examples of Sliders and Check buttons。使用你的最小示例,我能想到的最简单的改编(看起来不错)如下所示:

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 笔记本)

我建议也尝试 ipywidgets,它的用户界面比 matplotlib.widgets 好得多。您可以阅读有关 Using 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')

各种过滤设置的结果如下所示:

当然还有很多配置布局等选项

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 Embedding Jupyter Widgets in Other Contexts than the Notebook.