0

I have been looking around for a bit have already come across the following related questions: Matplotlib: disable powers of ten in log plot

Prevent axes from being in scientific notation (powers of 10) using matplotlib in Python on semilogy plot

However neither have been able to really help me. I am essentially making a reasonably simple scatter plot with an associated colour map, however I cannot seem to get rid of the power of 10 labelling on the y-axis. Here is my code and the resulting plot. 'teff', 'lum', and 'col1' are all series of dtype('float64'), and I have defined the colourmap 'rvb' in a separate function.

plt.figure(figsize=(12,6))
plt.scatter(teff,lum,s=10,c=col1, cmap=rvb)
plt.yscale('log')
plt.colorbar()
axes = plt.gca()
plt.gca().invert_xaxis()
plt.xlabel('Effective Temperature [K]')
plt.ylabel('Luminosity [L$_{\odot}$]')
plt.show()

Current Scatter Plot

I have tried a few variations of the following solution found in the similar questions

from matplotlib.ticker import ScalarFormatter
ax.get_yaxis().get_major_formatter().set_useOffset(False)

However I just get errors, e.g. 'LogFormatterSciNotation' object has no attribute 'set_useOffset'.

I have also tried to solve the issue using subplots but then I cannot get the colourmap to work. I am hoping for a solution that allows me to keep my plot looking almost identical, just with the powers of 10 changed to actual numbers, and if possible more regular intervals.

Thanks!

qwerty
  • 105
  • 2
  • 8

2 Answers2

1

Here is a working version which uses axes objects:

import matplotlib.pyplot as plt
import matplotlib.cm as cm
import numpy as np

from matplotlib.ticker import ScalarFormatter

x = [i for i in range(10)]
y = [i for i in range(10)]
z =  [i for i in range(20,30)]

fig = plt.figure(figsize=(12,6))
ax = plt.gca()

my_cmap = cm.jet
scatter_plot = ax.scatter(x, y, s=30, cmap=my_cmap, c=z)

m = cm.ScalarMappable(cmap=my_cmap)
m.set_array(np.array(z))
plt.colorbar(m)

ax.set_yscale('log')
ax.set_xlabel('Effective Temperature [K]')
ax.set_ylabel('Luminosity [L$_{\odot}$]')
ax.yaxis.set_major_formatter(ScalarFormatter())

plt.show()

You had the right idea in messing with the formatter: when you set the y axis to logscale, the formatter is switched to LogFormatter, so I switched back to ScalarFormatter.

As for the colorbar, I pass it to the ax.scatter call, and then use this:

m.set_array(np.array(z))
plt.colorbar(m)

In this way, I create a mapping between the z array and the colors: the first value will correspond to the color at the bottom and so on. I pass this to the colorbar along with the z column and that's it. You can find more info here: https://matplotlib.org/3.1.1/api/cm_api.html.

Just one thing: the docs say that the range for the colors (so z here) needs to be in [0,1] typically. Here it works, but you might want to normalize just in case.

EDIT: as @ImportanceOfBeingErnest pointed out, the scatter plot is also scalar mappable, so you can also use this:

scatter_plot.set_array(np.array(z))
plt.colorbar(scatter_plot)
neko
  • 379
  • 1
  • 5
  • Thanks so much, this works almost perfectly. The only issue I appear to be having is that the colorbar is spanning from -0.1 - 0.1, even after normalising. I can't find anything in the docs about it, so was wondering if you had any idea? if you aren't sure of a solution it isn't the end of the world. – qwerty Jul 30 '19 at 16:01
  • 2
    What's the use of the additional `ScalarMappable` here? Why not just use the scatter itself (which is a ScalarMappable to start with), like `plt.colorbar(scatter_plot)`? – ImportanceOfBeingErnest Jul 30 '19 at 23:22
  • @ImportanceOfBeingErnest : I didn't realize that. Updated the answer with your suggestion. – neko Jul 31 '19 at 08:23
  • @qwerty: can you post an example of the data you want to plot? I cannot replicate it – neko Jul 31 '19 at 08:24
  • @neko I am using panda series'. The data I was having issues with was just numbers ranging from -0.3 to 2.7, each associated to a point on the scatter. However the edit/comment has fixed it and now it is working perfectly - thanks! – qwerty Aug 01 '19 at 13:12
-1

Quick solution: You can get the ticks and labels with plt.yticks(), then replace the labels with empty strings. Try adding the following lines:

locs, labels = plt.yticks()
plt.yticks(locs, ['' for label in labels])

Alternatively, change the font color:

plt.tick_params(axis='y', labelcolor='white')
Tarifazo
  • 4,118
  • 1
  • 9
  • 22
  • Thanks for this, however leaving the strings empty results in there being no y-axis information at all, and it stops the ylim from working. There are no labels, and even hovering over the plot gives no y value information. Any idea how to use this but retain the actual y data? – qwerty Jul 30 '19 at 15:31
  • Also try changing the font color (edit); strange however, i don't have any limit problems if I call `plt.yticks(...)` just before `plt.show()`. – Tarifazo Jul 30 '19 at 15:56