Remove tick labels but not tick marks but preserve distance beween ticks - python

I want to remove tick labels but keep the tick marks and keep my ticks consistently spaced. I have tried using both ax.tick_params(labelleft='off') and ax.set_yticks(np.arange(0,100,10), " ") but using either of these options rescales my y-axis, and I do not want this to happen.
a1 = plt.subplot(121, adjustable='box')
a1.plot(on[:,0], on[:, 1], linewidth=0, marker=markerz[i], color=kolor[i], ms=mymark)
a1.minorticks_on()
a1.set_yticks(np.arange(0,100,10))
a2 = plt.subplot(122, adjustable='box')
a2.plot(on[:,0], on[:, 1], linewidth=0, marker=markerz[i], color=kolor[i], ms=mymark)
a2.minorticks_on()
a2.tick_params(labelleft='off')
a2.set_yticks(np.arange(0,100,10))
This is what my plot actually looks like. I want certain subplots to share certain axes. I am trying to accomplish that by removing certain tick labels. I want to be able to remove tick labels without rescaling the tick spacing.

You can set empty ticks to your plots like this:
y_ind = np.arange(0,100,10)
plt.yticks(y_ind,['']*len(y_ind))
If you do not want your y-axis to be scaled again, then you can set the y-axis scale:
plt.ylim((y_ind[0],y_ind[-1]))
Here is an example:
import matplotlib.pyplot as plt
import numpy as np
d1 = np.random.rand(100)
d2 = np.random.rand(100)
plt.subplot(2,1,1)
plt.plot(d1)
plt.xticks(np.arange(0,110,10),['']*11)
plt.xlim((0,100))
plt.subplot(2,1,2)
plt.plot(d2)
plt.xticks(np.arange(0,110,10),['']*11)
plt.xlim((0,100))

Related

Puzzling behavior for matplotlib.pyplot yticks([])

I want to suppress pyplot's automatically generated tick labels in favor of my own labels. When I suppress the y-tick labels using pyplot.yticks([]) in the following Python script,
from matplotlib import pyplot as plt
num_points = 10
data = [i for i in range(num_points)]
fig = plt.figure()
ax = plt.subplot(1,1,1)
ax.plot(data)
ax.set_yscale('log')
plt.yticks([])
plt.text(1, 7, '10 data points')
plt.show()
pyplot suppresses y-tick labels, as desired:
But when the num_points is less than ten, pyplot ignores pyplot.yticks([]), inserts its automatically generated tick labels, and produces
When I supply my own tick labels by supplying a list of value and a list of labels, via plt.yticks(values_list, labels_list), pyplot.yticks() accepts my labels, but it still draws its automatically generated tick labels, overwriting my labels.
If I change the nine-point log plot to a linear plot by omitting the ax.set_yscale('log') statement, pyplot does not draw automatically generate tick labels:
The problem appears to be related to log plots with fewer than ten points. How do I suppress the automatically generated tick labels in log plots having fewer than ten points?
When working with a log axis, not only the major ticks but also the minor ticks are shown by default. You can turn them off separately. Note that when there are only very few major ticks, the minor ticks also can get a label.
Also note it usually isn't a good idea to have zero values on a log scale. As log(0) is minus infinity, matplotlib has to do some fragile guesswork about the desired tick distances.
from matplotlib import pyplot as plt
from matplotlib import ticker
num_points = 10
data = [i+2 for i in range(num_points)]
fig = plt.figure()
ax = plt.subplot(1,1,1)
ax.plot(data)
ax.set_yscale('log')
ax.text(1, 7, '10 data points')
ax.yaxis.set_major_locator(ticker.NullLocator())
ax.yaxis.set_minor_locator(ticker.NullLocator())
plt.show()
The image shows the major ticks in blue and the minor ticks in red. As in this example there is only one major tick, some of the minor ticks also got a label.

How to remove a particular grid line corresponding to a custom xtick on a log scale axis?

I'd like to remove the vertical grid line corresponding to the custom xtick (displayed at x = 71 in the below picture). I could remove a horizontal grid line corresponding to the ytick 701 in the below picture by using a hack : since I have no minor tick on the y axis, I defined the custom ytick corresponding to the line that points toward the maximum and crosses the y axis as a minor tick, and then I disabled grid lines for minor ticks on the y axis. Unfortunately I cannot use the same hack on the x axis without disabling the grid lines of the minor ticks and that's something I'd like to avoid at all costs.
Below is a not so minimal albeit still WE.
There are many things I don't understand, the 2 majors are why does
locs, labels = plt.xticks()
not return the locs and labels that are plotted and why I don't get xticks labels displayed as 10^x where x = 0, 1, 2 and 3 but that's outside the scope of the original question.
import matplotlib.pyplot as plt
plt.grid(True)
import numpy as np
# Generate data
x_data = np.arange(1, 1000 , 10)
y_data = np.random.lognormal(1e-5, 3, len(x_data))
y_max = max(y_data)
# plot
plt.xscale('log')
import math
ratio_log = math.log(x_data[np.argmax(y_data)]) / math.log(max(x_data)) # I need to do this in order to plot a horizontal red dashed line that points to the max and do not extend any further.
plt.axhline(y=y_max, xmin=0, xmax = ratio_log, color='r', linestyle='--') # horizontal line pointing to the max y value.
axes = plt.gca()
axes.set_xlim([1, max(x_data)]) # Limits for the x axis.
# custom ticks and labels
# First yticks because I'm able to achieve what I seek
axes.set_yticks([int(y_max)], minor=True) # Sets the custom ytick as a minor one.
from matplotlib.ticker import FormatStrFormatter
axes.yaxis.set_minor_formatter(FormatStrFormatter("%.0f"))
axes.yaxis.grid(False, which='minor') # Removes minor yticks grid. Since I only have my custom yticks as a minor one, this will disable only the grid line corresponding to that ytick. That's a hack.
import matplotlib.ticker as plticker
loc = plticker.MultipleLocator(base=y_max / 3.3) # this locator puts ticks at regular intervals. I ensure the y axis ticks look ok.
axes.yaxis.set_major_locator(loc)
# Now xticks. I'm having a lot of difficulty here, unable to remove the grid of a particular custom xticks.
locs, labels = plt.xticks() # Strangely, this doesn't return the locs and labels that are plotted. There are indeed 2 values that aren't displayed in the plot, here 1.00000000e-01 and 1.00000000e+04. I've got to remove them before I can append my custom loc and label.
# This means that if I do: plt.xticks(locs, labels) right here, it would enlarge both the lower and upper limits on the x axis... I fail to see how that's intuitive or useful at all. Might this be a bug?
locs = np.append(locs[1:-1], np.asarray(x_data[np.argmax(y_data)])) # One of the ugliest hack I have ever seen... to get correct ticks and labels.
labels = (str(int(loc)) for loc in locs) # Just visuals to get integers on the axis.
plt.xticks(locs, labels) # updates the xticks and labels.
plt.plot((x_data[np.argmax(y_data)], x_data[np.argmax(y_data)]), (0, y_max), 'r--') # vertical line that points to the max. Non OO way to do it, so a bad way.
plt.plot(x_data, y_data)
plt.savefig('grid_prob.png')
plt.close()
Example picture below (the code outputs a different picture each time it is executed, but the problem appears in all pictures).
Credit for the idea goes to #ImportanceOfBeingErnest to whom I am extremely grateful.
I removed the grid with
axes.xaxis.grid(False, which='both')
, then I added a grid correspond to each xtick except the custom one with the following loop:
for loc in locs[1:-1]:
if loc != x_data[np.argmax(y_data)]:
plt.axvline(x=loc, color = 'grey', linestyle = '-', linewidth = 0.4)
Insert this code just before the line
plt.xticks(locs, labels) # updates the xticks and labels.
Example of output picture below.

Plotting a second scaled y axis in matplotlib from one set of data

I have two views of the same data, which calls for the need to have another y-axis which is scaled appropriately from the first natural y-axis. So when I plot my {x,y} data, the left y-axis shows y, but the right y-axis also shows 1/y or any other function. I do not ever want to plot {x, f(x)} or {x, 1/y}.
Now to complicate matters I am using the .plt style of interaction rather than the axis method.
plt.scatter(X, Y, c=colours[count], alpha=1.0, label=chart, lw = 0)
plt.ylabel(y_lbl)
plt.xlabel(x_lbl)
Is there another way - with plt? Or is it a case of generating two overlain plots and changing the alpha appropriately?
I had to check your previous (duplicate) question and all the comments to understand what you actually want. So to just get a secondary y-axis you can still use twinx. Then you can use set_ylim make sure it has the same limits as the first. To put tick labels according to some function (in your case 1/y) you can use a custom FuncFormatter.
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.ticker as mticker
fig, ax1 = plt.subplots(1,1)
ax1.set_xlabel('x')
ax1.set_ylabel('y')
# plot something
x = np.linspace(0.01, 10*np.pi, 1000)
y = np.sin(x)/x
ax1.plot(x, y)
# add a twin axes and set its limits so it matches the first
ax2 = ax1.twinx()
ax2.set_ylabel('1/y')
ax2.set_ylim(ax1.get_ylim())
# apply a function formatter
formatter = mticker.FuncFormatter(lambda x, pos: '{:.3f}'.format(1./x))
ax2.yaxis.set_major_formatter(formatter)
plt.show()
Result:

Logarithmically scaled minor tick marks on a matplotlib colorbar?

I'm having some trouble setting up a pcolormesh plot with a colorbar that includes logarithmically spaced minor tick marks on the colorbar.
The closest I've come is something like this:
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
xbins = np.linspace(0, 1, 50)
ybins = np.linspace(0, 1, 50)
data = np.random.random((49,49))
fig, ax = plt.subplots()
im = ax.pcolormesh(xbins, ybins, data, norm=matplotlib.colors.LogNorm())
cb = fig.colorbar(im)
cb.ax.minorticks_on()
plt.savefig('test.png')
The trouble with this solution is that the minor ticks are spaced evenly in log space:
I'd like to set up the plot so I have evenly spaced minor ticks in linear space, which should show up unevenly spaced on this plot.
I know that I can manually set the minor tick labels using a FixedFormatter, but I'd prefer not to do that if possible since I will be making a large number of plots automatically.
I think the best way to custom colorbars' ticks is to use the "ticks" argument of the fig.colorbar method and not trying to modify the attributes of the axe that contains the colorbar.
from matplotlib.ticker import LogLocator
"..."
cb = fig.colorbar(im, ticks = LogLocator(subs=range(10)))
Added for posterity:
From this answer: #JoeKington https://stackoverflow.com/a/20079644/230468:
minorticks = p.norm(np.arange(1, 10, 2))
cb.ax.xaxis.set_ticks(minorticks, minor=True)
This is annoying that you have to create the tick locations manually, but it seems to work.

Combining plt.plot(x,y) with plt.boxplot()

I'm trying to combine a normal matplotlib.pyplot plt.plot(x,y) with variable y as a function of variable x with a boxplot. However, I only want a boxplot on certain (variable) locations of x but this does not seem to work in matplotlib?
Are you wanting something like this? The positions kwarg to boxplot allows you to place the boxplots at arbitrary positions.
import matplotlib.pyplot as plt
import numpy as np
# Generate some data...
data = np.random.random((100, 5))
y = data.mean(axis=0)
x = np.random.random(y.size) * 10
x -= x.min()
x.sort()
# Plot a line between the means of each dataset
plt.plot(x, y, 'b-')
# Save the default tick positions, so we can reset them...
locs, labels = plt.xticks()
plt.boxplot(data, positions=x, notch=True)
# Reset the xtick locations.
plt.xticks(locs)
plt.show()
This is what has worked for me:
plot box-plot
get boxt-plot x-axis tick locations
use box-plot x-axis tick locations as x-axis values for the line plot
# Plot Box-plot
ax.boxplot(data, positions=x, notch=True)
# Get box-plot x-tick locations
locs=ax.get_xticks()
# Plot a line between the means of each dataset
# x-values = box-plot x-tick locations
# y-values = means
ax.plot(locs, y, 'b-')

Categories