ipython notebook arrange plots horizontally

隐身守侯 提交于 2021-01-20 16:04:40

问题


Currently, when creating two consecutive plots in an ipython notebook, they are displayed one below the other:

enter image description here

I'm wondering if there's any way to have them displayed in rows until the space runs out in the window. So for the first two plots, the output would look like this:

enter image description here

I realize that I can do something similar by arranging subplots in a grid, but I'm wondering if it's possible to do it automatically so that plots are wrapped onto the next 'line' when the space runs out?


回答1:


This works for me in Python 3.5, Jupyter 4.4.0.

The plots "flow around" when you resize the browser window, to fill the horizontal space.

The plots can also be different sizes (try substituting figsize=(3+i/3,2+i/4) - see the second image below)

(Just realised how old this question is; I look periodically for the same thing. I confess the code is cobbled together from other web examples, but I've lost the references now)

import matplotlib.pyplot as plt
import numpy as np
from IPython.display import HTML
import io
import base64


class FlowLayout(object):
    ''' A class / object to display plots in a horizontal / flow layout below a cell '''
    def __init__(self):
        # string buffer for the HTML: initially some CSS; images to be appended
        self.sHtml =  """
        <style>
        .floating-box {
        display: inline-block;
        margin: 10px;
        border: 3px solid #888888;  
        }
        </style>
        """

    def add_plot(self, oAxes):
        ''' Saves a PNG representation of a Matplotlib Axes object '''
        Bio=io.BytesIO() # bytes buffer for the plot
        fig = oAxes.get_figure()
        fig.canvas.print_png(Bio) # make a png of the plot in the buffer

        # encode the bytes as string using base 64 
        sB64Img = base64.b64encode(Bio.getvalue()).decode()
        self.sHtml+= (
            '<div class="floating-box">'+ 
            '<img src="data:image/png;base64,{}\n">'.format(sB64Img)+
            '</div>')

    def PassHtmlToCell(self):
        ''' Final step - display the accumulated HTML '''
        display(HTML(self.sHtml))




oPlot = FlowLayout() # create an empty FlowLayout

# Some fairly regular plotting from Matplotlib
gX = np.linspace(-5,5,100) # just used in the plot example
for i in range(10): # plot 10 charts
    fig, ax = plt.subplots(1, 1, figsize=(3,2)) # same size plots
                           # figsize=(3+i/3,2+i/4)) # different size plots
    ax.plot(gX, np.sin(gX*i)) # make your plot here
    oPlot.add_plot(ax) # pass it to the FlowLayout to save as an image
    plt.close() # this gets rid of the plot so it doesn't appear in the cell


oPlot.PassHtmlToCell()




回答2:


Yes, you can do this:

In [3]: import numpy as np
   ...: xs = np.linspace(0,100,100)
   ...: fig, axs = plt.subplots(nrows=1, ncols=2)
   ...: axs[0].plot(xs, xs * xs)
   ...: axs[1].plot(xs, np.sqrt(xs))
   ...: 

Output:

enter image description here




回答3:


Because the question was posed quite some time ago, I will propose an updated solution for those finding this question via search engines.

Since Jupyter has largely replaced the IPython notebook and Jupyter Lab is planned to replace Jupyter, my solution is implemented in Jupyter Lab 0.35.4.

In this environment, I find it extremely useful to evaluate a cell that reads:

%%html

<style>
    .jp-OutputArea-child {
        display: inline-block;
    }
</style>

This allows for better utilization of vertical space by allowing outputs areas, especially plots, to float side by side. I wish a more refined variant of this were the default behavior.

Browsers are not currently supporting CSS parent selectors, but according to the selectors level 4 working draft, it would be better to use something like the following if browsers start supporting it:

%%html

<style>
    .jp-OutputArea-child:has(> .jp-RenderedImage) {
        display: inline-block;
    }
</style>



回答4:


Pretty sure there isn't away to do so without the subplot or grid plot methods. As for the plot size, you can specify their sizes with something like ax[0].axes([.65, .6, .2, .2]) or plt.subplots(1, 2, figuresize=(12,4)). Unfortunately, this is how matplotlib is setup. If you use the interpreter, you can resize the GUI.



来源:https://stackoverflow.com/questions/21754976/ipython-notebook-arrange-plots-horizontally

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