first must say, I love the mplfinance, it is a very nice way to display data on the chart.
my problem now is, I cant reduce the space to the borders. There is a parameter calle "tight_layout" but it cuts information off. Probably I do something wrong.
mpf.plot(df_history, show_nontrading=True, figratio=(10,7), figscale=1.5, datetime_format='%d.%m.%y',
xrotation=90, tight_layout=True,
alines=dict(alines=seq_of_points, colors=seq_of_colors, linestyle='-', linewidths=0.5),
type='candle', savefig=bildpfad, addplot=apdict,
update_width_config=dict(candle_linewidth=0.4))
When I use tight_layout=True, it lookes like this:
The space around the chart is perfekt, but the data in the chart is cut off.
and if I use tight_layout=False it uses too much space and the html file created looks crooked.
Does anybody know the right way?
There are a couple of different things you can do to fix this. First, understand the reason why this is happening. The tight_layout algorithm sets the x-axis limits to just outside the limits of your dataframe datetime index, whereas some of your alines points are obviously outside of this range. Given that, there are a few things you can do:
use kwarg xlim=(xmin,xmax) to manually set the x-axis limits that you want.
pad the end of you ohlc dataframe with nan values out to the latest date that you need on your plot.
request a bug fix or enhancement that tight_layout should take alines into account.
HTH.
P.S. Presently xlim only accepts numbers (int or float) that correspond to row numbers in your dataframe (or that correspond to matplotlib dates, see P.P.S. below). I hope to enhance xlim to accept dates sometime soon. In the meantime, try somthing like this:
xmin = 0
xmax = len(df_history)*1.4
mpf.plot(df_history,...,xlim=(xmin,xmax))
P.P.S. I just realized that the above (xmax = len(df_history)*1.4) will work only for show_nontrading=False. However with show_nontrading=True as you have it, you will need to set xmax and xmin differently, as:
import matplotlib.dates as mdates
...
# decide how many days past the end of the data
# that you want the maximum x-axis limit to be:
numdays = 10
# then:
xmin = mdates.date2num(df_history.index[0].to_py_datetime())
xmax = mdates.date2num(df_history.index[-1].to_py_datetime()) + numdays
mpf.plot(df_history,...,xlim=(xmin,xmax))
(notice above they are not both .index[0] but xmax derives from .index[-1])
My apologies that the above work-arounds for xlim are elaborate. This is motivating me even more to finish the xlim enhancement so that users can just pass in a date as a string or datetime. Users of mplfinance should not have to worry about these date conversion details.
Related
I have been working on a dataframe plot, where I have 2k values to show and its indexes. However, when I try to plot them, obviously, matplotlib tries to squeeze all the index labels in the axis, making it impossible to read. It looks like this:
I have tried to increase figsize, but there are just too much xticks. Since the data is not linear (there are maybe 900 values between 0 and 1, 600 values between 1-100 and the rest >100), I cannot just re-arange the xticks with np.arange(), since the data loses correlation (there are 2k bars, but the last index is 1534.34). If I try xticks=np.arange(0, max1, max1/20) to get 20 ticks evenly spaced, I get this result:
Which obviously, is not true, since like I said, the max index is 1534.34, so that the last tick should be at the very end of the horizontal axis. Also, as as said, the first 900 values are between 0 and 1, and this is not true in the plot.
I don't know if I've been clear enough or this question is adequate, but this is my first question and I have tried to. So don't be too harsh please. However all criticism is welcomed. Thanks.
I use ax.xaxis.set_major_locator(ticker.MaxNLocator(interval)) to set my ticks on the x axis after defining the interval as some integer. See documentation here. I think this relies on calling the graph in a form such as:
fig = plt.figure(figsize = (5,2))
ax = fig.add_axes([0, 0, 1, 1])
I am trying to plot this DataFrame which records various amounts of money over a yearly series:
from matplotlib.dates import date2num
jp = pd.DataFrame([1000,2000,2500,3000,3250,3750,4500], index=['2011','2012','2013','2014','2015','2016','2017'])
jp.index = pd.to_datetime(jp.index, format='%Y')
jp.columns = ['Money']
I would simply like to make a bar graph out of this using PyPlot (i.e pyplot.bar).
I tried:
plt.figure(figsize=(15,5))
xvals = date2num(jp.index.date)
yvals = jp['Money']
plt.bar(xvals, yvals, color='black')
ax = plt.gca()
ax.xaxis_date()
plt.show()
But the chart turns out like this:
Only by increasing the width substantially will I start seeing the bars. I have a feeling that this graph is attributing the data to the first date of the year (2011-01-01 for example), hence the massive space between each 'bar' and the thinness of the bars.
How can I plot this properly, knowing that this is a yearly series? Ideally the y-axis would contain only the years. Something tells me that I do not need to use date2num(), since this seems like a very common, ordinary plotting exercise.
My guess as to where I'm stuck is not handling the year correctly. As of now I have them as DateTimeIndex, but maybe there are other steps I need to take.
This has puzzled me for 2 days. All solutions I found online seems to use DataFrame.plot, but I would rather learn how to use PyPlot properly. I also intend to add two more sets of bars, and it seems like the most common way to do that is through plt.bar().
Thanks everyone.
You can either do
jp.plot.bar()
which gives:
or plot against the actual years:
plt.bar(jp.index.year, jp.Money)
which gives:
I have a histogram shown here which I made using the following:
import pylab as pl
fd = FreqDist(list(industries))
X = np.arange(len(fd))
pl.bar(X, fd.values(), align='center', width=0.15)
pl.xticks(X, fd.keys(), rotation=90)
pl.tick_params(labelsize=8)
ymax = max(fd.values()) + 1
pl.ylim(0, ymax)
pl.subplots_adjust(bottom=0.3)
pl.savefig('internalDoorCount.jpg')
However I need the gap to reduce between the y-axis and the first histogram bar. Also how do you prevent overlapping of text?
You can try to avoid overlapping of the text by using this function:
pl.gcf().autofmt_xdate(bottom=0.3, rotation=-30, ha="left")
It's created for rotating date tick labels, but it should work good here. But you most probably have to either reduce the font size, and/or increase the width of your figure.
Assuming pl is matplotlib.pyplot, use pl.xlim. Because I'm not sure what values your x-axis takes, try
pl.xlim(min(X), max(X))
I cannot upvote and I'm amazed how old answers here are still helpful. So, as I still don't have points to comment, I'm answering here to correct a typo from #wflynny and say his answer is simple and works. The actual beginning of the code is "plt", instead of "pl":
plt.xlim(min(x),max(x))
The complete documentation is here.
I am plotting some columns of a csv using Pandas/Matplotlib. The index column is the time in seconds (which has very high number).
For example:
401287629.8
401287630.8
401287631.7
401287632.8
401287633.8
401287634.8
I need this to be printed as my xticklabel when i plot. But it is changing the number format as shown below:
plt.figure()
ax = dfPlot.plot()
legend = ax.legend(loc='center left', bbox_to_anchor=(1,0.5))
labels = ax.get_xticklabels()
for label in labels:
label.set_rotation(45)
label.set_fontsize(10)
I couldn't find a way for the xticklabel to print the exact value rather than shortened version of it.
This is essentially the same problem as How to remove relative shift in matplotlib axis
The solution is to tell the formatter to not use an offset
ax.get_xaxis().get_major_formatter().set_useOffset(False)
Also related:
useOffset=False in config file?
https://github.com/matplotlib/matplotlib/issues/2400
https://github.com/matplotlib/matplotlib/pull/2401
If it's not rude of me to point out, you're asking for a great deal of precision from a single chart. Your sample data shows a six-second difference over two times that are both over twelve and a half-years long.
You have to cut your cloth to your measure on this one. If you want to keep the years, you can't keep the seconds. If you want to keep the seconds, you can't have the years.
I would like to draw a standard 2D line graph with pylot, but force the axes' values to be between 0 and 600 on the x, and 10k and 20k on the y. Let me go with an example...
import pylab as p
p.title(save_file)
p.axis([0.0,600.0,1000000.0,2000000.0])
#define keys and items elsewhere..
p.plot(keys,items)
p.savefig(save_file, dpi=100)
However, the axes still adjust to the size of the data. I'm interpreting the effect of p.axis to be setting what the max and min could be, not enforcing them to be the max or min. The same happens when I try to use p.xlim() etc.
Any thoughts?
Thanks.
Calling p.plot after setting the limits is why it is rescaling. You are correct in that turning autoscaling off will get the right answer, but so will calling xlim() or ylim() after your plot command.
I use this quite a lot to invert the x axis, I work in astronomy and we use a magnitude system which is backwards (ie. brighter stars have a smaller magnitude) so I usually swap the limits with
lims = xlim()
xlim([lims[1], lims[0]])
To answer my own question, the trick is to turn auto scaling off...
p.axis([0.0,600.0, 10000.0,20000.0])
ax = p.gca()
ax.set_autoscale_on(False)
I tried all of those above answers, and I then summarized a pipeline of how to draw the fixed-axes image. It applied both to show function and savefig function.
before you plot:
fig = pylab.figure()
ax = fig.gca()
ax.set_autoscale_on(False)
This is to request an ax which is subplot(1,1,1).
During the plot:
ax.plot('You plot argument') # Put inside your argument, like ax.plot(x,y,label='test')
ax.axis('The list of range') # Put in side your range [xmin,xmax,ymin,ymax], like ax.axis([-5,5,-5,200])
After the plot:
To show the image :
fig.show()
To save the figure :
fig.savefig('the name of your figure')
I find out that put axis at the front of the code won't work even though I have set autoscale_on to False.
I used this code to create a series of animation. And below is the example of combing multiple fixed axes images into an animation.
Try putting the call to axis after all plotting commands.