Skip to content Skip to sidebar Skip to footer

Imshow And Plot Side By Side

I'm trying to put side-by-side numpy array displayed as image and seaborn distplot of the same array. I've came up with the following function: def visualize(arr): f, (ax1, ax2

Solution 1:

There are just so many ways to tackle this. All of the following will give more or less the same image

enter image description here

A. Reduce the available space

You may reduce the available space such that both plots are constrained to the same vertical margins. This can be done by

  1. reducing figure height

    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(6,2.3), ...)
    

  2. using subplots_adjust to limit the margins

    fig.subplots_adjust(top=0.7, bottom=0.3)
    

B. Use InsetPosition

You may use mpl_toolkits.axes_grid1.inset_locator.InsetPosition to adjust the coordinates of the second axes to match those of the first one.

import seaborn as sns
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1.inset_locator import InsetPosition

defvisualize(arr):
    fig, (ax1, ax2) = plt.subplots(1, 2,
                               gridspec_kw = {'width_ratios': [1, 3]})

    ax1.imshow(arr)

    flat = arr.flatten()
    x = flat[~np.isnan(flat)]
    sns.distplot(x, ax=ax2)

    ip = InsetPosition(ax1, [1.5,0,3,1]) 
    ax2.set_axes_locator(ip)

    plt.show()

arr = np.random.randn(200,120)
visualize(arr)

C. Use an axes divider

You may create only the axes for the image and then use mpl_toolkits.axes_grid1.make_axes_locatable to create a new axes next to it.

import seaborn as sns
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable

def visualize(arr):
    fig, ax = plt.subplots()
    divider = make_axes_locatable(ax)
    ax2 = divider.new_horizontal(size="300%", pad=0.5)
    fig.add_axes(ax2)

    ax.imshow(arr)

    flat = arr.flatten()
    x = flat[~np.isnan(flat)]
    sns.distplot(x, ax=ax2)

    plt.show()

arr = np.random.randn(200,120)
visualize(arr)

D. calculate the desired aspect ratio

import seaborn as sns
import numpy as np
import matplotlib.pyplot as plt

defvisualize(arr):
    gkw = {'width_ratios':[1, 3] }
    fig, (ax1, ax2) = plt.subplots(1, 2,  gridspec_kw = gkw )

    ax1.imshow(arr)

    flat = arr.flatten()
    x = flat[~np.isnan(flat)]
    sns.distplot(x, ax=ax2)

    ya = np.diff(np.array(ax2.get_ylim()))[0]
    xa = np.diff(np.array(ax2.get_xlim()))[0]
    wa = gkw['width_ratios'][0]/float(gkw['width_ratios'][1])
    ia = arr.shape[0]/float(arr.shape[1])
    ax2.set_aspect(float(wa*ia/(ya/xa)))

    plt.show()

arr = np.random.randn(200,120)
visualize(arr)

E. Dynamically copy positions

You may get the position of the left plot and copy its y-coordinates to the right subplot's position. This is a nice add-on to existing code. The drawback is necessary because subsequent changes to the figure size require to recalculate the positions.

import seaborn as sns
import numpy as np
import matplotlib.pyplot as plt

defvisualize(arr):
    gkw = {'width_ratios':[1, 3] }
    fig, (ax1, ax2) = plt.subplots(1, 2,  gridspec_kw = gkw )

    ax1.imshow(arr)

    flat = arr.flatten()
    x = flat[~np.isnan(flat)]
    sns.distplot(x, ax=ax2)

    defon_resize(evt=None):
        ax1.apply_aspect()
        bb1 = ax1.get_position()
        bb2 = ax2.get_position()
        bb2.y0 = bb1.y0; bb2.y1 = bb1.y1
        ax2.set_position(bb2)

    fig.canvas.mpl_connect("resize_event", on_resize)
    on_resize()

    plt.show()

arr = np.random.randn(200,120)
visualize(arr)

Post a Comment for "Imshow And Plot Side By Side"