Dash in python - callback error about scatter plot and dropdown - python

I'm studying dash library.
This code showing the scatter plot when i select column in the data frame.
This works without any problem, but call back error occurs on the web page.
on the web, callback error updating spas-graph.figure
i can't understand why this error occurs.
[import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import plotly.graph_objects as go
import pandas as pd
df = pd.DataFrame({
'depth' : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
'upper_value' : [1, 4, 6, 2, 6, 8, 9, 10, 4, 2],
'middle_value' : [5, 3, 7, 8, 1, 2, 3, 1, 4, 8],
'down_value' : [6, 2, 1, 10, 5, 2, 3, 4, 2, 7]
})
col_list = df.columns[1:4]
app = dash.Dash(__name__)
app.layout = html.Div([
dcc.Dropdown(
id = 'select-cd',
options = [
{'label' : i, 'value' : i}
for i in col_list
]
),
dcc.Graph(id = 'spas-graph')
])
#app.callback(
Output('spas-graph', 'figure'),
[Input('select-cd', 'value')]
)
def update_figure(selected_col):
return {
'data' : [go.Scatter(
x = df[selected_col],
y = df['depth'],
mode = 'lines + markers',
marker = {
'size' : 15,
'opacity' : 0.5,
'line' : {'width' : 0.5, 'color' : 'white'}
}
)],
'layout' : go.Layout(
xaxis={'title': 'x_scale'},
yaxis={'title': 'y_scale'},
hovermode='closest'
)
}
if __name__ == '__main__':
app.run_server(debug=True)

You have not defined the value parameter in your dropdown method. So when the server starts the first input it picks up is a None value.
You can solve it in two ways:
Add a default value in the Dropdown:
Handle None value in the callback method
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import plotly.graph_objects as go
import pandas as pd
df = pd.DataFrame({
'depth' : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
'upper_value' : [1, 4, 6, 2, 6, 8, 9, 10, 4, 2],
'middle_value' : [5, 3, 7, 8, 1, 2, 3, 1, 4, 8],
'down_value' : [6, 2, 1, 10, 5, 2, 3, 4, 2, 7]
})
col_list = df.columns[1:4]
app = dash.Dash(__name__)
app.layout = html.Div([
dcc.Dropdown(
id = 'select-cd',
options = [
{'label' : i, 'value' : i}
for i in col_list
],
value = col_list[0]
),
dcc.Graph(id = 'spas-graph')
])
#app.callback(
Output('spas-graph', 'figure'),
[Input('select-cd', 'value')]
)
def update_figure(selected_col):
if selected_col is None:
selected_col = col_list[0]
return {
'data' : [go.Scatter(
x = df[selected_col],
y = df['depth'],
mode = 'lines + markers',
marker = {
'size' : 15,
'opacity' : 0.5,
'line' : {'width' : 0.5, 'color' : 'white'}
}
)],
'layout' : go.Layout(
xaxis={'title': 'x_scale'},
yaxis={'title': 'y_scale'},
hovermode='closest'
)
}

Related

Drawing custom error bars when using plotly subplots

This question is closely related to an earlier one that I posted. I would like to draw confidence intervals for each bar within subplots of a figure, using the information from two columns in my data frame describing the upper and lower limit of each confidence interval. I tried to use the solution from that earlier post, but it does not seem to be applicable when one wants to use different colors and/or different rows in order to draw subplots for the figure.
For example, the following code does not produce the right confidence intervals. For instance, the CI of the 3rd bar in the second row should go from 11 to 5:
import pandas as pd
import plotly.express as px
df = pd.DataFrame(
{"x": [0, 1, 2, 3, 0, 1, 2, 3],
"y": [6, 10, 2, 5, 8, 9, 10, 11],
"ci_upper": [8, 11, 2.5, 4, 9, 10, 11, 12],
"ci_lower": [5, 9, 1.5, 3, 7, 6, 5, 10],
"state": ['foo','foo','foo','foo','bar','bar','bar','bar'],
"color": ['0','0','1','1','0','0','1','1']}
)
fig = px.bar(df, x="x", y="y",facet_row='state',color='color').update_traces(
error_y={
"type": "data",
"symmetric": False,
"array": df["ci_upper"] - df["y"],
"arrayminus": df["y"] - df["ci_lower"],
}
)
fig.update_yaxes(dtick=1)
fig.show(renderer='png')
it's the same technique but solution needs to consider it's multiple traces (4 in this example)
encoded in hovertemplate of each trace are the facet and color. Extract these and filter data down to appropriate rows
then build instruction for error bars as with simpler condition
import pandas as pd
import plotly.express as px
df = pd.DataFrame(
{
"x": [0, 1, 2, 3, 0, 1, 2, 3],
"y": [6, 10, 2, 5, 8, 9, 10, 11],
"ci_upper": [8, 11, 2.5, 4, 9, 10, 11, 12],
"ci_lower": [5, 9, 1.5, 3, 7, 6, 5, 10],
"state": ["foo", "foo", "foo", "foo", "bar", "bar", "bar", "bar"],
"color": ["0", "0", "1", "1", "0", "0", "1", "1"],
}
)
fig = px.bar(df, x="x", y="y", facet_row="state", color="color")
fig.update_yaxes(dtick=1)
def error_facet(t):
# filter data frame based on contents of hovertemplate
d = df.query(
" and ".join(
[
f"{q.split('=')[0]}==\"{q.split('=')[1]}\""
for q in t.hovertemplate.split("<br>")[0:2]
]
)
)
t.update(
{
"error_y": {
"type": "data",
"symmetric": False,
"array": d["ci_upper"] - d["y"],
"arrayminus": d["y"] - d["ci_lower"],
}
}
)
fig.for_each_trace(error_facet)
fig

Drop down menu for Plotly graph

Here is my dataframe:
df = pd.DataFrame({"Date":["2020-01-27","2020-02-27","2020-03-27","2020-04-27", "2020-05-27", "2020-06-27", "2020-07-27",
"2020-01-27","2020-02-27","2020-03-27","2020-04-27", "2020-05-27", "2020-06-27", "2020-07-27"],
"A_item":[2, 8, 0, 1, 8, 10, 4, 7, 2, 15, 5, 12, 10, 7],
"B_item":[1, 7, 10, 6, 5, 9, 2, 5, 6, 1, 2, 6, 15, 8],
"C_item":[9, 2, 9, 3, 9, 18, 7, 2, 8, 1, 2, 8, 1, 3],
"Channel_type":["Chanel_1", "Chanel_1", "Chanel_1", "Chanel_1", "Chanel_1", "Chanel_1", "Chanel_1",
"Chanel_2", "Chanel_2", "Chanel_2", "Chanel_2", "Chanel_2", "Chanel_2", "Chanel_2"]
})
I want to plot a group Bar chart with the dropdown filter on the Channel_type col. That's what I am trying:
trace2 = go.Bar(x=df["Date"], y=df[["B_item"]])
trace3 = go.Bar(x=df["Date"], y=df[["C_item"]])
list_updatemenus = [{'label': 'All',
'method': 'update',
'args': [{'visible': [True, True]}, {'title': 'All'}]},
{'label': 'Chanel_1',
'method': 'update',
'args': [{'visible': [True, False]}, {'title': 'Chanel_1'}]},
{'label': 'Chanel_2',
'method': 'update',
'args': [{'visible': [False, True]}, {'title': 'Chanel_2'}]}]
data = [trace1,trace2,trace3]
layout=go.Layout(title='Distribution of Sales by Region',updatemenus=list([dict(buttons= list_updatemenus)]),width=1000,height=800,barmode='group')
fig = go.Figure(data,layout)
fig.show()
And not getting the desired output:Plot 1
As it filters the graph by the "A_item", "B_item" and "C_item" while I would like to filter it by the Channel_type col as mentioned.
So the ideal result would be the below graph, but with the dropdown menu that changes the graph based on Channel_type :
Plot 2
I am able to solve the problem with Ipywidgets in the Jupyter notebook, but it’s not really working for my particular task. Here is the code:
from plotly import graph_objs as go
import ipywidgets as w
from IPython.display import display
x = 'Date'
y1 = 'A_item'
y2 = 'B_item'
y3 = 'C_item'
trace1 = {
'x': df[x],
'y': df[y1],
'type': 'bar',
'name':'A_item'
}
trace2={
'x': df[x],
'y': df[y2],
'type': 'bar',
'name':'B_item'
}
trace3 = {
'x': df[x],
'y': df[y3],
'type': 'bar',
'name':'C_item',
}
data = [trace1, trace2, trace3]
# Create layout for the plot
layout=dict(
title='Channels',
width=1200, height=700, title_x=0.5,
paper_bgcolor='#fff',
plot_bgcolor="#fff",
xaxis=dict(
title='Date',
type='date',
tickformat='%Y-%m-%d',
gridcolor='rgb(255,255,255)',
zeroline= False,
),
yaxis=dict(
title='My Y-axis',
zeroline= False
)
)
fig = go.FigureWidget(data=data, layout=layout)
def update_fig(change):
aux_df = df[df.Channel_type.isin(change['new'])]
with fig.batch_update():
for trace, column in zip(fig.data, [y1, y2, y3]):
trace.x = aux_df[x]
trace.y = aux_df[column]
drop = w.Dropdown(options=[
('All', ['Chanel_1', 'Chanel_2']),
('Chanel_1', ['Chanel_1']),
('Chanel_2', ['Chanel_2']),
])
drop.observe(update_fig, names='value')
display(w.VBox([drop, fig]))
And here is the output:
The problem is that I am not able to wrap the VBox into an HTML file and save the dropdown menu. Also, it isn’t working in the Python shell as it is intended for the Jupyter notebook, and I need to share it.
So the ideal result would be to wrap the last figure within the Plotly fig only without the ipywidgets.
Any help be really appreciated!
Thank you!
The most important thing to note is that for go.Bar, if you have n dates in the x parameter and you pass a 2D array of dimension (m, n) to the y parameter of go.Bar, Plotly understands to create a grouped bar chart with each date n having m bars.
For your DataFrame, something like df[df['Channel_type'] == "Channel_1"][items].T.values will reshape it as needed. So we can apply this to the y field of args that we pass the to the buttons we make.
Credit to #vestland for the portion of the code making adjustments to the buttons to make it a dropdown.
import pandas as pd
import plotly.graph_objects as go
df = pd.DataFrame({"Date":["2020-01-27","2020-02-27","2020-03-27","2020-04-27", "2020-05-27", "2020-06-27", "2020-07-27",
"2020-01-27","2020-02-27","2020-03-27","2020-04-27", "2020-05-27", "2020-06-27", "2020-07-27"],
"A_item":[2, 8, 0, 1, 8, 10, 4, 7, 2, 15, 5, 12, 10, 7],
"B_item":[1, 7, 10, 6, 5, 9, 2, 5, 6, 1, 2, 6, 15, 8],
"C_item":[9, 2, 9, 3, 9, 18, 7, 2, 8, 1, 2, 8, 1, 3],
"Channel_type":["Channel_1", "Channel_1", "Channel_1", "Channel_1", "Channel_1", "Channel_1", "Channel_1",
"Channel_2", "Channel_2", "Channel_2", "Channel_2", "Channel_2", "Channel_2", "Channel_2"]
})
fig = go.Figure()
colors = ['#636efa','#ef553b','#00cc96']
items = ["A_item","B_item","C_item"]
for item, color in zip(items, colors):
fig.add_trace(go.Bar(
x=df["Date"], y=df[item], marker_color=color
))
# one button for each df column
# slice the DataFrame and apply transpose to reshape it correctly
updatemenu= []
buttons=[]
for channel in df['Channel_type'].unique():
buttons.append(dict(method='update',
label=channel,
args=[{
'y': df[df['Channel_type'] == channel][items].T.values
}])
)
## add a button for both channels
buttons.append(dict(
method='update',
label='Both Channels',
args=[{
'y': df[items].T.values
}])
)
# some adjustments to the updatemenu
# from code by vestland
updatemenu=[]
your_menu=dict()
updatemenu.append(your_menu)
updatemenu[0]['buttons']=buttons
updatemenu[0]['direction']='down'
updatemenu[0]['showactive']=True
fig.update_layout(updatemenus=updatemenu)
fig.show()

Convert JSON to Excel by Python

I have a JSON that need to convert to Excel.
I'm using Python 3.8 with xlsxwriter library.
Below is sample JSON.
{
"companyId": "123456",
"companyName": "Test",
"companyStatus": "ACTIVE",
"document": {
"employee": {
"employeeId": "EM1567",
"employeeLastName": "Test Last",
"employeeFirstName": "Test Fist"
},
"expenseEntry": [
{
"allocation": [
{
"allocationId": "03B249B3598",
"journal": [
{
"journalAccountCode": "888",
"journalPayee": "EMPL",
"journalPayer": "COMP",
"taxGuid": [
"51645A638114E"
]
},
{
"journalAccountCode": "999",
"journalPayee": "EMPL",
"journalPayer": "EMPL",
"taxGuid": [
"8114E51645A63"
]
},
],
"tax": [
{
"taxCode": "TAX123",
"taxSource": "SYST"
},
{
"taxCode": "TAX456",
"taxSource": "SYST"
}
]
}
],
"approvedAmount": 200.0,
"entryDate": "2020-12-10",
"entryId": "ENTRY9988"
}
],
"report": {
"currencyCode": "USD",
"reportCreationDate": "2020-12-10",
"reportId": "ACA849BBB",
"reportName": "Test Report",
"totalApprovedAmount": 200.0
}
},
"id": "c71b7d756f549"
}
And my current code:
https://repl.it/#tonyiscoming/jsontoexcel
I tried with pandas
import pandas as pd
df = pd.json_normalize(data, max_level=5)
df.to_excel('test.xlsx', index=False)
And got the result
I tried with json_excel_converter
from json_excel_converter import Converter
from json_excel_converter.xlsx import Writer
conv = Converter()
conv.convert(data, Writer(file='test.xlsx'))
And got the result
This is my expectation
Would anyone please help me in this case? Thank you so much.
Here is the code what you are looking for. I did this using XlsxWriter package. First I made the template with some cell format stuff. After that, I entered values using according to your JSON.
import xlsxwriter
from itertools import zip_longest
data = [
{
"companyId": "123456",
"companyName": "Test",
"companyStatus": "ACTIVE",
"document": {
"employee": {
"employeeId": "EM1567",
"employeeLastName": "Test Last",
"employeeFirstName": "Test Fist"
},
"expenseEntry": [
{
"allocation": [
{
"allocationId": "03B249B3598",
"journal": [
{
"journalAccountCode": "888",
"journalPayee": "EMPL",
"journalPayer": "COMP",
"taxGuid": [
"51645A638114E"
]
},
{
"journalAccountCode": "999",
"journalPayee": "EMPL",
"journalPayer": "EMPL",
"taxGuid": [
"8114E51645A63"
]
},
],
"tax": [
{
"taxCode": "TAX123",
"taxSource": "SYST"
},
{
"taxCode": "TAX456",
"taxSource": "SYST"
}
]
}
],
"approvedAmount": 200.0,
"entryDate": "2020-12-10",
"entryId": "ENTRY9988"
}
],
"report": {
"currencyCode": "USD",
"reportCreationDate": "2020-12-10",
"reportId": "ACA849BBB",
"reportName": "Test Report",
"totalApprovedAmount": 200.0
}
},
"id": "c71b7d756f549"
}
]
xlsx_file = 'your_file_name_here.xlsx'
# define the excel file
workbook = xlsxwriter.Workbook(xlsx_file)
# create a sheet for our work, defaults to Sheet1.
worksheet = workbook.add_worksheet()
# common merge format
merge_format = workbook.add_format({'align': 'center', 'valign': 'vcenter'})
# set all column width to 20
worksheet.set_column('A:V', 20)
# column wise template creation (A-V)
worksheet.merge_range(0, 0, 4, 0, 'companyId', merge_format) # A
worksheet.merge_range(0, 1, 4, 1, 'companyName', merge_format) # B
worksheet.merge_range(0, 2, 4, 2, 'companyStatus', merge_format) # C
worksheet.merge_range(0, 3, 0, 20, 'document', merge_format) # C-U
worksheet.merge_range(1, 3, 1, 5, 'employee', merge_format) # D-F
worksheet.merge_range(2, 3, 4, 3, 'employeeId', merge_format) # D
worksheet.merge_range(2, 4, 4, 4, 'employeeLastName', merge_format) # E
worksheet.merge_range(2, 5, 4, 5, 'employeeFirstName', merge_format) # F
worksheet.merge_range(1, 6, 1, 15, 'expenseEntry', merge_format) # G-P
worksheet.merge_range(2, 6, 2, 12, 'allocation', merge_format) # G-M
worksheet.merge_range(3, 6, 4, 6, 'allocationId', merge_format) # G
worksheet.merge_range(3, 7, 3, 10, 'journal', merge_format) # H-K
worksheet.write(4, 7, 'journalAccountCode') # H
worksheet.write(4, 8, 'journalPayee') # I
worksheet.write(4, 9, 'journalPayer') # J
worksheet.write(4, 10, 'taxGuid') # K
worksheet.merge_range(3, 11, 3, 12, 'tax', merge_format) # L-M
worksheet.write(4, 11, 'taxCode') # L
worksheet.write(4, 12, 'taxSource') # M
worksheet.merge_range(2, 13, 4, 13, 'approvedAmount', merge_format) # N
worksheet.merge_range(2, 14, 4, 14, 'entryDate', merge_format) # O
worksheet.merge_range(2, 15, 4, 15, 'entryId', merge_format) # P
worksheet.merge_range(1, 16, 1, 20, 'report', merge_format) # Q-U
worksheet.merge_range(2, 16, 4, 16, 'currencyCode', merge_format) # Q
worksheet.merge_range(2, 17, 4, 17, 'reportCreationDate', merge_format) # R
worksheet.merge_range(2, 18, 4, 18, 'reportId', merge_format) # S
worksheet.merge_range(2, 19, 4, 19, 'reportName', merge_format) # T
worksheet.merge_range(2, 20, 4, 20, 'totalApprovedAmount', merge_format) # U
worksheet.merge_range(0, 21, 4, 21, 'id', merge_format) # V
# inserting data
row = 5
for obj in data:
worksheet.write(row, 0, obj.get('companyId'))
worksheet.write(row, 1, obj.get('companyName'))
worksheet.write(row, 2, obj.get('companyStatus'))
document = obj.get('document', {})
# employee details
employee = document.get('employee', {})
worksheet.write(row, 3, employee.get('employeeId'))
worksheet.write(row, 4, employee.get('employeeLastName'))
worksheet.write(row, 5, employee.get('employeeFirstName'))
# report details
report = document.get('report', {})
worksheet.write(row, 16, report.get('currencyCode'))
worksheet.write(row, 17, report.get('reportCreationDate'))
worksheet.write(row, 18, report.get('reportId'))
worksheet.write(row, 19, report.get('reportName'))
worksheet.write(row, 20, report.get('totalApprovedAmount'))
worksheet.write(row, 21, obj.get('id'))
# expenseEntry details
expense_entries = document.get('expenseEntry', [])
for expense_entry in expense_entries:
worksheet.write(row, 13, expense_entry.get('approvedAmount'))
worksheet.write(row, 14, expense_entry.get('entryDate'))
worksheet.write(row, 15, expense_entry.get('entryId'))
# allocation details
allocations = expense_entry.get('allocation', [])
for allocation in allocations:
worksheet.write(row, 6, allocation.get('allocationId'))
# journal and tax details
journals = allocation.get('journal', [])
taxes = allocation.get('tax', [])
for journal_and_tax in list(zip_longest(journals, taxes)):
journal, tax = journal_and_tax
worksheet.write(row, 7, journal.get('journalAccountCode'))
worksheet.write(row, 8, journal.get('journalPayee'))
worksheet.write(row, 9, journal.get('journalPayer'))
worksheet.write(row, 11, tax.get('taxCode'))
worksheet.write(row, 12, tax.get('taxSource'))
# taxGuid details
tax_guides = journal.get('taxGuid', [])
if not tax_guides:
row = row + 1
continue
for tax_guide in tax_guides:
worksheet.write(row, 10, tax_guide)
row = row + 1
# finally close the created excel file
workbook.close()
One thing, instead of creating a template in the script you can make your own one and save it somewhere else. Then get the copy of that template and just add data using the script. This will give you a chance to make your own base template, otherwise, you have to format your excel using the script, such as border formattings, merge cells, etc.
I used zip_longest python built-in function from itertools to zip journal and tax objects. Just follow Python – Itertools.zip_longest() or Python's zip_longest Function article for examples. If you didn't understand anything from my code, please comment below.
Having empty cells in an Excel Grid is not something really "propper", which is why json_excel_converter beahaves like this.
So, If you want to achieve this, I'm afraid you'll have to develop it all by yourself.

Plotly: How to change variable/label names for the legend in a plotly express line chart?

I want to change the variable/label names in plotly express in python. I first create a plot:
import pandas as pd
import plotly.express as px
d = {'col1': [1, 2, 3], 'col2': [3, 4, 5]}
df = pd.DataFrame(data=d)
fig = px.line(df, x=df.index, y=['col1', 'col2'])
fig.show()
Which yields:
I want to change the label names from col1 to hello and from col2 to hi. I have tried using labels in the figure, but I cannot get it to work:
fig = px.line(df, x=df.index, y=['col1', 'col2'], labels={'col1': "hello", 'col2': "hi"})
fig.show()
But this seems to do nothing, while not producing an error. Obviously I could achieve my goals by changing the column names, but the actual plot i'm trying to create doesn't really allow for that since it comes from several different dataframes.
The answer:
Without changing the data source, a complete replacement of names both in the legend, legendgroup and hovertemplate will require:
newnames = {'col1':'hello', 'col2': 'hi'}
fig.for_each_trace(lambda t: t.update(name = newnames[t.name],
legendgroup = newnames[t.name],
hovertemplate = t.hovertemplate.replace(t.name, newnames[t.name])
)
)
Plot:
The details:
Using
fig.for_each_trace(lambda t: t.update(name = newnames[t.name]))
...you can change the names in the legend without ghanging the source by using a dict
newnames = {'col1':'hello', 'col2': 'hi'}
...and map new names to the existing col1 and col2 in the following part of the figure structure (for your first trace, col1):
{'hovertemplate': 'variable=col1<br>index=%{x}<br>value=%{y}<extra></extra>',
'legendgroup': 'col1',
'line': {'color': '#636efa', 'dash': 'solid'},
'mode': 'lines',
'name': 'hello', # <============================= here!
'orientation': 'v',
'showlegend': True,
'type': 'scatter',
'x': array([0, 1, 2], dtype=int64),
'xaxis': 'x',
'y': array([1, 2, 3], dtype=int64),
'yaxis': 'y'},
But as you can see, this doesn't do anything with 'legendgroup': 'col1', nor 'hovertemplate': 'variable=col1<br>index=%{x}<br>value=%{y}<extra></extra>' And depending on the complexity of your figure, this can pose a problem. So I would add legendgroup = newnames[t.name] and hovertemplate = t.hovertemplate.replace(t.name, newnames[t.name])into the mix.
Complete code:
import pandas as pd
import plotly.express as px
from itertools import cycle
d = {'col1': [1, 2, 3], 'col2': [3, 4, 5]}
df = pd.DataFrame(data=d)
fig = px.line(df, x=df.index, y=['col1', 'col2'])
newnames = {'col1':'hello', 'col2': 'hi'}
fig.for_each_trace(lambda t: t.update(name = newnames[t.name],
legendgroup = newnames[t.name],
hovertemplate = t.hovertemplate.replace(t.name, newnames[t.name])
)
)
Add the "name" parameter: go.Scatter(name=...)
Source https://plotly.com/python/figure-labels/
fig = go.Figure()
fig.add_trace(go.Scatter(
x=[0, 1, 2, 3, 4, 5, 6, 7, 8],
y=[0, 1, 2, 3, 4, 5, 6, 7, 8],
name="Name of Trace 1" # this sets its legend entry
))
fig.add_trace(go.Scatter(
x=[0, 1, 2, 3, 4, 5, 6, 7, 8],
y=[1, 0, 3, 2, 5, 4, 7, 6, 8],
name="Name of Trace 2"
))
fig.update_layout(
title="Plot Title",
xaxis_title="X Axis Title",
yaxis_title="X Axis Title",
legend_title="Legend Title",
font=dict(
family="Courier New, monospace",
size=18,
color="RebeccaPurple"
)
)
fig.show()
This piece of code is more concise.
import pandas as pd
import plotly.express as px
df = pd.DataFrame(data={'col1': [1, 2, 3], 'col2': [3, 4, 5]})
series_names = ["hello", "hi"]
fig = px.line(data_frame=df)
for idx, name in enumerate(series_names):
fig.data[idx].name = name
fig.data[idx].hovertemplate = name
fig.show()
If you're looking for something even more concise, this function does the job-
def custom_legend_name(new_names):
for i, new_name in enumerate(new_names):
fig.data[i].name = new_name
Then before fig.show(), just pass a list consisting of the names you want, to the function, like this custom_legend_name(['hello', 'hi'])
Here's what the complete code would look like-
def custom_legend_name(new_names):
for i, new_name in enumerate(new_names):
fig.data[i].name = new_name
import pandas as pd
import plotly.express as px
d = {'col1': [1, 2, 3], 'col2': [3, 4, 5]}
df = pd.DataFrame(data=d)
fig = px.line(df, x=df.index, y=['col1', 'col2'])
custom_legend_name(['hello','hi'])
fig.show()

Python - Problem to paint different colours in x,y and z axis with Ipyvolume library

I'm trying to create a 3D plot with Python library "ipyvolume" where every point in the plot has a colour. The points can be repeated colours. There is a problem when it paint the points in the plot. Some idea to fix this?
Import the libraries:
import pandas as pd
import numpy as np
import ipyvolume as ipv
Load the data:
dataframe = pd.read_csv("C:/Users/j/Desktop/K - Means/test.csv",sep=",")
dataframe.head()
Picture about Dataframe:
Dataframe
Creation of the axes:
X = np.array(dataframe[["op","ex","ag"]])
y = np.array(dataframe['categoria'])
Information about X:
array([[34.297953, 41.948819, 29.370315],
[44.986842, 37.938947, 24.279098],
[41.733854, 38.999896, 34.645521],
[40.377154, 52.337538, 31.082154],
[36.664677, 48.530806, 31.138871],
[33.531771, 43.211667, 25.786667],
[31.851102, 47.182362, 19.594331],
[31.865118, 55.377559, 36.258346],
[46.393488, 39.93031 , 16.658062],
[39.436667, 32.966288, 32.291591],
[52.750992, 41.698855, 17.057176],
[41.328182, 39.173333, 21.070505],
[54.407727, 34.104318, 18.771818],
[47.610076, 39.439545, 21.438409],
[39.435149, 41.479403, 21.004104],
[48.617348, 43.617955, 19.263258],
[40.073543, 44.194724, 33.921417],
[43.37292 , 43.792263, 21.067737],
[49.792403, 41.435581, 16.433953],
[30.020465, 44.29969 , 39.117984],
[36.909459, 51.947297, 34.687568],
[50.594462, 41.383154, 17.896538],
[34.186667, 18.693542, 9.682292],
[31.215455, 44.180909, 32.87 ],
[47.27686 , 41.973372, 12.40186 ],
[45.369773, 35.925909, 23.478258],
[35.943438, 45.519531, 28.02125 ],
[36.272348, 40.065152, 28.706894],
[44.501603, 46.598931, 29.535038],
[49.028308, 38.450462, 19.791538],
[34.235923, 41.231615, 14.153692],
[53.11048 , 39.00608 , 17.2064 ],
[49.28542 , 42.117786, 21.008931],
[52.895725, 38.620229, 19.972748],
[30.691797, 59.824844, 33.395938],
[34.949528, 50.177402, 36.325276],
[41.76596 , 49.865253, 30.071414],
[30.825938, 55.912578, 29.489922],
[38.948976, 44.460866, 27.345827],
[46.955854, 35.376179, 23.747561],
[45.053969, 48.950992, 24.374427],
[45.088504, 50.765276, 25.71252 ],
[42.444615, 45.780231, 24.745615],
[40.046439, 37.722197, 30.568258],
[52.535221, 35.290973, 15.793009],
[56.691163, 31.135698, 20.439651],
[48.709282, 44.728513, 19.387538],
[53.453713, 38.522321, 16.655907],
[31.450855, 45.490983, 40.583162],
[31.891474, 53.373368, 24.296316],
[49.077731, 45.670798, 17.449202],
[36.196989, 42.358817, 24.191613],
[38.91342 , 46.979524, 28.669524],
[60.225087, 28.902609, 14.337043],
[35.545054, 30.295484, 39.422796],
[56.815859, 38.419375, 13.961641],
[49.47 , 30.96626 , 23.053053],
[47.811742, 41.36447 , 20.816439],
[35.779512, 31.227724, 27.689919],
[55.974031, 33.09 , 21.330698],
[40.502021, 34.040957, 16.767979],
[38.78828 , 36.947204, 24.048172],
[52.082462, 39.402308, 16.628231],
[57.427596, 33.121827, 12.412404],
[39.528547, 42.353077, 23.810769],
[39.36155 , 40.205116, 26.27124 ],
[66.665564, 26.855564, 15.602331],
[48.587099, 26.988702, 9.948168],
[52.675729, 35.32625 , 16.510208],
[45.813043, 53.54587 , 30.403261],
[44.765313, 43.954375, 24.824609],
[42.643386, 33.345984, 14.643386],
[44.512578, 37.723594, 15.144922],
[51.830571, 44.304667, 10.049524],
[42.202857, 38.628681, 21.68989 ],
[57.241308, 33.237462, 16.194154],
[36.353298, 39.223723, 26.603617],
[35.566589, 48.679535, 29.923023],
[33.422105, 56.539263, 32.230842],
[31.7503 , 44.3443 , 39.1499 ],
[33.332362, 46.603622, 37.348898],
[41.929385, 41.960077, 17.815385],
[57.145227, 31.194545, 16.385 ],
[46.137348, 43.874697, 15.843258],
[49.331231, 34.458231, 23.982462],
[44.171154, 43.299846, 27.451538],
[49.322373, 41.494915, 14.199153],
[46.158281, 47.806719, 23.341641],
[48.355859, 35.778281, 15.101563],
[47.143474, 40.162316, 20.52 ],
[48.403333, 36.152326, 12.157829],
[40.281616, 35.341515, 20.805657],
[49.049323, 32.918647, 22.447594],
[47.737462, 41.528077, 19.694385],
[48.743333, 42.93187 , 17.984797],
[38.766702, 42.88383 , 22.15266 ],
[38.471406, 41.289922, 39.664375],
[54.911368, 42.269895, 11.263263],
[37.240989, 46.254286, 31.804286],
[46.319462, 38.176692, 14.143846],
[53.331333, 33.349333, 18.497333],
[51.006406, 36.351563, 22.484609],
[47.646364, 39.943939, 23.249848],
[32.683125, 54.681667, 35.906667],
[65.067447, 25.46617 , 14.787447],
[54.431756, 37.019847, 19.690305],
[35.834375, 44.595625, 23.930625],
[39.546441, 45.188475, 25.213644],
[41.114 , 41.884769, 19.713231],
[50.898163, 38.136837, 19.937347],
[45.669015, 44.523106, 20.548864],
[37.411719, 43.379531, 33.332422],
[31.541828, 47.688172, 28.897527],
[41.483701, 50.352283, 30.561496],
[36.813721, 52.722403, 14.703256],
[43.81828 , 42.931613, 17.494624],
[39.31561 , 30.73935 , 13.23122 ],
[63.995606, 26.921818, 9.305985],
[44.541328, 45.529453, 33.89125 ],
[35.420439, 41.05807 , 24.249737],
[45.162043, 34.678602, 22.719355],
[38.499688, 46.513828, 34.344766],
[55.293566, 49.822326, 20.592791],
[46.21 , 35.002222, 19.006667],
[54.151721, 32.722131, 11.041475],
[43.443893, 23.982901, 17.032443],
[40.120985, 27.149545, 23.975758],
[53.95 , 42.411488, 16.108347],
[48.796045, 46.014478, 14.642985],
[43.805615, 36.315846, 21.608308],
[51.161 , 44.074 , 17.386154],
[58.380294, 45.653922, 12.822843],
[40.345769, 37.003923, 17.285538],
[40.808939, 43.961591, 18.982424],
[57.962308, 33.373538, 17.684 ],
[35.569389, 38.904885, 31.624351],
[31.960417, 48.533125, 40.096458],
[71.696129, 27.57121 , 19.093548],
[51.537405, 36.465344, 23.008168],
[36.258913, 45.225652, 39.427283]])
Information about y:
array([7, 7, 4, 2, 4, 7, 7, 5, 7, 7, 3, 1, 1, 2, 8, 3, 4, 6, 2, 4, 2, 3,
3, 7, 2, 4, 8, 1, 4, 3, 8, 1, 2, 7, 4, 5, 1, 2, 2, 1, 6, 2, 6, 1,
1, 2, 6, 3, 1, 7, 2, 8, 6, 2, 8, 2, 1, 3, 8, 2, 8, 4, 2, 1, 8, 9,
1, 1, 2, 4, 6, 8, 8, 4, 9, 2, 8, 4, 4, 9, 5, 2, 4, 1, 2, 7, 2, 3,
2, 1, 2, 7, 2, 2, 1, 7, 7, 2, 4, 6, 1, 1, 1, 4, 2, 4, 2, 8, 7, 5,
9, 9, 8, 9, 7, 1, 8, 2, 4, 8, 8, 2, 2, 1, 2, 1, 6, 2, 4, 2, 1, 1,
1, 7, 3, 7, 4, 2, 1, 1], dtype=int64)
In this piece of code I am trying to add different colours by every point in the plot:
fig = ipv.figure()
colores=['blue','red','green','cyan','yellow','orange','black','pink','brown','purple']
asignar=[]
for row in y:
asignar.append(colores[row])
scatter=ipv.scatter(X[:, 0], X[:, 1], X[:, 2],marker="sphere", color=asignar, size=2)
ipv.selector_default
ipv.show()
The result of the last piece of code is an infinite execution.
Changing the scatter's color the plot is created:
fig = ipv.figure()
colores=['blue','red','green','cyan','yellow','orange','black','pink','brown','purple']
asignar=[]
for row in y:
asignar.append(colores[row])
scatter=ipv.scatter(X[:, 0], X[:, 1], X[:, 2],marker="sphere", color="red", size=2)
ipv.selector_default
ipv.show()
Plot
Suggestion from https://github.com/maartenbreddels/ipyvolume/issues/12#issuecomment-284685146 might work, something like:
import ipyvolume as ipv
import matplotlib
c = matplotlib.cm.afmhot(np.linspace(0, 1, len(y)))
ipv.quickscatter(X[:, 0], X[:, 1], X[:, 2],marker="sphere",color=c,size=2)

Categories

Resources