imshow and plot side by side

有些话、适合烂在心里 提交于 2019-12-24 07:14:43

问题


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) = 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)
    plt.show()

which produces:

As you can see, the image has smaller height than the plot. How can I modify my function in order to have the same height for the plot and the imshow?

I want the following placement of the image and the plot:


回答1:


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

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

def visualize(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

def visualize(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

def visualize(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)

    def on_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)


来源:https://stackoverflow.com/questions/45782686/imshow-and-plot-side-by-side

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!