0

I'd like to show the chart below, but with the x-axis on a log scale.

df = pd.DataFrame(np.random.randint(0,100,size=(100, 2)), columns=list('XY'))
sns.jointplot(data=df,x='X',y='Y',height=3,kind='hex')

enter image description here

To be clear, I don't want to log X first, rather I want the numbers to stay the same but the distance between the axis ticks to change. In altair, it would look like the following (I can't do hex in altair, although please correct me if I'm wrong on that):

enter image description here

EDIT: Matt suggested adding xscale="log". That gets me very nearly there. I just need a way to from powers to normal integers.

enter image description here

  • 2
    The Matplotlib `hexbin` function https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.hexbin.html, which seaborn will be using under the hood, seems to accept a `xscale` argument of `log` , so you might just be able to pass `xscale="log"` as another keyword arguement to `jointplot` and it may get passed through to `hexbin`. – Matt Pitkin Jan 26 '23 at 12:14
  • 2
    See https://stackoverflow.com/questions/45419316/matplotlib-figure-with-logarithmic-axis-but-ticks-without-scientific-exponential for the ticks. You need `g = sns.jointplot(...)` and `g.ax_joint.xaxis.set_major_formatter(matplotlib.ticker.ScalarFormatter())` – JohanC Jan 26 '23 at 12:32
  • Or, if you want commas, so that 1000 is 1,000, you could follow, e.g., https://stackoverflow.com/a/46574866/1862861. – Matt Pitkin Jan 26 '23 at 12:57

1 Answers1

2

You can use the xscale="log" keyword argument, which gets passed to the Matplotlib hexbin function that is used under-the-hood by seaborn. E.g.,

sns.jointplot(data=df, x='X', y='Y' ,height=3, kind='hex')

As stated in the comments, there are various ways to set the axis tick labels to not be in scientific format. The simplest is to do:

import matplotlib.ticker as mticker

grid = sns.jointplot(data=df, x='X', y='Y', height=3, kind='hex', xscale="log")
grid.ax_joint.xaxis.set_major_formatter(mticker.ScalarFormatter())

If instead you want, e.g., 1000 to be formatted with a comma so that it is 1,000, you could instead do:

grid.ax_joint.xaxis.set_major_formatter(mticker.StrMethodFormatter("{x:,.0f}"))
Matt Pitkin
  • 3,989
  • 1
  • 18
  • 32