bokeh plotting second axis - how to get limits of primary axis? - python

I have a bokeh plot with date on the x-axis (data["obs_date"]) and I want another x-axis at the top covering the same range but shown in a different format (mjd below).
I have tried to add the second axis with:
plot.extra_x_ranges = {"MJD":
Range1d(start=Time(min(data["obs_date"])).mjd,
end=Time(max(data["obs_date"])).mjd)}
plot.add_layout(LinearAxis(x_range_name="MJD", axis_label="MJD",
axis_label_text_font_size="16pt"),
"above")
However, because bokeh adds a small buffer to the limits of the plot, using min max of data["obs_date"] as the limits for this new axis gives me a small offset - in the image below 16 Jan 2018 should align with 58134. It also causes it to break when I only have one point to plot.
How can I set the limits of my new axis so that it is 'aware' of the limits of the primary axis? Coming form a matplotlib background, I suppose the equivalent I am looking for is ax.get_xlim().

Bokeh implicitly uses DataRange1d that computes the padded bounds based on its range_padding, range_padding_units, and follow_interval fields, and whether the underlying scale is linear or logarithmic. But it does not store the computed values.
So, your only options at this point are either to set the boundaries explicitly for both ranges or to compute the boundaries for the extra range based on the aforementioned DataRange1d fields and the scale type.

Related

Compare stock indices of different sizes Python

I am using Python to try and do some macroeconomic analysis of different stock markets. I was wondering about how to properly compare indices of varying sizes. For instance, the Dow Jones is around 25,000 on the y-axis, while the Russel 2000 is only around 1,500. I know that the website tradingview makes it possible to compare these two in their online charter. What it does is shrink/enlarge a background chart so that it matches the other on a new y-axis. Is there some statistical method where I can do this same thing in Python?
I know that the website tradingview makes it possible to compare these two in their online charter. What it does is shrink/enlarge a background chart so that it matches the other on a new y-axis.
These websites rescale them by fixing the initial starting points for both indices at, say, 100. I.e. if Dow is 25000 points and S&P is 2500, then Dow is divided by 250 to get to 100 initially and S&P by 25. Then you have two indices that start at 100 and you then can compare them side by side.
The other method (works good only if you have two series) - is to set y-axis on the right hand side for one series, and on the left hand side for the other one.
You have multiple possibilities here. Let's say you define your axis by the following call
fig, ax = plt.subplots()
Then, you can change the scale of the y axis to logarithmic using
ax.set_yscale('log')
You can also define two y axes inside the same plot with different scales with the call
ax2 = ax.twinx()
and then plot, let's say, big values on ax and small ones on ax2. That will only work well if you have two ranges of values at most.
Another solution is to create a new axis which zooms inside your plot
from mpl_toolkits.axes_grid1.inset_locator import zoomed_inset_axes
ax2 = zoomed_inset_axes(ax, zoom, bbox_to_anchor=(, ),
bbox_transform=ax.transAxes, loc='', borderpad=)
A last thing would be to directly scale your data. For example, if DowJones varies between 20,000 and 30,000, then you can apply the following transformation
DowJones = (DowJones - min(DowJones)) / (max(DowJones) - min(DowJones))
and then your values will vary between 0 and 1. Applying similar transformations to other variables will then allow you to compare variations more easily on the same graph without making any change to the axes.

Python, Seaborn: Logarithmic Swarmplot has unexpected gaps in the swarm

Let's look at a swarmplot, made with Python 3.5 and Seaborn on some data (which is stored in a pandas dataframe df with column lables stored in another class. This does not matter for now, just look at the plot):
ax = sns.swarmplot(x=self.dte.label_temperature, y=self.dte.label_current, hue=self.dte.label_voltage, data = df)
Now the data is more readable if plotted in log scale on the y-axis because it goes over some decades.
So let's change the scaling to logarithmic:
ax.set_yscale("log")
ax.set_ylim(bottom = 5*10**-10)
Well I have a problem with the gaps in the swarms. I guess they are there because they have been there when the plot is created with a linear axis in mind and the dots should not overlap there. But now they look kind of strange and there is enough space to from 4 equal looking swarms.
My question is: How can I force seaborn to recalculate the position of the dots to create better looking swarms?
mwaskom hinted to me in the comments how to solve this.
It is even stated in the swamplot doku:
Note that arranging the points properly requires an accurate transformation between data and point coordinates. This means that non-default axis limits should be set before drawing the swarm plot.
Setting an existing axis to log-scale and use this for the plot:
fig = plt.figure() # create figure
rect = 0,0,1,1 # create an rectangle for the new axis
log_ax = fig.add_axes(rect) # create a new axis (or use an existing one)
log_ax.set_yscale("log") # log first
sns.swarmplot(x=self.dte.label_temperature, y=self.dte.label_current, hue=self.dte.label_voltage, data = df, ax = log_ax)
This yields in the correct and desired plotting behaviour:

multiple y axes (matplotlib) - unable to define scale increments

Two follow-up questions to a post from yesterday (Multiple Y Axes), is it possible to:
Set the scale increments with ylim or yticks? (so that they line up at 5 steps each)
Change the right Y-axis data to kind='bar' ?
The gridlines do not match up (see image):
Edit: I did not understand that I was plotting in 2D lines by default, so I was trying to change the "kind" as I would in pandas; for example, df.plot(kind='').

Creating ticks in a matplotlib heatmap based on range of values [duplicate]

This question already has answers here:
How to relabel axis ticks for a matplotlib heatmap
(3 answers)
Closed 1 year ago.
I am creating a heatmap in matplotlib where on the x and y axis is some parameter of a measurement and the color represents the value of the measurement. Matplotlib automatically gives the axes ticks based on the index of the value. For example if on the x axis I am measuring at 50 different values the ticks will be from 0 to 50. However the real value of this parameter is for example from -30 to 80 and I would like matplotlib to create the ticks based on this minimum and maximum.
I have tried using set_xticks but this requires the positions of the ticks as well as their labels. I am thinking that I should be able to just give matplotlib a min of -34 and max of 67 and have it create nice looking ticks placed at the proper positions but I haven't been able to find how.
After some digging in examples on the matplotlib website I found this option in imshow called extent in which you can replace the default zero-based coordinates with your own values for the min and max of both axes.
Wouldn't pyplot.xlim() or pyplot.figure.set_xlim() work in this case? Just say something like:
import matplotlib.pyplot as plt
plt.xlim(-30,80)
plt.ylim(0,100) #Or whatever
As far as I know the set_xticks function is too sophisticated for this. With that one you can specify what to put as your tick labels etc. For example if you want to associate a numerical series with a series of letters. For example:
x = [-8,-6,-4,-2,0,2,4,6,8]
labels = ['K2','K4','K6','K8','M0','M2','M4','M6','M8']
plt.xticks(x, labels)
Is one I used personally to translate integers into stellar spectral types (which is relevant, since I'm an astronomer ;p).
Hope this helps.
`

Xaxis Labels not matching Data Points - Pandas/Matplotlib

I have a TimeSeries in Pandas that I want to plot. I have 336 records in the TimeSeries. I only want to show the date/time (index of the TimeSeries) on the x-axis once per every 20 or so data points.
Here is how I am trying to do this:
stats.plot()
ax.set_xticklabels(stats.index, rotation=45 )
ax.xaxis.set_major_locator(MultipleLocator(20))
ax.xaxis.set_minor_locator(NullLocator())
ax.yaxis.set_major_locator(MultipleLocator(.075))
draw()
My x-axis show the correct number of labels (18), but these are the first 18 in the series, they are not correctly corresponding to the datapoints in the plot.
The problem is you are using set_xticklabels which sets the value of the tick labels independent of the data. The ticks are labeled sequentially from the list you pass in.
From this I can't really tell what you are trying to do, but the behavior you are seeing is the 'correct' behavior for the library (it's doing exactly what you told it to, but that isn't what you want it to do).

Categories

Resources