Code is below
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")
How to add filter in the graph itself that user has to privilege to select which product
has to display in the graph and count
also let's say if count > 11
then only Pencil has to appear.
Is there any alternate way also there to do this?
IF one column is date column can we do filtering with date column also
As suggested in the comments, one way to do this is using the matplotlib.widgets
and you can read more about them here, though for the actual implementation, I found most useful their examples of Sliders and Check buttons. Using your minimal example, the simplest adaptation I could come up with (that looks ok) would look like this:
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()
With various filtering settings, the result looks like this:
I'd suggest also trying ipywidgets
, which have a much nicer user interface than matplotlib.widgets
. You can read more about Using Interact. Using your minimal example:
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')
The result with various filtering settings looks as follows:
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 Embedding Jupyter Widgets in Other Contexts than the Notebook.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With