Good day
I have been on this all day. I am trying to add widgets to my notebooks on my Jupyter(ipython) notebook. Below is my code which makes sense in my head but it is not populating anything. I am trying to control the list of values in StatusesList through a widget so it changes the graph populated. Please help.
from plotly import __version__
from plotly.offline import download_plotlyjs, init_notebook_mode, iplot
import plotly.plotly as py
import plotly.graph_objs as go
from plotly.graph_objs import *
import numpy as np
import cufflinks as cf
init_notebook_mode()
cf.go_offline()
import pandas as pd
cf.set_config_file(theme='pearl')
from __future__ import print_function
from ipywidgets import interact, interactive, fixed
import pandas as pd
import ipywidgets as widgets
from IPython.display import display
df = pd.read_excel("C:\Users\UserName\Downloads\Complaints Management.xlsx")
df_status = df[['Status', 'Member Number']].groupby('Status').count()
StatusesList = df_status.index.tolist()
GragphValueList = df_status["Member Number"].tolist()
# w = Output()
def f(x):
x = StatusesList
return x
interact(f, x = StatusesList)
fig_status = {
'data': [{'labels': x,
'values': GragphValueList,
'type': 'pie'}],
'layout': {'title': 'Complaints by status'}
}
iplot(fig_status)
file sample
I think you are looking for this type of interactivity right?
by_list = ['Priority', 'Status', 'Deadline', 'Query Category'] #df.keys().tolist()
#interact(x = by_list )
def f(x):
df_data = df[[x, 'Member Number']].groupby(x).count()
fig_status = {
'data': [{'labels': df_data.index.tolist(),
'values': df_data["Member Number"].tolist(),
'type': 'pie'}],
'layout': {'title': 'Complaints by %s' % x}
}
iplot(fig_status)
You have control over the by_list by adding or removing string corresponding to fields in your Excel. It is also possible to get all fields using df.keys().tolist() but this might be a little unstable.
PS. Thank you for showing me plotly, I hadn't heard/seen it before but it can produce some nice (interactive) statistical graphs!
Related
I am trying to pass .opts() arguments to style a holoviews .Bars graph, but all arguments are being ignored when passed. This results in the following error:
WARNING:param.Bars02978: Use of call to set options will be deprecated in the next major release (1.14.0). Use the equivalent .opts method instead.
I am on version 1.14.8.
How can I pass the .opts() so my graph can be styled appropriately?
# https://www.youtube.com/watch?v=ZWP_h6WV8h0 Connecting multiple plots
from collections import defaultdict
import panel as pn
import holoviews as hv
from holoviews import opts
import pandas as pd
import numpy as np
import pandas_bokeh
import bokeh
from bokeh.plotting import figure
from bokeh.models import ColumnDataSource, TableColumn, DataTable, DateEditor, IntEditor\
, DateFormatter, NumeralTickFormatter, CustomJS, DatePicker, widgets
from bokeh.models import Panel, Tabs, Row
from bokeh.io import show
from bokeh.layouts import Column, layout
import hvplot.pandas
hv.extension('bokeh', 'matplotlib')
renderer = hv.renderer('bokeh')
renderer = renderer.instance(mode='server')
data = {
"calories": [420],
"duration": [50],
"ggg": [60]
}
#load data into a DataFrame object:
df = pd.DataFrame(data)
print(df)
df2 = pd.DataFrame({'Missing Data': df[['calories']].sum(axis=1), 'Delayed Data': df[['duration']].sum(axis=1)
, 'Duplicate Data': df[['ggg']].sum(axis=1)})
print(df2)
bar_opts = opts.Bars(height=400, width=600, tools=["hover"], bgcolor="grey", xlabel="Wine Class", ylabel="Malic Acid", ylim=(0.0, 3.5))
bars = hv.Bars(pd.melt(df2.reset_index(), ['index']), ['index', 'variable'], 'value', label='dl_refined_analytics').opts(bar_opts)
bars.opts(height=400, width=600, tools=["hover"], bgcolor="grey", xlabel="Wine Class", ylabel="Malic Acid", ylim=(0.0, 3.5))
dmap = hv.DynamicMap(bars)
app = pn.Row(dmap)
app.show() ```
What was the intent behind hv.DynamicMap(bars)? I'm not sure why you'd want to pass the bars object to a DynamicMap constructor, and if you just use app = pn.Row(bars) instead of app = pn.Row(dmap) it should work fine.
I have a 2D plotly graph with a hover feature. When you hover over each point, the label (e.g. 'image 2, cluster 1') associated with that point appears. I'd like for label to be appended onto an existing list if I were to click on the point (rather than just hover over it). The reason why is that I'd later like to use the data of this point to perform another task. Is there an example online that demonstrates how to do this-- have looked through the documentation but haven't found something for this yet. Thanks!
The hoverData that is available to you by default, with some sample data, is this:
{
"points": [
{
"curveNumber": 1,
"pointNumber": 7,
"pointIndex": 7,
"x": 1987,
"y": 74.32,
"bbox": {
"x0": 420.25,
"x1": 426.25,
"y0": 256,
"y1": 262
}
}
]
}
I'm not quite sure what you mean by 'label', so I can only assume that it would be the name of a trace or something similar, like in this example from the Plotly docs:
But as you can see, that's not readily available in the hoverData dict. This means that you'll have to use this information to reference your figure structure as well, so that you end up with something like this:
[['New Zealand', 2002, 79.11]]
And that's not a problem as long as you're willing to use Plotly Dash. I've made a complete setup for you that should meet your requirements. In the app in the image below you'll find a figure along with two output fields for strings. The first field shows the info from that last point you've clicked in the figure. On every click, a new element is added to a list named store. The last fields shows the complete information from the same click.
The answer to your question is, yes, there is a way to save the data of a clicked point in a list. And one way to do so is through the following callback that uses clickdata to reference your figure object, store those references in a list, and append new elements every time you click a new element.
App
Complete code:
import json
from textwrap import dedent as d
import pandas as pd
import plotly.graph_objects as go
import numpy as np
import dash
from dash import dcc
import dash_html_components as html
import plotly.express as px
from dash.dependencies import Input, Output
from jupyter_dash import JupyterDash
import warnings
warnings.simplefilter(action='ignore', category=FutureWarning)
# app info
app = JupyterDash(__name__)
styles = {
'pre': {
'border': 'thin lightgrey solid',
'overflowX': 'scroll'
}
}
# data
df = px.data.gapminder().query("continent=='Oceania'")
# plotly figure
fig = px.line(df, x="year", y="lifeExp", color="country", title="No label selected")
fig.update_traces(mode="markers+lines")
app.layout = html.Div([
dcc.Graph(
id='figure1',
figure=fig,
),
html.Div(className
='row', children=[
html.Div([
dcc.Markdown(d("""Hoverdata using figure references""")),
html.Pre(id='hoverdata2', style=styles['pre']),
], className='three columns'),
html.Div([
dcc.Markdown(d("""
Full hoverdata
""")),
html.Pre(id='hoverdata1', style=styles['pre']),
], className='three columns')
]),
])
# container for clicked points in callbacks
store = []
#app.callback(
Output('figure1', 'figure'),
Output('hoverdata1', 'children'),
Output('hoverdata2', 'children'),
[Input('figure1', 'clickData')])
def display_hover_data(hoverData):
if hoverData is not None:
traceref = hoverData['points'][0]['curveNumber']
pointref = hoverData['points'][0]['pointNumber']
store.append([fig.data[traceref]['name'],
fig.data[traceref]['x'][pointref],
fig.data[traceref]['y'][pointref]])
fig.update_layout(title = 'Last label was ' + fig.data[traceref]['name'])
return fig, json.dumps(hoverData, indent=2), str(store)
else:
return fig, 'None selected', 'None selected'
app.run_server(mode='external', port = 7077, dev_tools_ui=True,
dev_tools_hot_reload =True, threaded=True)
You need to use callbacks to perform this type of action (register on_click()). Have defined clicked as a list of clicked points. Demonstrated how this can be achieved with ipwidgets or dash
ipwidgets
import numpy as np
import plotly.express as px
import plotly.graph_objects as go
import ipywidgets as widgets
from pathlib import Path
import json
x = np.random.uniform(-10, 10, size=50)
y = np.sin(x)
clicked = []
# construct figure that has holders for points, interpolated line and final lines
fig = go.FigureWidget(
[
go.Scatter(x=x, y=y, mode="markers", name="base_points"),
]
)
fig.update_layout(template="simple_white")
out = widgets.Output(layout={"border": "1px solid black"})
out.append_stdout("Output appended with append_stdout\n")
# create our callback function
#out.capture()
def base_click(trace, points, selector):
global clicked
clicked.append(points.__dict__)
fig.data[0].on_click(base_click)
widgets.HBox([fig, out])
dash
from jupyter_dash import JupyterDash
import dash
from dash.dependencies import Input, Output, State
import numpy as np
import json
clicked = []
# Build App
app = JupyterDash(__name__)
app.layout = dash.html.Div(
[
dash.dcc.Graph(
id="fig",
figure=go.Figure(go.Scatter(x=x, y=y, mode="markers", name="base_points")),
),
dash.html.Div(id="debug"),
]
)
#app.callback(
Output("debug", "children"),
Input("fig", "clickData"),
)
def point_clicked(clickData):
global clicked
clicked.append(clickData)
return json.dumps(clickData)
# Run app and display result inline in the notebook
app.run_server(mode="inline")
I have an input field, button and output placed in a Jupyter notebook using a function. On the button there is an on_click that will trigger a function that will plot a graph in the output. However, this function is using another function to generate the data for the graph. Now I want to show the progress of this 2nd function in the output. How would I go about doing this?
I looked into using tqdm, but then I just get the initial progress bar in the log (which doesn't update), not in the notebook cell
from random import randint
from matplotlib import pyplot as plt
from tqdm.notebook import tqdm
from ipywidgets import Layout, Button, Box, FloatText, Label, Output
def form_plot_simulation():
button = Button(
description='Plot simulation results',
disabled=False,
tooltip='Plot simulation results')
global simulations_field
simulations_field = FloatText(value='10')
global out_plot_sim
out_plot_sim = Output()
button.on_click(plot_data)
form_items = [
Box([simulations_field]),
Box([button]),
Box([out_plot_sim])
]
form_plot_sim = Box(form_items, layout=Layout(
display='flex',
flex_flow='column',
border='solid 2px',
align_items='stretch',
width='600px'))
return form_plot_sim
def plot_data(b):
simulations = int(simulations_field.value)
data = simulate_test(simulations)
plt.figure(figsize=(12,8))
plt.plot(data)
with out_plot_sim:
out_plot_sim.clear_output()
plt.show()
def simulate_test(simulations):
data = []
for i in tqdm(range(0,simulations)):
datapoint = randint(0,10)
data.append(datapoint)
return data
The cell in the notebook just has this code to display the form:
display(form_plot_simulation())
EDIT: Note: I hate the usage of global, but didn't know how to pass the field value on in the functions.
I don't have tqdm here, but you can adapt your example. I used a functools partial to bundle another argument to the on_click function.
from random import randint
from matplotlib import pyplot as plt
# from tqdm.notebook import tqdm
from ipywidgets import Layout, Button, Box, FloatText, Label, Output
import time
import functools
def form_plot_simulation():
button = Button(
description='Plot simulation results',
disabled=False,
tooltip='Plot simulation results')
global simulations_field
simulations_field = FloatText(value='10')
global out_plot_sim
out_plot_sim = Output()
output_progress = Output(height='20px')
button.on_click(functools.partial(plot_data, output_progress))
form_items = [
simulations_field,
button,
output_progress,
out_plot_sim,
]
form_plot_sim = Box(form_items, layout=Layout(
display='flex',
flex_flow='column',
border='solid 2px',
align_items='stretch',
width='600px'))
return form_plot_sim
def plot_data(output_widget, b):
simulations = int(simulations_field.value)
data = simulate_test(simulations, output_widget)
plt.figure(figsize=(12,8))
plt.plot(data)
with out_plot_sim:
out_plot_sim.clear_output()
plt.show()
def simulate_test(simulations, output_widget):
data = []
for i in range(0,simulations):
datapoint = randint(0,10)
data.append(datapoint)
time.sleep(0.1)
with output_widget:
output_widget.clear_output()
print(i)
return data
I am developing dashboard using Dash Plotly and I am getting an error when I click tabs.
The error says null is not an object (evaluating ‘n.layout’)
(This error originated from the built-in JavaScript code that runs Dash apps. Click to see the full stack trace or open your browser’s console.)"
Can any one help me to solve this problem?
My code is found below.
import dash
import dash_core_components as dcc
import dash_html_components as html
import dash_daq as daq
from dash.dependencies import Input, Output
import plotly.graph_objs as go
import pandas as pd
import numpy as np
from copy import copy
import dash_table
import json
import base64
import plotly.express as px
#Data
errors = pd.read_csv(r’/Users/kapital/Documents/ABCD/PM/errors.csv’)
external_stylesheets = [‘https://codepen.io/chriddyp/pen/bWLwgP.css’]
app = dash.Dash(name, external_stylesheets=external_stylesheets)
first_graph = dcc.Graph(id=‘graph1’,style={‘borderBottom’: ‘thin lightgrey solid’,‘padding’: ‘10px 5px’})
#, animate = True
content_tab_1 = html.Div(children = [
html.Div(first_graph, style = {‘vertical-align’:‘center’, ‘horizontal-align’:‘center’})
],
style={‘width’: ‘87%’})
app.layout = html.Div([
dcc.Tabs(id='tabs-example', value='tab-1', children=[
dcc.Tab(label='Tab one', value='tab-1',
children =[content_tab_1]),
dcc.Tab(label='Tab two', value='tab-2'),
]),
html.Div(id='tabs-example-content')
])
#app.callback(Output(‘graph1’, ‘figure’),
Input(‘tabs-example’, ‘value’))
def render_content(tab):
if tab == ‘tab-1’:
err_count = pd.DataFrame(errors['errorID'].value_counts().reset_index().values, columns=["Error", "Count"])
err_count = err_count.sort_index(axis = 0, ascending=True)
fig = px.bar(err_count, x = 'Error', y = 'Count')
return fig
# return html.Div([
# html.H3('Tab content 1')
# ])
if name == ‘main’:
app.run_server(debug=True)
The problem is that your callback function does not have an else to its conditional statement. When the user selects the second tab, that callback has no alternate path, and returns None, which gives you the error you see. I did this to fix it, but you'll probably want something more:
#app.callback(Output('graph1', 'figure'),
Input('tabs-example', 'value'))
def render_content(tab):
if tab == 'tab-1':
err_count = pd.DataFrame.from_dict(dict(
Error=[1, 2, 3, ],
Count=[5, 6, 7])
)
err_count = err_count.sort_index(axis=0, ascending=True)
fig = px.bar(err_count, x='Error', y='Count')
return fig
else:
return {}
import nltk
from nltk.chat.util import Chat, reflections
import pandas as pd
import ipywidgets as widgets
from ipywidgets import interact, interact_manual,fixed
df = pd.read_excel (r'C:\Users\Desktop\ex\ex_dataset.xlsx', sheet_name='Sheet3')
print ('Travel Suggestion')
pairs=[
['My name is (.*)',['hi %1']],
['What is Travel Suggestion',['Travel Suggestion is suggest the best of Restaurant or Tourist attraction']],
]
widgets.interact_manual.opts['manual_name'] = 'Restaurant'
def Restaurant():
print(df)
interact_manual(Restaurant)
chat = Chat(pairs,reflections)
chat.converse()
By the time chat.converse() is running, you can not run anything else in the notebook.
Here is a workaround that should fit your needs:
cell[1]:
import nltk
from nltk.chat.util import Chat, reflections
import pandas as pd
import ipywidgets as widgets
from ipywidgets import interact, interact_manual,fixed
df = pd.read_excel (r'C:\Users\Desktop\ex\ex_dataset.xlsx', sheet_name='Sheet3')
print ('Travel Suggestion')
pairs=[
['My name is (.*)',['hi %1']],
['What is Travel Suggestion',['Travel Suggestion is suggest the best of Restaurant or Tourist attraction']],
]
widgets.interact_manual.opts['manual_name'] = 'Restaurant'
def Restaurant():
print(df)
interact_manual(Restaurant)
chat = Chat(pairs,reflections)
cell[2]:
chat.converse()