【问题标题】:How to add filter in the graph如何在图表中添加过滤器
【发布时间】:2020-10-07 00:08:06
【问题描述】:

代码如下

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

  • 如何在图表本身中添加过滤器,用户必须有权选择哪个product 必须在图表中显示,count 也可以说如果count > 11 那么只有铅笔必须出现。

  • 还有其他方法可以做到这一点吗?

  • 如果一列是日期列,我们也可以使用日期列进行过滤

【问题讨论】:

标签: python matplotlib graph widget filtering


【解决方案1】:

matplotlib.widgets

按照 cmets 中的建议,一种方法是使用matplotlib.widgets,您可以阅读更多关于它们的信息here,但对于实际实现,我发现它们的Sliders 和@987654323 示例最有用@。使用您的最小示例,我能想到的最简单的改编(看起来不错)如下所示:

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

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

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

此解决方案主要用于 Jupyter Notebook, 虽然如果你想将此功能嵌入到其他地方,你 可以阅读Embedding Jupyter Widgets in Other Contexts than the Notebook

【讨论】:

  • upwoting 以获得很好的解释,如果一列是日期列,我们也可以使用 date 过滤
  • @aysh 我没有看到任何为matplotlib.widgets 预先制作的东西,所以如果你要使用那个模块,你必须为日期定制一些东西。相比之下,ipywidgets 有一个专门为此而设计的 Date picker 小部件!
猜你喜欢
  • 1970-01-01
  • 2017-02-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-21
  • 2017-09-06
  • 1970-01-01
相关资源
最近更新 更多