Matplotlib graph does not show in Python Interactive Window - pandas

The following is my code, but I can't get the plot to show on my Visual Studio Code even though I am running this on the Python Interactive Window, which should usually show a graph plot after running. The tables are showing just fine. I also do not get a default graph which pops up like it normally should. What am I doing wrong?
import yfinance as yf
import pandas as pd
import matplotlib
matplotlib.use('agg')
import matplotlib.pyplot as plt
import talib
df = pd.read_csv('filename.csv')
df = df.sort_index()
macd, macdsignal, macdhist = talib.MACD(df['Close'], fastperiod=12, slowperiod=26, signalperiod=9)
macd = macd.to_list()
macdsignal = macdsignal.to_list()
macdhist = macdhist.to_list()
df['macd'], df['macdsignal'], df['macdhist'] = macd,macdsignal,macdhist
ax = plt.gca()
print(df.columns)
df.plot(kind='line',x='Date',y='macd', color='blue',ax=ax)
df.plot(kind='line',x='Date',y='macdsignal', color='red', ax=ax)
plt.show()
The csv file has data that looks like this

The issue was with matplotlib.use('agg'), which does not support the show() function. This prevented the graph from being displayed on Visual Studio's Interactive Window. The matplotlib.use('agg') method can, however, be used for saving your graph in a .png format.
According to Matplotlib.org, agg is "the canonical renderer for user interfaces, which uses the Anti-Grain Geometry C++ library to make a raster (pixel) image of the figure". More information can be found at this link here

Related

matplotlib chart construction to suit use flask? (working example uses matplotlib.figure FigureCanvasAgg) can I construct errorbars?

I have a matplotlib chart working nicely as a python script. I need to create this chart style in flask. Can't use this method within flask as flask thread management doesn't play with matplotlib.
Oddly, the current method will run once successfully, subsequent runs will produce this error.
RuntimeError: main thread is not in main loop
So this is my desired chart format to produce in flask.
the code I'm using currently.
fig, ax = plt.subplots()
fig.subplots_adjust(bottom=0.29, top=.91)
ax.set_title(title)
ax.set_ylabel("y label text")
ax.set_xlabel('x label text')
ax.tick_params(axis='x', labelrotation = -80)
l = ax.plot(df_output['column1'])
y_error = df_output['column2']
plt.errorbar(list(df_output.index), \
list(df_output['column1']), \
yerr = y_error,fmt='o',ecolor = 'blue',color='blue')
fig.legend(l, loc=8, labels=labels)
#loc=2 = top left corner, loc=8 = 'lower center'
#plt.show()
plt.savefig(output_path+"/"+title+'_errorbars.png')
I found this example that works with flask
https://gist.github.com/illume/1f19a2cf9f26425b1761b63d9506331f
it uses this matplotlib charting syntax. Need to convert my old matplotlib format to suit the flask compatible format. Is this chart format possible via FigureCanvasAgg?
fig = Figure()
axis = fig.add_subplot(1, 1, 1)
print("type(axis):", type(axis))
x_points = data.iloc[:, 0]
y_points = data['mean minus sterility control mean']
axis.plot(x_points, y_points)
output = io.BytesIO()
FigureCanvasAgg(fig).print_png(output)
return Response(output.getvalue(), mimetype="image/png")
I'll admit to not being strong in building matpotlib charts. changing between chart building methods throws me.
I'm digging around the docs at moment.
https://matplotlib.org/stable/gallery/user_interfaces/canvasagg.html
I did find this Q&A (RuntimeError: main thread is not in main loop with Matplotlib and Flask)
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
while this appears to run for me. I want to move away from creating charts as files on the server, too much potential for file mismanagement, creating the chart as a io.BytesIO() output (or some format within the flask http response to user) is a much better solution.
(I'd like to keep at an image output, rather than change architecture to (say) a json output and constructing chart in client using javascript libraries)

how to make plt plot do not show figure [duplicate]

I need to create a figure in a file without displaying it within IPython notebook. I am not clear on the interaction between IPython and matplotlib.pylab in this regard. But, when I call pylab.savefig("test.png") the current figure get's displayed in addition to being saved in test.png. When automating the creation of a large set of plot files, this is often undesirable. Or in the situation that an intermediate file for external processing by another app is desired.
Not sure if this is a matplotlib or IPython notebook question.
This is a matplotlib question, and you can get around this by using a backend that doesn't display to the user, e.g. 'Agg':
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
plt.plot([1,2,3])
plt.savefig('/tmp/test.png')
EDIT: If you don't want to lose the ability to display plots, turn off Interactive Mode, and only call plt.show() when you are ready to display the plots:
import matplotlib.pyplot as plt
# Turn interactive plotting off
plt.ioff()
# Create a new figure, plot into it, then close it so it never gets displayed
fig = plt.figure()
plt.plot([1,2,3])
plt.savefig('/tmp/test0.png')
plt.close(fig)
# Create a new figure, plot into it, then don't close it so it does get displayed
plt.figure()
plt.plot([1,3,2])
plt.savefig('/tmp/test1.png')
# Display all "open" (non-closed) figures
plt.show()
We don't need to plt.ioff() or plt.show() (if we use %matplotlib inline). You can test above code without plt.ioff(). plt.close() has the essential role. Try this one:
%matplotlib inline
import pylab as plt
# It doesn't matter you add line below. You can even replace it by 'plt.ion()', but you will see no changes.
## plt.ioff()
# Create a new figure, plot into it, then close it so it never gets displayed
fig = plt.figure()
plt.plot([1,2,3])
plt.savefig('test0.png')
plt.close(fig)
# Create a new figure, plot into it, then don't close it so it does get displayed
fig2 = plt.figure()
plt.plot([1,3,2])
plt.savefig('test1.png')
If you run this code in iPython, it will display a second plot, and if you add plt.close(fig2) to the end of it, you will see nothing.
In conclusion, if you close figure by plt.close(fig), it won't be displayed.

Pandas in PyCharm: Where does it display the boxplot?

I am making a python script using the PyCharm IDE, and the idea is to display descriptive statistics and a box plot for each group in a DataFrame. The statistics displays, but the boxplot is nowhere to be seen...
I have tried Googling an answer, but it does not seem this question have been answered before.
import pandas as pd
import matplotlib as plt
(...)
for name, group in grouped:
if len(group) > 3:
print("\n\nNAME: {}".format(name))
print("GROUP: {}".format(group))
print("DESCRIPTIVE STATISTICS
{}".format(group.distance2.describe()))
print(group.distance2.plot.box())
group.distance2.plot.box()
I do not get any error messages, the code runs and completes, but I do not know where the boxplot is supposed to display.
I think the code as it is does not create a matplotlib figure object. Try creating a test data object for group.distance2, then create a matplotlib boxplot object. I am assuming you are using the matplotlib library.
import matplotlib.pyplot as plt
for name, group in grouped:
if len(group) > 3:
data = group.distance2
# create a matplotlib figure object
fig, axs = plt.subplots(1, 1)
# basic plot
axs[0, 0].boxplot(data)
axs[0, 0].set_title('basic plot of group.distance2')
plt.show()
It that works, you can try putting several group data into one figure (axes). Here is more information: https://matplotlib.org/3.1.0/gallery/statistics/boxplot_demo.html

Annotating a box outside the box, matplotlib

I want the text to appear beside the box instead of inside it:
Here is what I did:
import matplotlib as mpl
import matplotlib.pyplot as plt
from custombox import MyStyle
fig = plt.figure(figsize=(10,10))
legend_ax = plt.subplot(111)
legend_ax.annotate("Text",xy=(0.5,0.5),xycoords='data',xytext=(0.5, 0.5),textcoords= ('data'),ha="center",rotation = 180,bbox=dict(boxstyle="angled, pad=0.5", fc='white', lw=4, ec='Black'))
legend_ax.text(0.6,0.5,"Text", ha="center",size=15)
Here is what it gives me:
Note: custombox is similar to the file that is written in this link:
http://matplotlib.org/1.3.1/users/annotations_guide.html
My ultimate aim is to make it look legend like where the symbol (angled box) appears beside the text that represents it.
EDIT 1: As suggested by Ajean I have annotated text separately but I can't turn of the text within the arrow
One way to do it would be to separate the text and the bbox (which you can reproduce using an arrow). The following gives me something close to what you want, I think.
import matplotlib.pyplot as plt
from matplotlib import patches
fig = plt.figure(figsize=(5,5))
ax = fig.add_subplot(111)
ax.annotate("Text", (0.4,0.5))
bb = patches.FancyArrow(0.5,0.5,0.1,0.0,length_includes_head=True, width=0.05,
head_length=0.03, head_width=0.05, fc='white', ec='black',
lw=4)
ax.add_artist(bb)
plt.show()
You can futz with the exact placement as needed. I'm not an expert on all the kwargs, so this may not be the best solution, but it will work.

Calling pylab.savefig without display in ipython

I need to create a figure in a file without displaying it within IPython notebook. I am not clear on the interaction between IPython and matplotlib.pylab in this regard. But, when I call pylab.savefig("test.png") the current figure get's displayed in addition to being saved in test.png. When automating the creation of a large set of plot files, this is often undesirable. Or in the situation that an intermediate file for external processing by another app is desired.
Not sure if this is a matplotlib or IPython notebook question.
This is a matplotlib question, and you can get around this by using a backend that doesn't display to the user, e.g. 'Agg':
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
plt.plot([1,2,3])
plt.savefig('/tmp/test.png')
EDIT: If you don't want to lose the ability to display plots, turn off Interactive Mode, and only call plt.show() when you are ready to display the plots:
import matplotlib.pyplot as plt
# Turn interactive plotting off
plt.ioff()
# Create a new figure, plot into it, then close it so it never gets displayed
fig = plt.figure()
plt.plot([1,2,3])
plt.savefig('/tmp/test0.png')
plt.close(fig)
# Create a new figure, plot into it, then don't close it so it does get displayed
plt.figure()
plt.plot([1,3,2])
plt.savefig('/tmp/test1.png')
# Display all "open" (non-closed) figures
plt.show()
We don't need to plt.ioff() or plt.show() (if we use %matplotlib inline). You can test above code without plt.ioff(). plt.close() has the essential role. Try this one:
%matplotlib inline
import pylab as plt
# It doesn't matter you add line below. You can even replace it by 'plt.ion()', but you will see no changes.
## plt.ioff()
# Create a new figure, plot into it, then close it so it never gets displayed
fig = plt.figure()
plt.plot([1,2,3])
plt.savefig('test0.png')
plt.close(fig)
# Create a new figure, plot into it, then don't close it so it does get displayed
fig2 = plt.figure()
plt.plot([1,3,2])
plt.savefig('test1.png')
If you run this code in iPython, it will display a second plot, and if you add plt.close(fig2) to the end of it, you will see nothing.
In conclusion, if you close figure by plt.close(fig), it won't be displayed.