matplotlib.pyplot plot_date function breaks on cftime.datetime objects - python-3.x

Trying to plot data using the matplotlib.pyplot.plot_date function with datetime objects originating from the netCDF4.num2date function I get the following error:
In [1]: from netCDF4 import num2date
In [2]: from matplotlib.pyplot import plot_date
In [3]: d=num2date((86400,2*86400),"seconds since 2000-01-01")
In [4]: gca().plot_date(d,(0,1))
...
AttributeError: 'cftime._cftime.DatetimeGregorian' object has no attribute 'toordinal'
The above exception was the direct cause of the following exception:
ConversionError
...
ConversionError: Failed to convert value(s) to axis units: array([cftime.DatetimeGregorian(2000-01-02 00:00:00),
cftime.DatetimeGregorian(2000-01-03 00:00:00)], dtype=object)
The following package versions are installed:
pandas 1.0.3
matplotlib 3.2.1
netcdf4 1.5.1.2
cftime 1.1.1.2
As the same thing perfectly works on a different machine with older package versions, I assume a version issue.
Also, I've tried the solution suggested in this thread and other related threads which seemed like a similar issue, but
from pandas.plotting import register_matplotlib_converters
register_matplotlib_converters()
didn't help neither.
Any suggestions welcome;)

Found the answer myself, from version 1.1.0 the num2date function in the cftime package changed its default behaviour to return cftime datetime instances instead of python datetime instances where possible (the option argument only_use_cftime_datetimes is now True by default, instead of False). The plot_date function however, at least currently, doesn't handle these.
To avoid the issue, use the arguments only_use_cftime_dateimes=False and only_use_python_datetime=True or use the convenience function num2pydate.

Related

backtesting.py ploting function not working

I'm trying to learn backtesting.py, when I run the following sample code, it pops up these errors, anyone could help? I tried to uninstall the Bokeh package and reinstall an older version, but it doen't work.
BokehDeprecationWarning: Passing lists of formats for DatetimeTickFormatter scales was deprecated in Bokeh 3.0. Configure a single string format for each scale
C:\Users\paul_\AppData\Local\Programs\Python\Python310\lib\site-packages\bokeh\models\formatters.py:399: UserWarning: DatetimeFormatter scales now only accept a single format. Using the first prodvided: '%d %b'
warnings.warn(f"DatetimeFormatter scales now only accept a single format. Using the first prodvided: {fmt[0]!r} ")
BokehDeprecationWarning: Passing lists of formats for DatetimeTickFormatter scales was deprecated in Bokeh 3.0. Configure a single string format for each scale
C:\Users\paul_\AppData\Local\Programs\Python\Python310\lib\site-packages\bokeh\models\formatters.py:399: UserWarning: DatetimeFormatter scales now only accept a single format. Using the first prodvided: '%m/%Y'
warnings.warn(f"DatetimeFormatter scales now only accept a single format. Using the first prodvided: {fmt[0]!r} ")
GridPlot(id='p11925', ...)
import bokeh
import datetime
import pandas_ta as ta
import pandas as pd
from backtesting import Backtest
from backtesting import Strategy
from backtesting.lib import crossover
from backtesting.test import GOOG
class RsiOscillator(Strategy):
upper_bound = 70
lower_bound = 30
rsi_window = 14
# Do as much initial computation as possible
def init(self):
self.rsi = self.I(ta.rsi, pd.Series(self.data.Close), self.rsi_window)
# Step through bars one by one
# Note that multiple buys are a thing here
def next(self):
if crossover(self.rsi, self.upper_bound):
self.position.close()
elif crossover(self.lower_bound, self.rsi):
self.buy()
bt = Backtest(GOOG, RsiOscillator, cash=10_000, commission=.002)
stats = bt.run()
bt.plot()
An issue was opened for this in the GitHub repo:
https://github.com/kernc/backtesting.py/issues/803
A comment in the issue suggests to downgrade bokeh to 2.4.3:
python3 -m pip install bokeh==2.4.3
This worked for me.
I had a similar issue, using Spyder IDE.
Found out I need to call the below for the plot to show for Spyder.
backtesting.set_bokeh_output(notebook=False)
I have update Python to version 3.11 & downgrade bokeh to 2.4.3
This worked for me.
Downgrading Bokeh didn't work for me.
But, after importing backtesting in Jupyter, I needed to do:
backtesting.set_bokeh_output(notebook=False)
The expected plot was then generated in a new interactive browser tab.

Importing sympy and matplotlib.pyplot causes a deprecation warning

This runs fine without any warnings or errors,
from matplotlib import pyplot as plt
plt.plot(range(10))
This,
from matplotlib import pyplot as plt
import sympy
plt.plot(range(10))
Produces,
/home/username/.local/lib/python3.8/site-packages/matplotlib/backends/backend_gtk3.py:327:
DeprecationWarning: Gtk.Window.set_wmclass is deprecated
self.window.set_wmclass("matplotlib", "Matplotlib")
Note that if you import them both but don't call the plot function, you don't get the deprecation warning.
I have no idea what is going on. Googling that warning does not quite find anything related to Sympy. Python is at 3.8.5, Sympy at 1.8 and Matplotlib at 3.4.0.
The message you received is a warning and not an error. The difference being that your code has been executed normally, the message provides extra information that in some point in the future Gtk.Window.set_wmclass will not be available, it's a note to programmers (in this case the matplotlib devs) that they should change their code to use the new way of doing something. If you use a combination of old/new packages you should expect to see these warnings.
You can either ignore/suppress this warning message, or update your packages.
It's recommended that you use a virtual environment to isolate the Python that you use to from the Python that your system uses. It will allow you to use up-to-date versions of packages and you will no longer risk accidentally breaking system utilities. There are many options and since Python ~3.6 there's the venv module included in the standard library.

Why do I have to import a library twice in Python (IDLE and the imported file)?

I am running Python 3.7.6 shell and have the library numpy installed correctly.
In my shell I type:
import numpy as np
and can use numpy however I desire. I then proceed to import 'my_lib.py' which contains:
def softmax(x):
e_x = np.exp(x - np.max(x))
return e_x / e_x.sum(axis=0)
In my shell I can call the function softmax(x) but I immediately get the error
NameError: name 'np' is not defined
My hypothesis here would be I've imported numpy into 'shell scope' and i've also imported softmax(x) into 'shell scope' so everything should be happy. To fix this problem I have to add
import numpy as np
into 'my_lib.py'.
How come I have to import numpy twice?
The code in each module can only use identifiers (names) that have be defined in or imported into that module. The global dict in each module only contains names global to that module. It might better be called the module dict or modular dict, but the name goes back to when there were no modules in computing.
You might benefit from reading https://docs.python.org/3/tutorial/modules.html and probably elsewhere in the tutorial.
(None of this has anything to do with the editor you use to write code or the IDE or shell you use to pass code to Python.)

Not able to find out the version of a module

I have imported norm as:
from scipy.stats import norm
I want to find out the version using:
print(scipy.__version__)
but it is raising an error called:
NameError: name 'scipy' is not defined
if i am using this:
print(norm.__version__)
but it is raising another error called:
AttributeError: 'norm_gen' object has no attribute '__version__'
Please help me to solve this issue.
Thanks
The line from scipy.stats import norm doesn't make the name scipy available in your current namespace. To use scipy.__version__, you must first import scipy.
In [57]: import scipy
In [58]: print(scipy.__version__)
1.4.1

networkx draw graph deprecated message

I am trying to draw a graph networkx using python 3.6 with Jupyter notebook and the network package with anaconda. But the graph is not drawing per the documentation, I am just getting a deprecated message.
CODE:
import networkx as nx
import csv
import matplotlib as plt
G = nx.read_pajek('Hi-tech.net')
nx.draw(G)
MESSAGE:
MatplotlibDeprecationWarning: pyplot.hold is deprecated.
Future behavior will be consistent with the long-time default:
plot commands add elements without first clearing the
Axes and/or Figure.
b = plt.ishold()
Future behavior will be consistent with the long-time default:
plot commands add elements without first clearing the
Axes and/or Figure.
plt.hold(b)
warnings.warn("axes.hold is deprecated, will be removed in 3.0")
To avoid this warning, I just simply replace
nx.draw(G)
by
nx.draw_networkx(G)
My Python is 3.4, Jupyter '1.0.0' and networkx '1.11'.
I was able to get rid of the message by going into the networkx library and simply placing # in front of the lines which produced the error.
I would infer the .hold() function is no longer necessary, nor does it need ot be replaced
I could get nx.draw(G) to work by adding the following line of command:
%matplotlib inline
As error suggest ... I change nx_pylab.py at 611
# if cb.is_numlike(alpha):
if isinstance(alpha,numbers.Number):
I just commented out the line 365 of file __init__.py in Lib\site-packages\matplotlib\cbook which reads
#deprecated('3.0', 'isinstance(..., numbers.Number)')

Resources