4

I have a Pandas dataframe which lists a number of companies, the number of consumer complaints which they have received within the month, and the month when they were received:

Company complaints

I am trying to create an interactive plot where all of the values under 'company' are displayed in a dropdown menu, and when a user chooses a company string, a line plot will automatically update to see how many complaints the company has received over time. I have the separate components built to some extent:

dropdown = widgets.Dropdown(options = sorted(list(set(df['company']))))

will display

dropdown

And then I can execute the following code to display a plot with the dropdown.value, either with df.plot or df.iplot:

df.plot example:

def line_plot(df, company):

    df = df[df['company'] == company]

    df.set_index('month').plot()

line_plot(df, dropdown.value)

df.plot example

df.iplot example:

df1 = df[df['company'] == dropdown.value]
df1.iplot(kind = 'line', x = 'month', y = 'complaints')

df.iplot example

Where I am having trouble is actually figuring out how to use the company name as an input for the plot that I want to generate. I have been reading up on ipywidgets and all of the examples I find use the dataframe columns themselves as the dropdown menu values rather than particular column values. I've tried the following:

@interact
def line_plot(company = sorted(df['company'].unique())):

    df = df[df['company'] == company]

    df.iplot(kind = 'line', x = company)

And get this traceback:

---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
/Applications/anaconda3/lib/python3.7/site-packages/ipywidgets/widgets/interaction.py in update(self, *args)
    254                     value = widget.get_interact_value()
    255                     self.kwargs[widget._kwarg] = value
--> 256                 self.result = self.f(**self.kwargs)
    257                 show_inline_matplotlib_plots()
    258                 if self.auto_display and self.result is not None:

<ipython-input-1040-3e3ff8e76afe> in line_plot(company)
      2 def line_plot(company = sorted(df['company'].unique())):
      3 
----> 4     df = df[df['company'] == company]
      5 
      6     df.iplot(kind = 'line', x = company)

UnboundLocalError: local variable 'df' referenced before assignment

As well as:

interactive_plot = interactive(line_plot, df = df, company = sorted(list(set(df['company']))))
interactive_plot

And receive

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
/Applications/anaconda3/lib/python3.7/site-packages/ipywidgets/widgets/interaction.py in update(self, *args)
    254                     value = widget.get_interact_value()
    255                     self.kwargs[widget._kwarg] = value
--> 256                 self.result = self.f(**self.kwargs)
    257                 show_inline_matplotlib_plots()
    258                 if self.auto_display and self.result is not None:

<ipython-input-1026-e7a7c82e3c6b> in line_plot(df, company)
      1 def line_plot(df, company):
      2 
----> 3     df = df[df['company'] == company]
      4 
      5     df.set_index('month').plot()

TypeError: string indices must be integers

Am I heading in the right direction, or is what I am trying to achieve even possible with ipywidgets? I will continue to investigate how this might work.

njrob
  • 115
  • 9
  • Why are you setting default value for company parameter of line_plot function to the list: sorted(df['company'].unique())? And I think at this point may be df is not initialized yet. Be careful with default function parameters, it's always tricky for such containers as list. – CrazyElf Dec 26 '19 at 16:42

1 Answers1

2

I have figured out a way to (kind of) achieve it, although ideally I would like that 'column' dropdown to not be visible:

Possible solution

njrob
  • 115
  • 9