I am trying to work with big data plotting around 20 plots on plotly and embed them on web page. I can very well plot individual plots with username and one api_key that found in the profile.
The Problem comes is when: I have to rerun all the 20 plots with python program after interval of every 15 mins and every time I am getting new windows. Instead I need the same plot to update/redraw.
How do I get that? I tried reading the plot.ly document and also few tutorials outside. Cannot find how to get it done. Can anyone please help me with steps or refer me to some document where I can know how to work with multiple plots that will update at same time.
I am following the steps given in plotly tutorial not sure if I should use stream_ids ? Or can I create a new api_key for every plot ?Confused !!! Thanks in Advance for the suggestions.
Edit: I could make access tokens and Initiate the credentials from the following tutorial.
The code below works perfect: But now I am looking for required fixing in the below code by trying to minimize the code with annotations and where to include the streaming API Access Tokens while having sizable scatter plots ?
import plotly.plotly as py
import plotly.tools as tls
from plotly.graph_objs import *
import csv
import pandas as pd
import numpy as np
df = pd.read_csv('finally.csv')
df1=df[['NAME','COUNT']]
sizemode='area'
sizeref=df1['COUNT'].max()/1000
def Trace(X,PLACE,sizes):
return Scatter(
x=X['NAME'],
y=X['COUNT'].sum(),
name=PLACE,
mode='marker',
marker=Marker(
line=Line(width=0.9),
size=sizes,
sizeref=sizeref,
opacity=0.9,
)
)
data=Data()
for PLACE, X in df1.groupby('NAME'):
sizes=X['COUNT'].sum()/1000
data.append(Trace(X,PLACE,sizes))
title = "Fig 1.1 : All NAMES"
x_title = "Names".format()
y_title = "Count"
# Define a dictionary of axis style options
axis_style = dict(
zeroline=False, # remove thick zero line
gridcolor='#FFFFFF', # white grid lines
ticks='outside', # draw ticks outside axes
ticklen=8, # tick length
tickwidth=1.5 # and width
)
# Make layout object
layout = Layout(
title=title, # set plot title
plot_bgcolor='#EFECEA', # set plot color to grey
xaxis=XAxis(
axis_style, # add axis style dictionary
title=x_title, # x-axis title
),
yaxis=YAxis(
axis_style, # add axis style dictionary
title=y_title, # y-axis title
),
showlegend=False,
)
fig = Figure(data=data,layout=layout)
plot_url=py.plot(fig,filename=' plotting')
In plot/ iplot there is 'fileopt' option which should help you. For example, if you would want to add new traces to your existing data you can run
plot_url = py.plot(fig, filename='my-file', fileopt='append')
You're right it is not well documented yet. But if you run help(py.plot) you would get a small document on it as follow:
plot(figure_or_data, validate=True, **plot_options)
Create a unique url for this plot in Plotly and optionally open url.
plot_options keyword agruments:
filename (string) -- the name that will be associated with this figure
fileopt ('new' | 'overwrite' | 'extend' | 'append') -- 'new' creates a
'new': create a new, unique url for this plot
'overwrite': overwrite the file associated with `filename` with this
'extend': add additional numbers (data) to existing traces
'append': add additional traces to existing data lists
world_readable (default=True) -- make this figure private/public
auto_open (default=True) -- Toggle browser options
True: open this plot in a new browser tab
False: do not open plot in the browser, but do return the unique url
Related
PowerBI Service does not appear to be able to render Python Script visuals that I can render via PowerBI Desktop (using Python 3.6) without problems where I require the use of dates in the x-axis of Seaborn scatterplot.
What are the possible reasons for this?
The result of running my code in PowerBI Desktop (running Python 3.6) appears as
However, the visual looks like this when published via PowerBI Service (Python Version unknown)
Notice how the x-axis and the y-axis are completely incorrect and the legend is not working for the colour coding and shapes.
Special Notes:
I am publishing to a Power BI Service under Pro Subscription
When I publish basic Python Scripts like those covered in Microsoft documentation I have no problem
The underlying data set is from a CSV file ingested via Power Query and is not a Python generated data set ie data frame. The dataset seen in my script is that which is generated via the use of the Python Script visualisation feature of PowerBI.
The script I am using is as follows:
# The following code to create a dataframe and remove duplicated rows is always executed and acts as a preamble for your script:
# dataset = pandas.DataFrame(EmployeeName, Event_Date, RerunCount, AMPCPUTIME, Client_App)
from matplotlib import dates as mpl_dates
from matplotlib import pyplot as plt
import pandas as pd
import seaborn as sns
# Prepare date for matplotlib
dataset['Event_Date'] = pd.to_datetime(dataset['Event_Date']) # This line is critical to fixing the x-axis for Event Date
plt.clf() #clears plot
# plot the data
sns.scatterplot(x='Event_Date', y='AMPCPUTIME',hue='RerunCount', style='Client_App',s=120, data=dataset, palette='bright')
# after plotting the data, format the labels
# X-axis Formatting
plt.gcf().autofmt_xdate()
date_format = mpl_dates.DateFormatter('%d-%m-%y')
plt.gca().xaxis.set_major_formatter(date_format)
plt.gca().xaxis.set_major_locator(plt.MaxNLocator(15))
plt.xticks(fontsize=12, color = 'white')
plt.xlabel("Date of Execution", size=20, labelpad = 20, color = 'white')
# Y-axis Formatting
plt.yticks(fontsize=16,color = 'white')
plt.ylabel("CPU Usage", size=20, labelpad = 20, color = 'white')
plt.ticklabel_format(style='plain', axis='y') # This is necessary to prevent scientific notation occuring on y-axis
current_values = plt.gca().get_yticks()
plt.gca().set_yticklabels(['{:,.0f}'.format(x) for x in current_values])
# Set Size of Plot
plt.gcf().set_size_inches(20, 10)
# Set Legend for plot
plt.legend(
markerscale=3,
fontsize='medium',
title_fontsize='14',
loc='center left',
bbox_to_anchor=(1, 0.5),
labelspacing = 2,
ncol =1,
)
# Set background colour
plt.axes().set_facecolor("#385870")
plt.gcf().set_facecolor("#385870")
# Apply Title to Plot
#plt.title(str(dataset['EmployeeName'].unique())[2:-2], pad = 20, fontsize='18')
# Reduce padding around cell
plt.tight_layout()
plt.show()
Previously answered.
More people are experiencing issues with their column index going loco.
Take a look at this post, it should clear things up for you.
I have been able to successfully create a custom shapefile Choropleth map using plotly and geopandas. It loads successfully in my Jupyter window. The following image is what the map looks like when running in Jupyter.
Successfully rendered map in Jupyter
This is the code used to render the above map:
data = go.Choroplethmapbox(
geojson = gdf_json,
locations = df.index.astype(str),
z = df['2016']['Total'],
text = df.index.astype(str),
colorbar=dict(thickness=20,ticklen=3,tickformat=',.2r',outlinewidth=0),
marker_line_width=0.5,
marker_opacity=0.4,
colorscale='gnbu',
zmin=zmin,
zmax=zmax,
hovertemplate = "<b>%{text}</b><br>" +
"%{z:,.4r}<br>" +
"<extra></extra>")
#mapbox geographic map layout
layout = go.Layout(
title='Expenditure, 2020',
autosize=True,
#hovermode='closest',
#showlegend=True,
height=600,
margin=dict(l=0, r=0, t=40, b=0),
mapbox = dict(
domain = {'x': [0, 1],'y': [0, 1]},
center = dict(lat=-27.628296146695863, lon=152.74025612708698),
accesstoken = MAPBOX_ACCESSTOKEN,
#pitch=0,
zoom=10,
style='light')
)
fig = go.Figure(data=data, layout=layout)
fig.show()
However, when I attempt to load the map into Dash, it returns as an empty graph. (Note I cancel out the fig.show() line of code during this process).
app.layout = html.Div([
dcc.Graph(id = 'plot', figure = fig)
])
if __name__ == '__main__':
app.run_server()
Unsuccessful map in Dash
What I have tried
To narrow down the potential problems, I have tried to load in other elements such as dropdowns, radio buttons and a range slider. These loaded successfully, just not the map itself. I am also using the correct public Mapbox API token, as I have previously loaded up a Scattermapbox graph (created a bubble map), which has been successful on Dash.
Possible reasons
Obviously the starting point is whether there might be a very small minor syntax error in my code.
However I'm also wondering if there's something wrong with the loading of the geojson? Even though it loads successfully in Jupyter, maybe there is a slightly different method used when loading it into Dash?
To convert my geopandas polygons into geojson:
I converted it into an appropriate CRS --> gdf.to_crs(epsg=4326)
Set the index to my unique id --> gdf.set_index(id)
Applied this function --> gdf_json = gdf.__geo_interface__
Example of the geojson file
Would love some help if possible. Thank you!
I'm working on a very similar problem and when I converted from jupyter to dash I do not recall having to change the process of the geojson. But don't reject that possibility yet. The fact that it isn't producing any errors from the geojson is likely indicative of an error in how you build your layout. So the first two things you should try first.
Run the debugger (if you aren't already) because this will pick up on errors that will not be ported to your terminal.
app.run_server(debug=True)
Put your map rendering code into a function
def build_map():
return fig #after building the map figure
app.layout = html.Div[(dcc.Graph(figure = build_map())]
I ran into one error with building larger maps where it would time out.
There are so many things that could go wrong here, so process of elimination is key. Feel free to comment below and I will continue to try and help you out!
how can I create one legend to control multiple bokeh figures? Or how can I customize an exported html file created with bokeh to add legend with similar functionality?
Here is the scenario. I create an html file with 4 different figures. Each figure has a legend with labels/names for individual lines that are shown in the particular figure. Each of the four legend is clickable to toggle the lines separately in each figure.
Even though each of the four figures has one legend, the lines are related, so they each line describes one thing.
I now want to create a legend for all figures combined in one, to toggle each line in all four figures.
Maybe there is a way to add this kind of functionality to the exported html file in some way?
I thought someone with more experience has an idea how to achieve that.
Thanks in advance!
Kind regards
Legends are not (yet?) 'standalone' bokeh models, they need to be attached to a figure. For now to have an external legend for multiple figures, and place it wherever in a layout, some workaround is needed.
I typically do it like below, with an 'invisible' figure that holds the shared legend. You then have to define the legend items manually and assign to each their label and list of renderers.
from bokeh.io import show
from bokeh.plotting import figure
from bokeh.models import LegendItem, Legend
from numpy.random import random, choice
from bokeh.layouts import gridplot
from webcolors import html4_names_to_hex
del html4_names_to_hex['white']
palette = list(html4_names_to_hex.keys())
fig_list = [figure(plot_width=300,plot_height=300) for i in range(4)]
renderer_list = []
color_list = []
for fig in fig_list:
for i in range(5):
color = choice(palette)
renderer = fig.line(range(10),random(10),line_width=2,color=color)
renderer_list += [renderer]
color_list += [color]
# Lines with the same color will share a same legend item
legend_items = [LegendItem(label=color,renderers=[renderer for renderer in renderer_list if renderer.glyph.line_color==color]) for color in set(color_list)]
## Use a dummy figure for the LEGEND
dum_fig = figure(plot_width=300,plot_height=600,outline_line_alpha=0,toolbar_location=None)
# set the components of the figure invisible
for fig_component in [dum_fig.grid[0],dum_fig.ygrid[0],dum_fig.xaxis[0],dum_fig.yaxis[0]]:
fig_component.visible = False
# The glyphs referred by the legend need to be present in the figure that holds the legend, so we must add them to the figure renderers
dum_fig.renderers += renderer_list
# set the figure range outside of the range of all glyphs
dum_fig.x_range.end = 1005
dum_fig.x_range.start = 1000
# add the legend
dum_fig.add_layout( Legend(click_policy='hide',location='top_left',border_line_alpha=0,items=legend_items) )
figrid = gridplot(fig_list,ncols=2,toolbar_location='left')
final = gridplot([[figrid,dum_fig]],toolbar_location=None)
show(final)
I use the following code to draw a heatmap in plotly:
import plotly.offline as plotly
import plotly.graph_objs as graph_objs
x = []
# fill x with stuff
path = os.path.join(self.get_current_job_directory(), track + '.html')
trace = graph_objs.Heatmap(z = x)
data = [trace]
plotly.plot(data, filename = path)
But I get a prompt screen like this. I need to generate hundreds of such plots on a remote server and its not practical to just dismiss them.
How to get rid of this?
Using the filename argument tells Plotly what filename to use for the HTML file it generates to contain the plot. That file is then viewed in the system's default HTML viewer, which in this case appears to be Lynx. Of course that's rather useless as the point is to view the plot, and Lynx is a text-only Web browser!
To avoid opening the plot, add auto_open=False to your plot() call:
plotly.plot(data, filename=path, auto_open=False)
I'm currently writing a scientific paper and am generating most of the figures using matplotlib. I have a pipeline set up using a makefile that regenerates all of my plots whenever I update the data. My problem is that the figures are made up multiple panels, and some of those panels should contain vector illustrations which I've created using Adobe Illustrator. How can I automatically combine the graphs with the illustrations when I update my raw data? I could save the vector illustrations in a raster format and then display them using matplotlib's imshow function, but I want the output to be a vector to ensure the best possible print quality.
After some more extensive googling I found this old message on the matplotlib mailing list:
The thread suggests using the python library PyX, which works well for me.
I can save both the illustrator diagrams and the matplotlib plots as .eps files, and then combine them together like this:
import pyx
c = pyx.canvas.canvas()
c.insert(pyx.epsfile.epsfile(0, 0, "1.eps", align="tl"))
c.insert(pyx.epsfile.epsfile(0,0,"2.eps", align="tr"))
c.writeEPSfile("combined.eps")
I found this example in the svgutils documentation which outlines how to combine matplotlib-generated SVGs into a single plot.
Here's the example from that page:
import svgutils.transform as sg
import sys
#create new SVG figure
fig = sg.SVGFigure("16cm", "6.5cm")
# load matpotlib-generated figures
fig1 = sg.fromfile('sigmoid_fit.svg')
fig2 = sg.fromfile('anscombe.svg')
# get the plot objects
plot1 = fig1.getroot()
plot2 = fig2.getroot()
plot2.moveto(280, 0, scale=0.5)
# add text labels
txt1 = sg.TextElement(25,20, "A", size=12, weight="bold")
txt2 = sg.TextElement(305,20, "B", size=12, weight="bold")
# append plots and labels to figure
fig.append([plot1, plot2])
fig.append([txt1, txt2])
# save generated SVG files
fig.save("fig_final.svg")