Controlling tick spacing in log-scale - python

When I apply:
ax.set_yscale('log')
to an axes in matplotlib, it creates a tick for every multiple of 10. Sometimes, this can bee to much, e.g. see screenshot below:
Instead, I would like to have a tick, say, every multiple of 100, or every multiple of 1000, while preserving a logarithmic scaling.
How can I do that in matplotlib?

Just use matplotlib.ticker.LogLocator
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import LogLocator
x = np.linspace(0, 10, 10)
y = 2**x
f = plt.figure()
ax = f.add_subplot(111)
plt.yscale('log')
ax.yaxis.set_major_locator(LogLocator(base=100))
ax.plot(x, y)
plt.show()
And do the same with minor locator if you wish, or adjust it any other way you like.

Related

Overlapping y axis lable in matplotlib

I have these code here to create an xgboost feature importance plot with more than 40 variables :
plot_importance(xgb_model)
plt.show()
However, I got a plot with overlapping y-axis labels and it was hard to read. The figsize=() argument did not seem to work.
Is there a way to make this plot readable?
Definitely go with figsize. You can see that because if you interactively change the window size you observe that the ticks labels d on't overlap anymore.
You can also change the font properties, see https://stackoverflow.com/a/11386056/13636407.
import numpy as np
import matplotlib.pyplot as plt
def plot_sin(figsize):
x = np.linspace(0, 4 * np.pi)
y = np.sin(x)
fig, ax = plt.subplots(figsize=figsize)
ax.plot(x, y)
ax.set_yticks(np.arange(-1.15, 1.15, 0.05))
ax.set_title(f"{figsize = }")
plot_sin(figsize=(12, 4))
plot_sin(figsize=(12, 10))
plt.show()

Seaborn Adjusting Markers

As you can see here, the X axis labels here are quite unreadable. This will happen regardless of how I adjust the figure size. I'm trying to figure out how to adjust the labeling so that it only shows certain points. The X axis are all numerical between -1 to 1, and I think it would be nice and more viewer friendly to have labels at -1, -.5, 0, .5 and 1.
Is there a way to do this? Thank you!
Here's my code
sns.set(rc={'figure.figsize':(20,8)})
ax = sns.countplot(musi['Positivity'])
ax.set_xticklabels(ax.get_xticklabels(), rotation=40, ha='right')
plt.tight_layout()
plt.show()
Basically seaborn is wrapper on matplotlib. You can use matplotlib ticker function to do a Job. Refer the below example.
Let's Plots tick every 1 spacing.
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import seaborn as sns
sns.set_theme(style="whitegrid")
x = [0,5,9,10,15]
y = [0,1,2,3,4]
tick_spacing = 1
fig, ax = plt.subplots(1,1)
sns.lineplot(x, y)
ax.xaxis.set_major_locator(ticker.MultipleLocator(tick_spacing))
plt.show()
Now Let's plot ticks every 5 ticks.
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import seaborn as sns
sns.set_theme(style="whitegrid")
x = [0,5,9,10,15]
y = [0,1,2,3,4]
tick_spacing = 5
fig, ax = plt.subplots(1,1)
sns.lineplot(x, y)
ax.xaxis.set_major_locator(ticker.MultipleLocator(tick_spacing))
plt.show()
P.S.: This solution give you explicit control of the tick spacing via the number given to ticker.MultipleLocater(), allows automatic limit determination, and is easy to read later.

Matplotlib: How can I show only exponents in the y tick labels of a semi-log plot with secondary_yaxis()?

I've been working on matplotlib's secondary-yaxis and I can't figure out how I should set "functions" parameter in order to get the result that I want.
I want to make a semi-log plot and set set the labels of y-ticks in the 2 following formats:
ordinary format such as "10^1, 10^2, 10^3, ..., 10^(exponent), ..."
the exponents only: "1, 2, 3, ..."
And I want to put them in the former style in the y-axis of left side, and the latter right side.
What I want to do can be done by using twinx() like this:
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(1, 3, 41)
y = 10**x
fig, ax1 = plt.subplots()
ax1.set_yscale('log')
ax1.plot(x, y)
ax2 = ax1.twinx()
ymin, ymax = ax1.get_ylim()
ax2.set_ylim(np.log10(ymin), np.log10(ymax))
plt.show()
You would see that i=(1, 2, 3) in the right label is located at the same height as 10^i in the left label.
However, I want to know how to do the same thing by secondary_yaxis. I've tried this but it didn't work.
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(1, 3, 41)
y = 10**x
fig, ax = plt.subplots()
ax.set_yscale('log')
ax.plot(x, y)
def forward(x):
return np.log10(x)
def backward(x):
return 10**x
secax = ax.secondary_yaxis('right', functions=(forward, backward))
plt.show()
It resulted in this:
You can see right-side tick labels are broken. I suspect that my way of setting the parameter "functions" of secondary_yaxis() might be invalid. I would appreciate it if you tell me how to do it.
I get the broken figure on matplotlib 3.1.0. and updating it to 3.3.0. has solved the problem. The same code as the second code block of the question generates this.
enter image description here

Setting the size of the scale factor on Matplotlib with very large/small scales

The following code:
import matplotlib.pyplot as plt
import numpy as np
r = 1e-20
t = np.linspace(0, 2*np.pi, 200)
fig, ax = plt.subplots()
ax.tick_params(axis='x', labelsize=8)
ax.plot(r*np.cos(t), r*np.sin(t))
Produces this:
Look at the "1e-20" on the x-axis. It isn't scaling with the rest of the tick labels. How do I change its fontsize?
Unfortunately, you will need to change the fontsize for the offset text separately:
ax.xaxis.offsetText.set_fontsize(8)

How to plot contourf and my graph in the same figure

I have a figure showing the contourf plot and another showing a plot i've made earlier and I want to plot both on the same figure what should I do?
Here is the code of my contourf plot:
import pylab as pl
from pylab import *
import xlrd
import math
import itertools
from matplotlib import collections as mc
import matplotlib.pyplot as plt
import copy as dc
import pyexcel
from pyexcel.ext import xlsx
import decimal
x_list = linspace(0, 99, 100)
y_list = linspace(0, 99, 100)
X, Y = meshgrid(x_list, y_list, indexing='xy')
Z = [[0 for x in range(len(x_list))] for x in range(len(y_list))]
for each_axes in range(len(Z)):
for each_point in range(len(Z[each_axes])):
Z[len(Z)-1-each_axes][each_point] = power_at_each_point(each_point, each_axes)
figure()
CP2 = contourf(X, Y, Z, cmap=plt.get_cmap('Reds'))
colorbar(CP2)
title('Coverage Plot')
xlabel('x (m)')
ylabel('y (m)')
show()
This is the code of my previously plotted plot:
lc = mc.LineCollection(lines, linewidths=3)
fig, ax = pl.subplots()
ax.add_collection(lc)
ax.autoscale()
ax.margins(0.05)
#The code blow is just for drawing the final plot of the building.
Nodes = xlrd.open_workbook(Node_file_location)
sheet = Nodes.sheet_by_index(0)
Node_Order_Counter = range(1, sheet.nrows + 1)
In_Node_Order_Counter = 0
for counter in range(len(Node_Positions_Ascending)):
plt.plot(Node_Positions_Ascending[counter][0], Node_Positions_Ascending[counter][1], marker='o', color='r',
markersize=6)
pl.text(Node_Positions_Ascending[counter][0], Node_Positions_Ascending[counter][1],
str(Node_Order_Counter[In_Node_Order_Counter]),
color="black", fontsize=15)
In_Node_Order_Counter += 1
#Plotting the different node positions on our plot & numbering them
pl.show()
Without your data we can't see what the plot is supposed to look like, but I have some general recommendations.
Don't use pylab. And if you absolutely must use it, use it within its namespace, and don't do from pylab import *. It makes for very sloppy code - for example, linspace and meshgrid are actually from numpy, but it's hard to tell that when you use pylab.
For complicated plotting, don't even use pyplot. Instead, use the direct object plotting interface. For example, to make a normal plot on top of a contour plot, (such as you want to do) you could do the following:
import numpy as np
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
x = np.linspace(1, 5, 20)
y = np.linspace(2, 5, 20)
z = x[:,np.newaxis] * (y[np.newaxis,:])**2
xx, yy = np.meshgrid(x, y)
ax.contourf(xx, yy, z, cmap='Reds')
ax.plot(x, 0.2*y**2)
plt.show()
Notice that I only used pyplot to create the figure and axes, and show them. The actual plotting is done using the AxesSubplot object.

Categories

Resources