Changing Index of the axis in a Graph in matplotlib - python

I have written a code which will plot a graph of Time VS Amplitude. Now , I want to change the index which is on the horizontal axis. I want to know how I can do it for a single plot and also for the subplots. I want the range of the horizontal axis to be from 0 to 2*pi.
#the following code was written for plotting
fig, (ax1, ax2 ,ax3) = plt.subplots(3 ,constrained_layout = True)
fig.suptitle('AMPLITUDE MODULATION' ,color = 'Red')
ax1.plot(message_signal)
ax1.set_title('Message Signal' ,color = 'green')
I expect the x-axis to go from 0 to 2*pi only. In short, I want to customize the indexing of the x-axis

You can use xlim to set the limits of the x-axis for whole plot or specific axes, e.g. plt.xlim(0, 1) or ax1.set_xlim(0, 1).
Here I set the limits for the x-axis to be [0, 3*pi]
fig, (ax1, ax2 ,ax3) = plt.subplots(3, constrained_layout = True)
fig.suptitle('AMPLITUDE MODULATION', color = 'Red')
x = np.linspace(0, 2*np.pi, 1000)
ax1.plot(x, np.sin(x))
ax1.set_title('Message Signal', color = 'green')
ax1.set_xlim(0, 3*np.pi)

Related

how to adjust the ticks of the different y axis in one graph to have the same high

Here I plot a bar graph and a line graph in the same figure:
There are 2 y-axes, money and increase_rate, each on a different scale.
How can I set the ticks of the two y-axes to be at the same hight?
import numpy as np
import matplotlib.pyplot as plt
time = [2000,2001,2002,2003]
money = [1000,2000,4000,6000]
increase_rate =[2,1,6,12]
fig, ax1 = plt.subplots()
width = 0.75
ax1.set_xlabel("")
ax1.set_ylabel("")
ax1.bar(time, money ,width = width, color = "#9370DB", alpha=0.6)
ax1.tick_params(axis='y')
ax1.spines['right'].set_visible(False)
ax1.spines['left'].set_visible(False)
ax1.spines['top'].set_visible(False)
ax1.spines['bottom'].set_visible(False)
ax2 = ax1.twinx() # instantiate a second axes that shares the same x-axis
ax2.set_ylabel("")
ax2.plot(time, increase_rate, color = "#FFFF00", lw = 3)
ax2.tick_params(axis='y')
ax2.spines['right'].set_visible(False)
ax2.spines['left'].set_visible(False)
ax2.spines['top'].set_visible(False)
ax2.grid(color='black', linestyle='dotted', linewidth=0.8, alpha = 0.5)
fig.tight_layout() # otherwise the right y-label is slightly clipped
plt.show()
Use the set_yticks to set the tick positions.
ax1.set_yticks(np.linspace(0, max(money), 5))
ax2.set_yticks(np.linspace(0, max(increase_rate), 5))

Python - creating two sharing y axis for double y subplot

Currently, I have the first y axis (probability) of my subplots aligned. However, I am attempting to get the secondary y axis (sample size) of the subplots aligned. I've tried to simply set the y-axis limit, but this solution isn't very generalizable.
Here is my code:
attacks = 5
crit_rate = .5
idealdata = fullMatrix(attacks, crit_rate)
crit_rate = ("crit_%.0f" % (crit_rate*100))
actualdata = trueDataM(attacks, crit_rate)
[enter image description here][1]
fig, axs = plt.subplots(attacks+1, sharex=True, sharey=True)
axs2 = [ax.twinx() for ax in axs]
fig.text(0.5, 0.04, 'State', ha='center')
fig.text(0.04, 0.5, 'Probability', va='center', rotation='vertical')
fig.text(.95, .5, 'Sample Size', va='center', rotation='vertical')
fig.text(.45, .9, 'Ideal vs. Actual Critical Strike Rate', va='center')
cmap = plt.get_cmap('rainbow')
samplesize = datasample(attacks, 'crit_50')
fig.set_size_inches(18.5, 10.5)
for i in range(attacks+1):
axs[i].plot(idealdata[i], color=cmap(i/attacks), marker='o', lw=3)
axs[i].plot(actualdata[i], 'gray', marker='o', lw=3, ls='--')
axs2[i].bar(range(len(samplesize[i])), samplesize[i], width=.1, color=cmap(i/attacks), alpha = .6)
plt.show()
https://i.stack.imgur.com/HKJlE.png
Without data to confirm my assumptions it's hard to tell if this will be correct.
You are not making any attempt to scale the left y-axes so that data must all have the same range. To ensure the right y-axes all have the same scale/limits you need to determine the range (max and min) of the (all) data being plotted on those axes then apply that to all of them.
It isn't clear whether samplesize is a Numpy ndarray or a lists of lists, I'm also assuming that it is a 2-d structure with range(attacks+1) rows. Since you are making bar charts on the second y-axes you only need to find the largest height in all the data.
# for a list of lists
biggest = max(max(row) for row in samplesize)
# or
biggest = max(map(max,samplesize))
# for an ndarray
biggest = samplesize.max()
Then apply that scale to all the right y-axes before they are shown
for ax in axs2:
ax.set_ylim(top=biggest)
If you determine biggest prior to the plot loop you can just add a line to that loop:
for i in range(attacks+1):
...
axs2[i].set_ylim(top=biggest)
You'll find plenty of related SO Q&A'a searching with the terms: matplotlib subplots same y scale, matplotlib subplots y axis limits or something similar.
Here is a toy example:
from matplotlib import pyplot as plt
import numpy as np
lines = np.random.randint(0,200,(5,10))
bars = [np.random.randint(0,np.random.randint(0,10000),10) for _ in (0,0,0,0,0,)]
fig, axs = plt.subplots(lines.shape[0], sharex=True, sharey=True)
axs2 = [ax.twinx() for ax in axs]
#xs = np.arange(lines.shape[1])
xs = np.arange(1,11)
biggest = max(map(max,bars))
for ax,ax2,line,row in zip(axs,axs2,lines,bars):
bars = ax2.bar(xs,row)
ax.plot(line)
ax2.set_ylim(top=biggest)
plt.show()
plt.close()

How to align logarithmic scale ticks across subplots?

I want to fix the position of the ticks on the logarithmic scale, such that they are the same in each subplot (see red annotation in image).
My code looks like this:
ax = fig.add_subplot(2,2, axis)
ax2 = ax.twinx()
ax2.set_yscale('log')
ax2.set_ylim(0,100)
Right now, set_yscale=('log') optimizes the tick spacing for each subplot. I prefer to adopt the tick spacing of the upper right subplot.
You can achieve this by getting the limits of the left twin axis and setting it as the limits of the right twin axis.
Consider the following working example. Follow this procedure for the subplots you want to align the axes of.
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(8, 3))
axl = fig.add_subplot(121)
axr = fig.add_subplot(122)
ax1 = axl.twinx()
ax1.plot(np.logspace(-2, 3, 5))
ax1.set_yscale('log')
ax2 = axr.twinx()
ax2.plot(np.logspace(0, 3, 5))
ax2.set_yscale('log')
ax2.set_ylim(ax1.get_ylim()) # <-- This is the key line
plt.tight_layout()
plt.show()
OP's solution:
Plot a dummy curve and set alpha=0. Make sure the curve spans y_min and y_max.
fig = plt.figure()
axes = [1,2,3,4]
for axis in axes:
ax = fig.add_subplot(2,2, axis)
ax2 = ax.twinx()
ax2.set_yscale('log')
ax2.plot(x_dummy, y_dummy, alpha=0) # <-- dummy plot
x_real, y_real = func_that_loads_data() # <-- your interesting plot
curve1 = ax2.plot(x_real, y_real)
plt.show()
The solution provided by Sheldore was impractical to implement because I plot my data using a for-loop (unavoidable unless I escalate the number of variables).
Since I overwrite the ax variable on every iteration, I would have to save the y-limit as a global variable. Read here why global variables should be avoided.
ax = fig.add_subplot(2,2, axis)
ax2 = ax.twinx()
ax2.set_yscale('log')
if axis == 1:
global yscale
yscale = ax2.get_ylim() # <-- where the magic happens
elif axis > 1:
ax2.set_ylim(yscale)

Python graph x axis frequency control

I want to make the x axis of the graph the same as below.
Ignore the color, I just want the x axis frequency to be in increments of 5.
To get the xticks from the first plot just use:
fig, ax = plt.subplots()
ax = df.plot(kind='bar', stacked=True)
xticks = ax.get_xticklabels()
Then apply it to the other plot with
ax2 = df.plot(...)
ax2.set_xticklabels(xticks)

python/matplotlib/seaborn- boxplot on an x axis with data points

My data set is like this: a python list with 6 numbers [23948.30, 23946.20, 23961.20, 23971.70, 23956.30, 23987.30]
I want them to be be a horizontal box plot above an x axis with[23855 and 24472] as the limit of the x axis (with no y axis).
The x axis will also contain points in the data.
(so the box plot and x axis have the same scale)
I also want the box plot show the mean number in picture.
Now I can only get the horizontal box plot.
(And I also want the x-axis show the whole number instead of xx+2.394e)
Here is my code now:
`
def box_plot(circ_list, wear_limit):
print circ_list
print wear_limit
fig1 = plt.figure()
plt.boxplot(circ_list, 0, 'rs', 0)
plt.show()
`
Seaborn code I am trying right now:
def box_plot(circ_list, wear_limit):
print circ_list
print wear_limit
#fig1 = plt.figure()
#plt.boxplot(circ_list, 0, 'rs', 0)
#plt.show()
fig2 = plt.figure()
sns.set(style="ticks")
x = circ_list
y = []
for i in range(0, len(circ_list)):
y.append(0)
f, (ax_box, ax_line) = plt.subplots(2, sharex=True,
gridspec_kw={"height_ratios": (.15, .85)})
sns.boxplot(x, ax=ax_box)
sns.pointplot(x, ax=ax_line, ay=y)
ax_box.set(yticks=[])
ax_line.set(yticks=[])
sns.despine(ax=ax_line)
sns.despine(ax=ax_box, left=True)
cur_axes = plt.gca()
cur_axes.axes.get_yaxis().set_visible(False)
sns.plt.show()
I answered this question in the other post as well, but I will paste it here just in case. I also added something that I feel might be closer to what you are looking to achieve.
l = [23948.30, 23946.20, 23961.20, 23971.70, 23956.30, 23987.30]
def box_plot(circ_list):
fig, ax = plt.subplots()
plt.boxplot(circ_list, 0, 'rs', 0, showmeans=True)
plt.ylim((0.28, 1.5))
ax.set_yticks([])
labels = ["{}".format(int(i)) for i in ax.get_xticks()]
ax.set_xticklabels(labels)
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.spines['left'].set_color('none')
ax.spines['bottom'].set_position('center')
ax.spines['bottom'].set_color('none')
ax.xaxis.set_ticks_position('bottom')
plt.show()
box_plot(l)
The result:
Do let me know if it correspond to what you were looking for.

Categories

Resources