I have a df - Wards - that contains the number of different events that happen on each ward of a hospital. I just want a simple bar chart of the totals of these events. I have used plotly before - I am no means an expert (evidently!) but I can't figure out where I am going wrong! With the code below I am seeing anything with fig.show(). I added the fig.write_image command to test - this returns the correct graph - but I can't figure out why my fig.show() command doesn't work
import plotly.express as px
import matplotlib.pyplot as plt
fig = px.bar(Wards, x='Ward', y='Total_Tasks')
fig.write_image("fig1.png")
fig.show()
I tried to duplicate your code but of course I don't have the data, so I made some up and I also didn't know for sure what modules you are importing, so I used the help at:
https://plotly.com/python/getting-started/
but anyway, here is what I came up with
that seems to work.
import plotly.express as px
import matplotlib.pyplot as plt
fig = px.bar(x=["a", "b", "c"], y=[1, 3, 2])
plt.savefig('fig1.png',bbox_inches="tight",dpi=600)
fig.show()
Related
I have a plotly object that should be showing up properly but for some reason it only shows up blank in DataBricks. The object type is:
plotly.graph_objs._figure.Figure
I have tried the following to display the figure:
fig.show()
display(fig)
displayHTML(fig.to_html())
All possible solutions I can think of result in the same thing. Thanks!
Btw... Using Plotly Version 4.9
Try using the plot method from plotly.offline. This following is from DataBricks documentation, but Jupyter notebooks have a similar issue where a Plotly graph_object Figure won't render unless you use plotly.offline.
from plotly.offline import plot
import plotly.graph_objects as go
# Instead of simply calling plot(...), store your plot as a variable and pass it to displayHTML().
# Make sure to specify output_type='div' as a keyword argument.
# (Note that if you call displayHTML() multiple times in the same cell, only the last will take effect.)
p = plot(
[ ## define your go.Figure here ##
],
output_type='div'
)
displayHTML(p)
Worth noting that you can similarly use the plot method from plotly.offline to display plotly.express plots.
This saves a lot of code for simple plots where graph_objects are overkill!
from plotly.offline import plot
import plotly.express as px
p = plot(
px.scatter(x=[0, 1, 2, 3, 4], y=[0, 1, 4, 9, 16]),
output_type='div'
)
displayHTML(p)
I have been trying to plot a simple bar chart using Seaborn. Oddly enough the previous plots worked, but these ones do not appear. No error is being thrown and as far as I can tell the code is okay. Perhaps a more experienced eye will be able to find an error.
import pandas as pd
import numpy as np
import pyodbc
import matplotlib.pyplot as plt
import seaborn as sns
region_pct_25 = region_totals.iloc[0:6, :]
region_pct_25['Opp_Lives_pct'] = ((region_pct_25.Lives / region_pct_25.Lives.sum())*100).round(2)
region_pct_25.reset_index(level=['RegionName'], inplace=True)
region_25_plt = sns.barplot(x="RegionName", y="Opp_Lives_pct", data=region_pct_25, color = 'g').set_title("Client Usage by Region: ADD ")
plt.show()
No plot is showing. Please help wherever you can!
adding %matplotlib inline to the preamble resolved the issue!
I am using the waterfall_chart package in Python to create a waterfall figure. The package mainly uses matplotlib in the backend, so I was trying to use the tls.mpl_to_plotly(mpl_fig) function to covert the matplotlib figure into plotly. But when converting, an error pops up. Is there a way to convert waterfall_chart into plotly or is there an easy way to create the chart directly in plotly? I saw some previous discussion on similar chart in plotly, but it involved pretty manual coding of the chart number.
You could use the following code to recreate the chart.
import waterfall_chart
import matplotlib.pyplot as plt
import plotly.tools as tls
a = ['sales','returns','credit fees','rebates','late charges','shipping']
b = [10,-30,-7.5,-25,95,-7]
mpl_fig = plt.figure()
waterfall_chart.plot(a, b)
plt.show()
waterfall chart
But when I try to convert to plotly using mpl_to_plotly(), there is an error:
plotly_fig = tls.mpl_to_plotly(mpl_fig)
ValueError: min() arg is an empty sequence
The detail of the waterfall_chart package could be found here: https://github.com/chrispaulca/waterfall/blob/master/waterfall_chart.py
My answer addresses
[...] or is there an easy way to create the chart directly in plotly?
With newer versions of plotly you can use plotly.graph_objs.Waterfall.
Below is a basic example with your data sample with a setup that uses iplot in an off-line Jupyter Notebook:
Plot:
Code:
# imports
import plotly
from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
from IPython.core.display import display, HTML
import plotly.figure_factory as ff
import plotly.graph_objs as go
import pandas as pd
import numpy as np
# setup
display(HTML("<style>.container { width:35% !important; } .widget-select > select {background-color: gainsboro;}</style>"))
init_notebook_mode(connected=True)
np.random.seed(1)
import plotly.offline as py
import plotly.graph_objs as go
py.init_notebook_mode(connected = False)
# your values
a = ['sales','returns','credit fees','rebates','late charges','shipping']
b = [10,-30,-7.5,-25,95,-7]
# waterfall trace
trace = go.Waterfall(
x = a,
textposition = "outside",
text = [str(elem) for elem in b],
y = b,
connector = {"line":{"color":"rgb(63, 63, 63)"}},
)
layout = go.Layout(
title = "Waterfall chart, plotly version 3.9.0",
showlegend = True
)
iplot(go.Figure([trace], layout))
Check your version with:
import plotly
plotly.__version__
Update your version in a cmd console using:
pip install plotly --upgrade
List a has a length of 6, list b has a length of 5.
Matplotlib refuses to display an empty array, list or whatever.
Solve it to add a number or 0 to b or add an if to your code, to avoid matplotlib gets an empty sequence.
I generate a lots of figures with a script which I do not display but store to harddrive. After a while I get the message
/usr/lib/pymodules/python2.7/matplotlib/pyplot.py:412: RuntimeWarning: More than 20 figures have been opened. Figures created through the pyplot interface (matplotlib.pyplot.figure) are retained until explicitly closed and may consume too much memory. (To control this warning, see the rcParam figure.max_num_figures).
max_open_warning, RuntimeWarning)
Thus, I tried to close or clear the figures after storing. So far, I tried all of the followings but no one works. I still get the message from above.
plt.figure().clf()
plt.figure().clear()
plt.clf()
plt.close()
plt.close('all')
plt.close(plt.figure())
And furthermore I tried to restrict the number of open figures by
plt.rcParams.update({'figure.max_num_figures':1})
Here follows a piece of sample code that behaves like described above. I added the different options I tried as comments at the places I tried them.
from pandas import DataFrame
from numpy import random
df = DataFrame(random.randint(0,10,40))
import matplotlib.pyplot as plt
plt.ioff()
#plt.rcParams.update({'figure.max_num_figures':1})
for i in range(0,30):
fig, ax = plt.subplots()
ax.hist([df])
plt.savefig("/home/userXYZ/Development/pic_test.png")
#plt.figure().clf()
#plt.figure().clear()
#plt.clf()
#plt.close() # results in an error
#plt.close('all') # also error
#plt.close(plt.figure()) # also error
To be complete, that is the error I get when using plt.close:
can't invoke "event" command: application has been destroyed
while executing "event generate $w <>"
(procedure "ttk::ThemeChanged" line 6)
invoked from within "ttk::ThemeChanged"
The correct way to close your figures would be to use plt.close(fig), as can be seen in the below edit of the code you originally posted.
from pandas import DataFrame
from numpy import random
df = DataFrame(random.randint(0,10,40))
import matplotlib.pyplot as plt
plt.ioff()
for i in range(0,30):
fig, ax = plt.subplots()
ax.hist(df)
name = 'fig'+str(i)+'.png' # Note that the name should change dynamically
plt.savefig(name)
plt.close(fig) # <-- use this line
The error that you describe at the end of your question suggests to me that your problem is not with matplotlib, but rather with another part of your code (such as ttk).
plt.show() is a blocking function, so in the above code, plt.close() will not execute until the fig windows are closed.
You can use plt.ion() at the beginning of your code to make it non-blocking. Even though this has some other implications the fig will be closed.
I was still having the same issue on Python 3.9.7, matplotlib 3.5.1, and VS Code (the issue that no combination of plt.close() closes the figure). I have three loops which the most inner loop plots more than 20 figures. The solution that is working for me is using agg as backend and del someFig after plt.close(someFig). Subsequently, the order of code would be something like:
import matplotlib
matplotlib.use('agg')
import matplotlib.pyplot as plt
someFig = plt.figure()
.
.
.
someFig.savefig('OUTPUT_PATH')
plt.close(someFig) # --> (Note 1)
del someFig
.
.
.
NOTE 1: If this line is removed, the output figures may not be plotted correctly! Especially when the number of elements to be rendered in the figure is high.
NOTE 2: I don't know whether this solution could backfire or not, but at least it is working and not hugging RAM or preventing plotting figures!
import tensorflow as tf
from matplotlib import pyplot as plt
sample_image = tf.io.read_file(str(PATH / 'Path to your file'))
sample_image = tf.io.decode_jpeg(sample_image)
print(sample_image.shape)
plt.figure("1 - Sample Image ")
plt.title(label="Sample Image", fontsize=12, color="red")
plt.imshow(sample_image)
plt.show(block=False)
plt.pause(3)
plt.close()
plt.show(block=False)
plt.pause(interval) do the trick
This does not really solve my problem, but it is a work-around to handle the high memory consumption I faced and I do not get any of the error messages as before:
from pandas import DataFrame
from numpy import random
df = DataFrame(random.randint(0,10,40))
import matplotlib.pyplot as plt
plt.ioff()
for i in range(0,30):
plt.close('all')
fig, ax = plt.subplots()
ax.hist([df])
plt.savefig("/home/userXYZ/Development/pic_test.png")
New to matplotlib and trying to explore existing data by iterating through a DataFrame via animation, but it seems very slow, can anyone see what I'm doing wrong or suggest improvements, have tried playing with frame speed but has little effect so I think its my code, would like to view this 2000 row object in 15 sec give or take. box is 8gb linex so should be fine, using ipython pop out figure to plot.
from pandas import *
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import animation
coef_mean = DataFrame(np.random.rand(2000,50))
def animate(f_frame):
plt.cla()
plt.plot(coef_mean.columns.values, coef_mean.ix[f_frame])
plt.ylim(f_coef_min,f_coef_max)
fig = plt.figure(figsize=(9,5))
f_coef_min, f_coef_max = coef_mean.min().min()-.02, coef_mean.max().max()+.02
anim = animation.FuncAnimation(fig, animate, frames=150)
plt.show()
any ideas out there what I have done wrong ? many thanks, LW
also to get the popout figure try using
%matplotlib qt
You don't need to replot inside the animation function. Instead, you should just update the data of the plot. In your case something like this should work:
fig, ax = plt.subplots()
custom_plot, = ax.plot(coef_mean.columns.values, coef_mean.ix[0])
ax.set_ylim(f_coef_min,f_coef_max)
def animate(f_frame):
custom_plot.set_ydata(coef_mean.ix[f_frame])
return custom_plot,
Look at some animation examples for more information. E.g:
http://matplotlib.org/examples/animation/simple_anim.html