4

If I have, for example, these 3 datasets to plot:

a = np.arange(0,10,1)
b = np.arange(2,6,1)
c = np.arange(5,10,1)

and obviously, I don't want them to share the same axis, because some of them would basically just have a big empty graph with a few datapoints somewhere in the corner. So I would ideally have subplots of different sizes, but all with the same scale (i.e. that the step 1 has the same length on all subplots). I know I could do this manually by setting the size of the figure, but for a larger number of datasets or not so nice numbers it would be a real pain. But searching through other questions or the documentation, I couldn't find anything that would, for example, set the fixed distance of ticks on axis or something. Please note that I am not asking about the aspect ratio. The aspect ratio can be different, I just need the same scale on an axis. (See the image below, which hopefully illustrates my problem. Note: no I don't need the scale bar in my actual plot, this is here for you to see how the scale is the same.) Thanks.

updated image

2
  • would axis('scaled') do the job? How should it be implemented? Commented Aug 25, 2016 at 5:23
  • Does stackoverflow.com/a/30266598/3826323 help? Commented Mar 3, 2017 at 11:54

2 Answers 2

2

After doing a lot of research, it looks like there really isn't any simple command to do this. But first, giving a thought of the range of both x and y values of each subplot and their ratios, and the layout, GridSpec will do the job.

So for our example, the layout is as presented in the question, i.e. the biggest picture on top, the two smaller ones next to each other underneath. To make it easier, the y range is the same for all of them (but if it wasn't we would use the same calculations as for x). Now, knowing this layout, we can create a grid. The vertical span is 20 (because we have two rows of 4 plots with y-range 10) and we may want some space between them for axis labels, legend etc., so we'll add extra 5. The first plot has x range of 10, However, the second and third figures have the range of 4 and 5, which is 9 in total, and we may also want some space between them, so let us add 3 extra. So the horizontal grid will span over 12. Hence, we create a grid 25 x 12 and fit our plots in this grid as follows:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import gridspec

## GRIDSPEC INTRO - creating a grid to distribute the subplots with same scales and different sizes.
fig = plt.figure()
gs=gridspec.GridSpec(25,12)
## SUBPLOTS of GRIDSPEC
#the first (big) plot
axes1 = plt.subplot(gs[:10,:10])
ax1 = plt.plot(x,y) # plot some data here
ax1 = plt.xlim(1,10)
ax1 = plt.ylim(1,10)
# the second plot below the big one on the left
axes2 = plt.subplot(gs[15:,:4])
ax2 = plt.plot(x,y) # plot some data here
ax2 = plt.xlim(2,6)
ax2 = plt.ylim(1,10)
# the third plot - below the big one on the right
axes3 = plt.subplot(gs[15:,7:])
ax3 = plt.plot(x,y) # plot some data here
ax3 = plt.xlim(5,10)
ax3 = plt.ylim(1,10)
plt.show()
Sign up to request clarification or add additional context in comments.

Comments

0

Well after an hour:

__author__ = 'madevelasco'

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd


def group(x, max, min, iters):
    total_range = max - min
    for i in range(0, iters):
        if (x > min + i*total_range/iters and x <= min + (i+1)*total_range/iters):
            return i



def newPlots():
    df = pd.DataFrame(np.random.randn(100, 2), columns=['x', 'y'])
    df.plot(x = 'x', y = 'y', kind = 'scatter', alpha=0.5)
    plt.show()

    ##Sort by the column you want
    df.sort_values(['x'], ascending=[False], inplace=True)
    result = df.reset_index(drop=True).copy()

    #Number of groups you want
    iterations = 3
    max_range = df['x'].max()
    min_range = df['x'].min()
    total_range = max_range - min_range

    result['group'] = result.apply(lambda x: group(x['x'], max_range, min_range, iterations ), axis=1)
    print(result)

    for x in range (0, iterations):

        lower = min_range + (x)*total_range/iterations
        upper = min_range + (1+x)*total_range/iterations
        new = result[result['group'] == x]
        new.plot(x = 'x', y = 'y', kind = 'scatter', alpha=0.3)
        axes = plt.gca()
        axes.set_xlim([lower, upper])
        axes.set_ylim([df['y'].min(),df['y'].max()])
        plt.show()

if __name__ == '__main__':
    newPlots()

I used pandas to to this. Honestly, the idea of visualization is to have all data in one graph but not separated like that. To maintain the idea of your date and even for readability, one of the axis should be fixed. I did between edits

Image of all points

General

Sub plots

first subplot

second subplot

third subplot

6 Comments

These axes are all of the same length and sharing the same x axis, but mine do not share anything and are of different lengths. I just want the unit to be same on all axes. So basically on this scale 1-10, I would like "1" to be 1 cm long, and therefore the axis for "a" to be 10 cm long, the axis for "b" be 4 cm long and axis for "c" be 5 cm long. (See updated question.) Thanks
Still not what I am asking for. See the image in my updated question. (xlim and ylim is DIFFERENT for each subplot. So obviously I can change the limits for each of them, but when I do it, the scale of each plot is different. And that is what I am struggling with.)
I think the image of the subplots didn't load properly. There is just an image of one plot. From the code alone I don't see how the grouping could help. Thank you for your effort, but if there isn't a simple command to do it, this overly complicated procedure isn't really worth the effort.
I fixed the images. The group is to spare it on even range parts, not on even sizes. Each group is to assing to which subplot the information will appear
Oh I see what you mean now! No, sorry, I don't want to sort my data based on ranges. I know what I want on each subplot and the RANGE is irrelevant. The ONLY relevant thing is how to make the STEP of ticks on the axis of the same SCALE. Your example doesn't help, because each of the plots has the step of 0.2 in range of 1.6. So obviously they are all the same. Please use my example data to reproduce my problem rather than creating yours which show your desired result.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.